diff --git a/Makefile b/Makefile index 5084c408..921bc640 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ endif include $(ONL)/make/config.mk # All available architectures. -ALL_ARCHES := amd64 powerpc armel arm64 +ALL_ARCHES := amd64 powerpc armel arm64 armhf # Build rule for each architecture. define build_arch_template @@ -26,7 +26,7 @@ $(foreach a,$(ALL_ARCHES),$(eval $(call build_arch_template,$(a)))) # Available build architectures based on the current suite BUILD_ARCHES_wheezy := amd64 powerpc BUILD_ARCHES_jessie := amd64 powerpc armel -BUILD_ARCHES_stretch := arm64 amd64 +BUILD_ARCHES_stretch := arm64 amd64 armel armhf # Build available architectures by default. .DEFAULT_GOAL := all diff --git a/REPO/stretch/packages/binary-armhf/Makefile b/REPO/stretch/packages/binary-armhf/Makefile new file mode 100644 index 00000000..6283cc30 --- /dev/null +++ b/REPO/stretch/packages/binary-armhf/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/repo.mk diff --git a/builds/any/installer/grub/builds/Makefile b/builds/any/installer/grub/builds/Makefile index cd392e1a..4092fc27 100644 --- a/builds/any/installer/grub/builds/Makefile +++ b/builds/any/installer/grub/builds/Makefile @@ -11,6 +11,7 @@ include $(ONL)/make/versions/version-onl.mk INSTALLER_NAME=$(FNAME_PRODUCT_VERSION)_ONL-OS_$(FNAME_BUILD_ID)_$(UARCH)_$(BOOTMODE)_INSTALLER MKINSTALLER_OPTS = \ + --onl-version "$(VERSION_STRING)" \ --arch $(ARCH) \ --boot-config boot-config \ --add-dir config \ diff --git a/builds/any/installer/installer.sh.in b/builds/any/installer/installer.sh.in index c5e33f3b..401c4dd4 100644 --- a/builds/any/installer/installer.sh.in +++ b/builds/any/installer/installer.sh.in @@ -19,6 +19,7 @@ if test "$ARCH" != "$IARCH"; then # identify mappings between kernel arch and debian arch case "$IARCH:$ARCH" in armel:armv7l) ;; + armhf:armv7l) ;; arm64:aarch64) ;; powerpc:ppc) ;; *) diff --git a/builds/any/installer/uboot/builds/Makefile b/builds/any/installer/uboot/builds/Makefile index dc3bc4b8..f835ae1d 100644 --- a/builds/any/installer/uboot/builds/Makefile +++ b/builds/any/installer/uboot/builds/Makefile @@ -11,6 +11,7 @@ include $(ONL)/make/versions/version-onl.mk INSTALLER_NAME=$(FNAME_PRODUCT_VERSION)_ONL-OS_$(FNAME_BUILD_ID)_$(UARCH)_$(BOOTMODE)_INSTALLER MKINSTALLER_OPTS = \ + --onl-version "$(VERSION_STRING)" \ --arch $(ARCH) \ --boot-config boot-config \ --add-dir config \ diff --git a/builds/any/rootfs/jessie/common/all-base-packages.yml b/builds/any/rootfs/jessie/common/all-base-packages.yml index df5454a8..bbeab6b4 100644 --- a/builds/any/rootfs/jessie/common/all-base-packages.yml +++ b/builds/any/rootfs/jessie/common/all-base-packages.yml @@ -8,6 +8,8 @@ - python - apt - apt-utils +- debconf +- dialog - procps - net-tools - iputils-ping @@ -78,3 +80,4 @@ - strace - sysstat - ipmitool +- lm-sensors diff --git a/builds/any/rootfs/jessie/common/armel-base-packages.yml b/builds/any/rootfs/jessie/common/armel-base-packages.yml index 71c41a67..6664ed16 100644 --- a/builds/any/rootfs/jessie/common/armel-base-packages.yml +++ b/builds/any/rootfs/jessie/common/armel-base-packages.yml @@ -1 +1,2 @@ - u-boot-tools +- onl-kernel-4.14-lts-armel-iproc-all-modules diff --git a/builds/any/rootfs/stretch/common/all-base-packages.yml b/builds/any/rootfs/stretch/common/all-base-packages.yml index 10b69061..746f5dbf 100644 --- a/builds/any/rootfs/stretch/common/all-base-packages.yml +++ b/builds/any/rootfs/stretch/common/all-base-packages.yml @@ -8,6 +8,8 @@ - python - apt - apt-utils +- debconf +- dialog - procps - net-tools - iputils-ping diff --git a/builds/any/rootfs/stretch/common/armel-base-packages.yml b/builds/any/rootfs/stretch/common/armel-base-packages.yml index 71c41a67..6664ed16 100644 --- a/builds/any/rootfs/stretch/common/armel-base-packages.yml +++ b/builds/any/rootfs/stretch/common/armel-base-packages.yml @@ -1 +1,2 @@ - u-boot-tools +- onl-kernel-4.14-lts-armel-iproc-all-modules diff --git a/builds/any/rootfs/stretch/common/armhf-base-packages.yml b/builds/any/rootfs/stretch/common/armhf-base-packages.yml new file mode 100644 index 00000000..643b4661 --- /dev/null +++ b/builds/any/rootfs/stretch/common/armhf-base-packages.yml @@ -0,0 +1,2 @@ +- u-boot-tools +- onl-kernel-4.14-lts-armhf-iproc-all-modules diff --git a/builds/any/rootfs/stretch/common/armhf-onl-packages.yml b/builds/any/rootfs/stretch/common/armhf-onl-packages.yml new file mode 100644 index 00000000..e58df638 --- /dev/null +++ b/builds/any/rootfs/stretch/common/armhf-onl-packages.yml @@ -0,0 +1,9 @@ +############################################################ +# +# These packages are specific to the ONL root filesystem build. +# +############################################################ +- onl-loader-fit + + + diff --git a/builds/any/rootfs/stretch/standard/standard.yml b/builds/any/rootfs/stretch/standard/standard.yml index 6adb7f1c..6b729e7b 100644 --- a/builds/any/rootfs/stretch/standard/standard.yml +++ b/builds/any/rootfs/stretch/standard/standard.yml @@ -46,12 +46,14 @@ Multistrap: source: http://apt.opennetlinux.org/debian suite: unstable omitdebsrc: true + arches: amd64, arm64, armel ONL-Local: packages: *Packages source: http://${APT_CACHE}apt.opennetlinux.org/debian suite: unstable omitdebsrc: true + arches: amd64, arm64, armel Local-All: source: ${ONLPM_OPTION_REPO}/${ONL_DEBIAN_SUITE}/packages/binary-all diff --git a/builds/any/rootfs/wheezy/common/all-base-packages.yml b/builds/any/rootfs/wheezy/common/all-base-packages.yml index eec465a1..2cf4931e 100644 --- a/builds/any/rootfs/wheezy/common/all-base-packages.yml +++ b/builds/any/rootfs/wheezy/common/all-base-packages.yml @@ -7,6 +7,8 @@ - python - apt - apt-utils +- debconf +- dialog - procps - net-tools - iputils-ping diff --git a/builds/armel/rootfs/builds/Makefile b/builds/armel/rootfs/builds/Makefile index 46d1ce72..a83c7d3e 100644 --- a/builds/armel/rootfs/builds/Makefile +++ b/builds/armel/rootfs/builds/Makefile @@ -4,7 +4,9 @@ include $(ONL)/make/config.armel.mk # Default to include all available powerpc platforms. # You override this with you own list or yaml file. # +ifndef PLATFORM_LIST export PLATFORM_LIST=$(shell onlpm --list-platforms --arch armel --csv ) +endif RFS_CONFIG := $(ONL)/builds/any/rootfs/$(ONL_DEBIAN_SUITE)/standard/standard.yml RFS_DIR := rootfs-armel.d diff --git a/builds/armhf/Makefile b/builds/armhf/Makefile new file mode 100644 index 00000000..435a9dac --- /dev/null +++ b/builds/armhf/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/arch-build.mk diff --git a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/Makefile b/builds/armhf/installer/Makefile similarity index 100% rename from packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/Makefile rename to builds/armhf/installer/Makefile diff --git a/builds/armhf/installer/installed/Makefile b/builds/armhf/installer/installed/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/builds/armhf/installer/installed/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/builds/armhf/installer/installed/PKG.yml b/builds/armhf/installer/installed/PKG.yml new file mode 100644 index 00000000..7ebcf973 --- /dev/null +++ b/builds/armhf/installer/installed/PKG.yml @@ -0,0 +1 @@ +!include $ONL/builds/any/installer/APKG.yml ARCH=armhf BOOTMODE=installed diff --git a/builds/armhf/installer/installed/builds/.gitignore b/builds/armhf/installer/installed/builds/.gitignore new file mode 100644 index 00000000..fbd18542 --- /dev/null +++ b/builds/armhf/installer/installed/builds/.gitignore @@ -0,0 +1 @@ +*INSTALLER diff --git a/builds/armhf/installer/installed/builds/Makefile b/builds/armhf/installer/installed/builds/Makefile new file mode 100644 index 00000000..4d72b17f --- /dev/null +++ b/builds/armhf/installer/installed/builds/Makefile @@ -0,0 +1,3 @@ +BOOTMODE=INSTALLED +include $(ONL)/make/config.armhf.mk +include $(ONL)/builds/any/installer/uboot/builds/Makefile diff --git a/builds/armhf/installer/installed/builds/boot-config b/builds/armhf/installer/installed/builds/boot-config new file mode 100644 index 00000000..76125102 --- /dev/null +++ b/builds/armhf/installer/installed/builds/boot-config @@ -0,0 +1,3 @@ +NETDEV=ma1 +BOOTMODE=INSTALLED +SWI=images::latest diff --git a/builds/armhf/installer/installed/builds/config/README b/builds/armhf/installer/installed/builds/config/README new file mode 100644 index 00000000..3e88e24e --- /dev/null +++ b/builds/armhf/installer/installed/builds/config/README @@ -0,0 +1,2 @@ +This partition contains system configuration data that is persistant across installations and upgrades of ONL-based systems. + diff --git a/builds/armhf/installer/swi/Makefile b/builds/armhf/installer/swi/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/builds/armhf/installer/swi/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/builds/armhf/installer/swi/PKG.yml b/builds/armhf/installer/swi/PKG.yml new file mode 100644 index 00000000..d3e77dcf --- /dev/null +++ b/builds/armhf/installer/swi/PKG.yml @@ -0,0 +1 @@ +!include $ONL/builds/any/installer/APKG.yml ARCH=armhf BOOTMODE=swi diff --git a/builds/armhf/installer/swi/builds/.gitignore b/builds/armhf/installer/swi/builds/.gitignore new file mode 100644 index 00000000..fbd18542 --- /dev/null +++ b/builds/armhf/installer/swi/builds/.gitignore @@ -0,0 +1 @@ +*INSTALLER diff --git a/builds/armhf/installer/swi/builds/Makefile b/builds/armhf/installer/swi/builds/Makefile new file mode 100644 index 00000000..e89cfa99 --- /dev/null +++ b/builds/armhf/installer/swi/builds/Makefile @@ -0,0 +1,3 @@ +BOOTMODE=SWI +include $(ONL)/make/config.armhf.mk +include $(ONL)/builds/any/installer/uboot/builds/Makefile diff --git a/builds/armhf/installer/swi/builds/boot-config b/builds/armhf/installer/swi/builds/boot-config new file mode 100644 index 00000000..bc868161 --- /dev/null +++ b/builds/armhf/installer/swi/builds/boot-config @@ -0,0 +1,3 @@ +NETDEV=ma1 +BOOTMODE=SWI +SWI=images::latest diff --git a/builds/armhf/installer/swi/builds/config/README b/builds/armhf/installer/swi/builds/config/README new file mode 100644 index 00000000..3e88e24e --- /dev/null +++ b/builds/armhf/installer/swi/builds/config/README @@ -0,0 +1,2 @@ +This partition contains system configuration data that is persistant across installations and upgrades of ONL-based systems. + diff --git a/builds/armhf/rootfs/Makefile b/builds/armhf/rootfs/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/builds/armhf/rootfs/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/builds/armhf/rootfs/PKG.yml b/builds/armhf/rootfs/PKG.yml new file mode 100644 index 00000000..2ed460a8 --- /dev/null +++ b/builds/armhf/rootfs/PKG.yml @@ -0,0 +1 @@ +!include $ONL/builds/any/rootfs/APKG.yml ARCH=armhf diff --git a/builds/armhf/rootfs/builds/.gitignore b/builds/armhf/rootfs/builds/.gitignore new file mode 100644 index 00000000..ea55cee3 --- /dev/null +++ b/builds/armhf/rootfs/builds/.gitignore @@ -0,0 +1,2 @@ +*.d/ +manifest.json diff --git a/builds/armhf/rootfs/builds/Makefile b/builds/armhf/rootfs/builds/Makefile new file mode 100644 index 00000000..45c1ea88 --- /dev/null +++ b/builds/armhf/rootfs/builds/Makefile @@ -0,0 +1,16 @@ +include $(ONL)/make/config.armhf.mk + +# +# Default to include all available powerpc platforms. +# You override this with you own list or yaml file. +# +ifndef PLATFORM_LIST +export PLATFORM_LIST=$(shell onlpm --list-platforms --arch armhf --csv ) +endif + +RFS_CONFIG := $(ONL)/builds/any/rootfs/$(ONL_DEBIAN_SUITE)/standard/standard.yml +RFS_DIR := rootfs-armhf.d +RFS_CPIO := rootfs-armhf.cpio.gz +RFS_SQUASH := rootfs-armhf.sqsh + +include $(ONL)/make/rfs.mk diff --git a/builds/armhf/swi/Makefile b/builds/armhf/swi/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/builds/armhf/swi/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/builds/armhf/swi/PKG.yml b/builds/armhf/swi/PKG.yml new file mode 100644 index 00000000..a5cfd1ae --- /dev/null +++ b/builds/armhf/swi/PKG.yml @@ -0,0 +1 @@ +!include $ONL/builds/any/swi/APKG.yml ARCH=armhf diff --git a/builds/armhf/swi/builds/.gitignore b/builds/armhf/swi/builds/.gitignore new file mode 100644 index 00000000..2ddf5f27 --- /dev/null +++ b/builds/armhf/swi/builds/.gitignore @@ -0,0 +1 @@ +manifest.json diff --git a/builds/armhf/swi/builds/Makefile b/builds/armhf/swi/builds/Makefile new file mode 100644 index 00000000..69024332 --- /dev/null +++ b/builds/armhf/swi/builds/Makefile @@ -0,0 +1,3 @@ +ROOTFS_PACKAGE := onl-rootfs +include $(ONL)/make/config.armhf.mk +include $(ONL)/make/swi.mk diff --git a/docker/images/builder8/1.10/Dockerfile b/docker/images/builder8/1.10/Dockerfile new file mode 100644 index 00000000..d729e076 --- /dev/null +++ b/docker/images/builder8/1.10/Dockerfile @@ -0,0 +1,12 @@ +FROM opennetworklinux/builder8:1.9 +MAINTAINER Jeffrey Townsend + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \ + apt-get install linux-perf-4.9 linux-tools-3.16 linux-tools -y + +# +# Docker shell and other container tools. +# +COPY docker_shell /bin/docker_shell +COPY container-id /bin/container-id diff --git a/docker/images/builder8/1.10/Makefile b/docker/images/builder8/1.10/Makefile new file mode 100644 index 00000000..0e19100f --- /dev/null +++ b/docker/images/builder8/1.10/Makefile @@ -0,0 +1,19 @@ +VERSION=1.10 +USER=opennetworklinux +REPO=builder8 + +TOOLS=../../../tools/docker_shell ../../../tools/container-id + +build: check_version + cp $(TOOLS) . + docker build -t $(USER)/$(REPO):$(VERSION) . + rm -rf $(notdir $(TOOLS)) + +# +# Todo: Query remote repository to see if the request version already exists to avoid accidental overwrites +# when a new image is built but the VERSION variable is not updated. +# +check_version: + +push: + docker push $(USER)/$(REPO):$(VERSION) diff --git a/docker/images/builder9/1.3/Dockerfile b/docker/images/builder9/1.3/Dockerfile new file mode 100644 index 00000000..6b4f733c --- /dev/null +++ b/docker/images/builder9/1.3/Dockerfile @@ -0,0 +1,27 @@ +############################################################ +# +# Add armel and armhf +# +############################################################ +FROM opennetworklinux/builder9:1.2 +MAINTAINER Jeffrey Townsend + +RUN dpkg --add-architecture armel +RUN dpkg --add-architecture armhf + +RUN apt-get update && apt-get upgrade -y + +RUN apt-get install -y \ + crossbuild-essential-armel \ + gcc-arm-linux-gnueabi \ + crossbuild-essential-armhf \ + gcc-arm-linux-gnueabi + +RUN xapt -a armel libedit-dev ncurses-dev libsensors4-dev libwrap0-dev libssl-dev libsnmp-dev +RUN xapt -a armhf libedit-dev ncurses-dev libsensors4-dev libwrap0-dev libssl-dev libsnmp-dev + +# +# Docker shell and other container tools. +# +COPY docker_shell /bin/docker_shell +COPY container-id /bin/container-id diff --git a/docker/images/builder9/1.3/Makefile b/docker/images/builder9/1.3/Makefile new file mode 100644 index 00000000..e3d03211 --- /dev/null +++ b/docker/images/builder9/1.3/Makefile @@ -0,0 +1,19 @@ +VERSION=1.3 +USER=opennetworklinux +REPO=builder9 + +TOOLS=../../../tools/docker_shell ../../../tools/container-id + +build: check_version + cp $(TOOLS) . + docker build -t $(USER)/$(REPO):$(VERSION) . + rm -rf $(notdir $(TOOLS)) + +# +# Todo: Query remote repository to see if the request version already exists to avoid accidental overwrites +# when a new image is built but the VERSION variable is not updated. +# +check_version: + +push: + docker push $(USER)/$(REPO):$(VERSION) diff --git a/docker/tools/PKG.yml b/docker/tools/PKG.yml index e1d6d2be..46024abd 100644 --- a/docker/tools/PKG.yml +++ b/docker/tools/PKG.yml @@ -1,6 +1,6 @@ common: arch: all - version: 1.4.0 + version: 1.3.10.0 copyright: Copyright 2013, 2014, 2015 Big Switch Networks maintainer: support@bigswitch.com support: opennetworklinux@googlegroups.com diff --git a/docker/tools/onlbuilder b/docker/tools/onlbuilder index d9cebc3b..8caf9ec5 100755 --- a/docker/tools/onlbuilder +++ b/docker/tools/onlbuilder @@ -18,8 +18,8 @@ g_current_uid = os.getuid() g_timestamp = datetime.datetime.now().strftime("%Y-%m-%d.%H%M%S") g_builder7_image_name="opennetworklinux/builder7:1.2" -g_builder8_image_name="opennetworklinux/builder8:1.9" -g_builder9_image_name="opennetworklinux/builder9:1.2" +g_builder8_image_name="opennetworklinux/builder8:1.10" +g_builder9_image_name="opennetworklinux/builder9:1.3" g_default_image_name=g_builder8_image_name g_default_container_name = "%s_%s" % (g_current_user, g_timestamp) diff --git a/make/config.armhf.mk b/make/config.armhf.mk new file mode 100644 index 00000000..7aba1e5b --- /dev/null +++ b/make/config.armhf.mk @@ -0,0 +1,12 @@ +############################################################ +# +# Open Network Linux +# +############################################################ +include $(ONL)/make/config.mk +export TOOLCHAIN := arm-linux-gnueabihf +export CROSS_COMPILER := $(TOOLCHAIN)- +export ARCH := armhf +export UARCH := ARMHF +export ARCH_BOOT := uboot +export __$(ARCH)__ := 1 diff --git a/make/dtbs.mk b/make/dtbs.mk index 48753f1b..dd8b27d1 100644 --- a/make/dtbs.mk +++ b/make/dtbs.mk @@ -13,14 +13,30 @@ ifndef DTB_LIST DTB_LIST := $(patsubst %.dts,%.dtb,$(DTS_LIST)) endif -%.dtb: %.dts - $(ONL)/tools/dtc -I dts -O dtb -o $@ $< +ifndef DTC + ifdef KERNEL + DTC := $(shell $(ONLPM) --find-file $(KERNEL) dtc) + ifeq ($(DTC),) + $(error No device tree compiler.) + endif + else + DTC := $(ONL)/tools/dtc + endif +endif -.DEFAULT_GOAL := $(DTB_LIST) +%.dtb: %.dts + cpp -nostdinc -undef -x assembler-with-cpp $(foreach inc,$(INCLUDES),-I$(inc) ) $< > $(notdir $<).i + $(DTC) $(foreach inc,$(INCLUDES),-i$(inc) ) $(DTC_OPTIONS) -I dts -O dtb -o $@ $(notdir $<).i + rm $(notdir $<).i + +.DEFAULT_GOAL := dtbs + +dtbs: $(DTB_LIST) + echo $(DTB_LIST) $(VPATH) + $(MAKE) setup-clean $(DTB_LIST): setup clean:: - rm -rf *.dtb - setup:: +setup-clean:: diff --git a/make/kbuild.mk b/make/kbuild.mk index 12052db8..8be2961b 100644 --- a/make/kbuild.mk +++ b/make/kbuild.mk @@ -174,7 +174,7 @@ endif MODSYNCLIST_DEFAULT := .config Module.symvers Makefile include scripts drivers \ arch/x86/include arch/x86/Makefile \ arch/powerpc/include arch/powerpc/Makefile arch/powerpc/lib arch/powerpc/boot/dts \ - arch/arm/include arch/arm/Makefile arch/arm/lib arch/arm/boot/dts + arch/arm/include arch/arm/Makefile arch/arm/lib arch/arm/boot/dts arch/arm/kernel MODSYNCLIST := $(MODSYNCLIST_DEFAULT) $(MODSYNCLIST_EXTRA) $(K_MODSYNCLIST) diff --git a/make/kmodule.mk b/make/kmodule.mk index aa84a07c..e87225a8 100644 --- a/make/kmodule.mk +++ b/make/kmodule.mk @@ -26,4 +26,4 @@ endif modules: rm -rf lib - ARCH=$(ARCH) $(ONL)/tools/scripts/kmodbuild.sh "$(KERNELS)" "$(KMODULES)" "$(SUBDIR)" + ARCH=$(ARCH) $(ONL)/tools/scripts/kmodbuild.sh "$(KERNELS)" "$(KMODULES)" "$(SUBDIR)" "$(KINCLUDES)" diff --git a/make/pkg.mk b/make/pkg.mk index 2589308e..98d9dfd6 100644 --- a/make/pkg.mk +++ b/make/pkg.mk @@ -14,7 +14,7 @@ include $(ONL)/make/config.mk # directory tree. # ifndef ARCHES -ARCHES := amd64 powerpc armel arm64 all +ARCHES := amd64 powerpc armel armhf arm64 all endif ONLPM_ENVIRONMENT = \ diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/ifup b/packages/base/all/initrds/loader-initrd-files/src/bin/ifup index 453a55c9..103318a5 100644 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/ifup +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/ifup @@ -44,18 +44,21 @@ if [ "${NETHW}" ]; then ip link set dev ${NETDEV} addr ${NETHW} fi -# Default DHCP timeout is 10 requests in 10 seconds. -NETRETRIES_DEFAULT=10 -NETRETRIES=${NETRETRIES:-$NETRETRIES_DEFAULT} -if [ "$NETRETRIES" = "infinite" ]; then - NETRETRIES= -elif [ $(echo "$NETRETRIES" | tr -d '[:digit:]') ] || [ "$NETRETRIES" -lt 0 ]; then - echo "Warning: the NETRETRIES setting is currently '$NETRETRIES'. This is invalid and the default value of $NETRETRIES_DEFAULT will be used instead." - NETRETRIES=$NETRETRIES_DEFAULT -fi case "${NETAUTO}" in dhcp|auto) + # Default DHCP timeout is 10 requests in 10 seconds. + NETRETRIES_DEFAULT=10 + NETRETRIES=${NETRETRIES:-$NETRETRIES_DEFAULT} + if [ "$NETRETRIES" = "infinite" ]; then + NETRETRIES= + elif [ $(echo "$NETRETRIES" | tr -d '[:digit:]') ] || [ "$NETRETRIES" -lt 0 ]; then + echo "Warning: the NETRETRIES setting is currently '$NETRETRIES'." + echo "This is invalid and the default value of $NETRETRIES_DEFAULT will be used instead." + NETRETRIES=$NETRETRIES_DEFAULT + fi + echo 1 >/proc/sys/net/ipv6/conf/${NETDEV}/autoconf + if [ -n "${NETRETRIES}" ]; then if ! udhcpc --retries $NETRETRIES --now -i ${NETDEV}; then echo "**********************************************************************" @@ -81,6 +84,9 @@ case "${NETAUTO}" in up) ifconfig "${NETDEV}" up ;; + none) + exit 0 + ;; *) if [ "${NETIP}" ] && [ "${NETMASK}" ] && [ "${NETIP#*/}" = "${NETIP}" ]; then NETIP=${NETIP}/$(ipcalc -p -s ${NETIP} ${NETMASK} | sed -n 's/PREFIX=//p') @@ -118,6 +124,7 @@ for i in $(seq 30); do fi sleep 1 done + wait_link_up() { local intf=$1 @@ -144,4 +151,5 @@ wait_link_up() if [ -n "${NETAUTO}" ]; then wait_link_up $NETDEV 100 fi -return 0 + +exit 0 diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/initrng.py b/packages/base/all/initrds/loader-initrd-files/src/bin/initrng.py new file mode 100644 index 00000000..4d33ed11 --- /dev/null +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/initrng.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python + +""" +Distributed under MIT License. +See LICENSE file for full license text. +""" + +import fcntl +import struct +import sys +import os +import hashlib +import logging +import argparse + +RNDADDENTROPY = 0x40085203 # from linux/random.h + +def sha512sum(digest, fileName, blockSize = 16 * 1024): + """ + Take SHA512 digest from file given by it's name contents. + + File opened in os.O_NONBLOCK mode to support FIFOs and + special files like /dev/kmsg. Read data from files in + blockSize (default 16kB) chunks to keep memory usage at + minimum when used with large files. + + Return True on success and False otherwise. + """ + + def read(): + try: + return fp.read(blockSize) + except IOError: + return b'' + #end def + + if digest is None: + return False + + try: + fp = open(fileName, 'rb') + except IOError: + return False + + flags = fcntl.fcntl(fp, fcntl.F_GETFL) | os.O_NONBLOCK + if fcntl.fcntl(fp, fcntl.F_SETFL, flags): + fp.close() + return False + + for block in iter(read, b''): + digest.update(block) + + fp.close() + return True + +def sha512(digest, fileName): + """ + Computes sha512sum() optionally logging status. + + For internal use only. + + Return 1 on success and 0 on failure. + """ + + rc = sha512sum(digest, fileName) + logging.debug("SHA512 (%s) = %s", fileName, 'ok' if rc else 'fail') + return int(rc) + +def add_entropy(digest, fileName = "/dev/urandom"): + """ + Adds digest.digest_size * 8 bits of entropy using ioctl(RNDADDENTROPY, ...) + to increase entropy count if fileName is a character special file node and + CAP_SYS_ADMIN is available (otherwise IOError is raised by fnctl.fnctl()). + + Writes entropy to fileName if IOError exception is raised by fnctl.fnctl() + or fileName is a regular file. Update entropy pool without incrementing + entropy count if fileName is special character device like "/dev/urandom". + """ + + try: + fp = open(fileName, 'ab') + except IOError as e: + return None, str(e) + + size = digest.digest_size + digest = digest.digest() + + method = None + err = None + + do_ioctl = not os.path.isfile(fileName) + + try: + if do_ioctl: + # from random(4): + # + # struct rand_pool_info { + # int entropy_count; + # int buf_size; + # __u32 buf[0]; + # }; + # + fmt = "ii{:d}s".format(size) + rand_pool_info = struct.pack(fmt, size * 8, size, digest) + fcntl.ioctl(fp, RNDADDENTROPY, rand_pool_info) + else: + raise IOError() + except IOError: + try: + fp.write(digest) + except IOError as e: + err = str(e) + else: + method = "write" + else: + method = "ioctl" + + return method, err + +def init(): + prog_name = os.path.splitext(os.path.basename(__file__))[0] + if not prog_name: + prog_name = "initrng" + + parser = argparse.ArgumentParser(description = 'Linux RNG early init') + + # loglevel + loglevels = { + 'crit' : 'CRITICAL', + 'err' : 'ERROR', + 'warn' : 'WARNING', + 'info' : 'INFO', + 'debug': 'DEBUG', + } + parser.add_argument('-l', '--loglevel', default = 'info', + choices = list(loglevels.keys()), + help = 'set program loging severity (level)') + + # entropy_files + dflt_entropy_files = [ + "/proc/timer_list", + "/proc/buddyinfo", + "/proc/interrupts", + "/proc/softirqs", + ] + + sched_debug = "/proc/sched_debug" + if os.path.isfile(sched_debug): + dflt_entropy_files.append(sched_debug) + else: + dflt_entropy_files.append("/proc/schedstat") + + parser.add_argument('-e', '--entropy-file', default = [], + action = 'append', dest = 'entropy_files', type = str, + help = 'files to use as source of entropy ({:s})'.format(', '.join(dflt_entropy_files))) + + # repeat + dflt_repeat = 8 + parser.add_argument('-r', '--repeat', default = dflt_repeat, + action = 'store', type = int, + help = 'repeat entropy updates # times (default {:d})'.format(dflt_repeat)) + + # output + dflt_output = "/dev/urandom" + parser.add_argument('-o', '--output', default = dflt_output, + action = 'store', type = str, + help = 'file to output entropy (default "{:s}")'.format(dflt_output)) + + args = parser.parse_args() + + logging.basicConfig(format = "{:s}: %(message)s".format(prog_name), + level = getattr(logging, loglevels[args.loglevel])) + + # adjust entropy_files + if not args.entropy_files: + args.entropy_files = dflt_entropy_files + logging.debug("using default list of files as entropy source") + + # adjust repeat + repeat = args.repeat + + if repeat <= 0: + repeat = 1 + elif repeat > 65536: + repeat = 65536 + + if repeat != args.repeat: + logging.debug("adjust repeat count from %d to %d", args.repeat, repeat) + args.repeat = repeat + + # truncate entropy file + output = args.output + try: + with open(output, 'wb'): + pass + except IOError: + logging.debug("entropy file '%s' isn't writable", output) + args = None + else: + logging.debug("entropy file '%s' is writable", output) + + return args + +if __name__ == '__main__': + args = init() + + if args is None: + logging.debug("fail to adjust/validate args") + sys.exit(1) + + logging.info("Linux Random Number Generator (RNG) early init") + + entropy_files = args.entropy_files + repeat = args.repeat + + for x in range(1, repeat + 1): + digest_sha512 = hashlib.sha512() + + i = 0 + for f in entropy_files: + i += sha512(digest_sha512, f) + if not i: + logging.debug("digest error for all entropy files, step %d", x) + continue + + method, err = add_entropy(digest_sha512, args.output) + if err: + logging.debug("error seeding Linux RNG, step %d: %s", x, err) + else: + logging.debug("seeded Linux RNG, method '%s', step %d", method, x) diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/swiprep b/packages/base/all/initrds/loader-initrd-files/src/bin/swiprep index 88cb76c6..d5a72f8e 100755 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/swiprep +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/swiprep @@ -138,7 +138,7 @@ case $(uname -m) in ARCH_LIST="x86_64 amd64" ;; armv7l) - ARCH_LIST="armel" + ARCH_LIST="armel armhf" ;; aarch64) ARCH_LIST="arm64" diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit b/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit index 9d869beb..dee91f07 100755 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit @@ -47,8 +47,10 @@ case "$(stat -f -c "%T" /tmp)" in ;; esac -# Grab cmdline settings +# Initialize RNG early +python /bin/initrng.py +# Grab cmdline settings touch /etc/onl/boot-config tr -s " " "\n" >> %s", line) + + if ex and code: + self.logger.error("Command failed with code %s", code) + raise subprocess.CalledProcessError(code, cmd) + + return code def _raise(self, msg, klass): self.logger.critical(msg) @@ -89,3 +121,36 @@ def dmerge(d1, d2): q.append((v1, v2, c3[k],)) return merged + + +def wget(url, directory=None, temp_directory=None, extension=None): + + import urllib2 + import tempfile + + try: + response = urllib2.urlopen(url) + filename = os.path.basename(urllib2.urlparse.urlparse(response.url).path) + except Exception, e: + return (e, None, None) + + if extension and not filename.endswith("%s" % extension): + return (ValueError("The requested filename does not have the correct extension (%s)" % extension), None, None) + + if directory is None: + directory = tempfile.mkdtemp(dir=temp_directory) + + if os.path.exists(os.path.join(directory, filename)): + return (ValueError("The requested filename already exists in the target directory."), None, None) + + try: + subprocess.check_call("wget -P %s %s" % (directory, url), shell=True) + return (None, filename, directory) + except subprocess.CalledProcessError, e: + return (e, None, None) + +def dpkg_architecture(): + try: + return subprocess.check_output(['/usr/bin/dpkg', '--print-architecture']).strip() + except (subprocess.CalledProcessError, OSError): + return None diff --git a/packages/base/any/fit/loader/builds/Makefile b/packages/base/any/fit/loader/builds/Makefile index f257e3b8..840f6fa7 100644 --- a/packages/base/any/fit/loader/builds/Makefile +++ b/packages/base/any/fit/loader/builds/Makefile @@ -4,7 +4,7 @@ endif .PHONY: onl-loader-fit.itb onl-loader-fit.its -onl-loader-fit.itb: +onl-loader-fit.itb: its $(ONL)/tools/flat-image-tree.py --initrd onl-loader-initrd:$(ARCH),onl-loader-initrd-$(ARCH).cpio.gz --arch $(ARCH) --add-platform initrd --itb $@ $(ONLPM) --copy-file onl-loader-initrd:$(ARCH) manifest.json . diff --git a/packages/base/any/kernels/3.16-lts/patches/drivers-mfd-lpc_ich.patch b/packages/base/any/kernels/3.16-lts/patches/drivers-mfd-lpc_ich.patch new file mode 100644 index 00000000..cc84b9b6 --- /dev/null +++ b/packages/base/any/kernels/3.16-lts/patches/drivers-mfd-lpc_ich.patch @@ -0,0 +1,12 @@ +Index: linux-3.16.39/drivers/mfd/lpc_ich.c +=================================================================== +--- linux-3.16.39.orig/drivers/mfd/lpc_ich.c ++++ linux-3.16.39/drivers/mfd/lpc_ich.c +@@ -493,6 +493,7 @@ static struct lpc_ich_info lpc_chipset_i + [LPC_LPT] = { + .name = "Lynx Point", + .iTCO_version = 2, ++ .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT_LP] = { + .name = "Lynx Point_LP", diff --git a/packages/base/any/kernels/3.16-lts/patches/series b/packages/base/any/kernels/3.16-lts/patches/series index 72485e2d..68e43b02 100644 --- a/packages/base/any/kernels/3.16-lts/patches/series +++ b/packages/base/any/kernels/3.16-lts/patches/series @@ -29,3 +29,4 @@ driver-igb-netberg-aurora.patch driver-hid-cp2112-mods.patch gcc-no-pie.patch driver-ixgbe-version-5.2.4.patch +drivers-mfd-lpc_ich.patch diff --git a/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/.gitignore b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/.gitignore new file mode 100644 index 00000000..285a565e --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/.gitignore @@ -0,0 +1,2 @@ +linux-4.14* +kernel-4.14* diff --git a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/Makefile b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/Makefile similarity index 87% rename from packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/Makefile rename to packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/Makefile index b3fcbd82..7c708593 100644 --- a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/Makefile +++ b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/Makefile @@ -1,4 +1,4 @@ -############################################################ +########################################################### # # # Copyright 2015 Big Switch Networks, Inc. @@ -29,13 +29,14 @@ endif K_PATCH_DIR := $(THIS_DIR)/patches include ../../kconfig.mk -K_CONFIG := arm-iproc-all.config +K_CONFIG := armel-iproc-all.config K_BUILD_TARGET := Image K_COPY_SRC := arch/arm/boot/Image K_COPY_GZIP := 1 ifndef K_COPY_DST -K_COPY_DST := kernel-4.4-lts-arm-iproc-all.bin.gz +K_COPY_DST := kernel-4.14-lts-armel-iproc-all.bin.gz endif export ARCH=arm + include $(ONL)/make/kbuild.mk diff --git a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/armel-iproc-all.config similarity index 80% rename from packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/arm-iproc-all.config rename to packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/armel-iproc-all.config index b1a38f03..d98fb16a 100644 --- a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/arm-iproc-all.config +++ b/packages/base/any/kernels/4.14-lts/configs/armel-iproc-all/armel-iproc-all.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.39 Kernel Configuration +# Linux/arm 4.14.49 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -30,8 +30,8 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="arm-linux-gnueabi-" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCALVERSION="-OpenNetworkLinux-armel" +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_XZ=y @@ -48,7 +48,7 @@ CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set CONFIG_CROSS_MEMORY_ATTACH=y -# CONFIG_FHANDLE is not set +CONFIG_FHANDLE=y CONFIG_USELIB=y # CONFIG_AUDIT is not set CONFIG_HAVE_ARCH_AUDITSYSCALL=y @@ -59,14 +59,18 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y CONFIG_HANDLE_DOMAIN_IRQ=y -# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_ARCH_HAS_TICK_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y @@ -97,15 +101,16 @@ CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_PREEMPT_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_SRCU=y -# CONFIG_TASKS_RCU is not set +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU=y CONFIG_RCU_STALL_COMMON=y -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 +CONFIG_LOG_BUF_SHIFT=17 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 CONFIG_GENERIC_SCHED_CLOCK=y # CONFIG_CGROUPS is not set # CONFIG_CHECKPOINT_RESTORE is not set @@ -113,9 +118,18 @@ CONFIG_GENERIC_SCHED_CLOCK=y # CONFIG_SCHED_AUTOGROUP is not set # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_HAVE_UID16=y CONFIG_BPF=y CONFIG_EXPERT=y @@ -124,20 +138,25 @@ CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set CONFIG_SYSFS_SYSCALL=y CONFIG_SYSCTL_SYSCALL=y +CONFIG_POSIX_TIMERS=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y CONFIG_BUG=y -# CONFIG_ELF_CORE is not set -# CONFIG_BASE_FULL is not set +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y # CONFIG_BPF_SYSCALL is not set -# CONFIG_SHMEM is not set -# CONFIG_AIO is not set +CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_ADVISE_SYSCALLS=y # CONFIG_USERFAULTFD is not set CONFIG_PCI_QUIRKS=y @@ -145,6 +164,7 @@ CONFIG_MEMBARRIER=y CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_USE_VMALLOC=y +# CONFIG_PC104 is not set # # Kernel Performance Events And Counters @@ -156,6 +176,9 @@ CONFIG_VM_EVENT_COUNTERS=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SYSTEM_DATA_VERIFICATION is not set # CONFIG_PROFILING is not set @@ -169,11 +192,12 @@ CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_NMI=y CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y @@ -182,20 +206,39 @@ CONFIG_HAVE_PERF_USER_STACK_DUMP=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_GCC_PLUGINS=y +# CONFIG_GCC_PLUGINS is not set CONFIG_HAVE_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR is not set CONFIG_CC_STACKPROTECTOR_NONE=y # CONFIG_CC_STACKPROTECTOR_REGULAR is not set # CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_THIN_ARCHIVES=y CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_REL=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_HAVE_EXIT_THREAD=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_BITS=8 +# CONFIG_HAVE_ARCH_HASH is not set +# CONFIG_ISA_BUS_API is not set CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y +# CONFIG_CPU_NO_EFFICIENT_FFS is not set +# CONFIG_HAVE_ARCH_VMAP_STACK is not set +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +# CONFIG_REFCOUNT_FULL is not set # # GCOV-based kernel profiling @@ -204,7 +247,7 @@ CONFIG_OLD_SIGACTION=y CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=1 +CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y @@ -213,12 +256,18 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_MODULE_SIG is not set # CONFIG_MODULE_COMPRESS is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_BLOCK=y CONFIG_LBDAF=y +CONFIG_BLK_SCSI_REQUEST=y CONFIG_BLK_DEV_BSG=y # CONFIG_BLK_DEV_BSGLIB is not set # CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_ZONED is not set # CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set # # Partition Types @@ -243,6 +292,7 @@ CONFIG_MSDOS_PARTITION=y CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set # CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLK_MQ_PCI=y # # IO Schedulers @@ -254,6 +304,9 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y CONFIG_MUTEX_SPIN_ON_OWNER=y @@ -266,10 +319,6 @@ CONFIG_FREEZER=y # CONFIG_MMU=y CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -279,9 +328,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set @@ -289,7 +335,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C24XX is not set -# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set @@ -306,7 +351,9 @@ CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_ARCH_MULTI_CPU_AUTO is not set # CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ACTIONS is not set # CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_ARTPEC is not set # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BERLIN is not set @@ -318,13 +365,15 @@ CONFIG_ARCH_XGS_IPROC=y # # XGS iProc SoC based Machine types # -CONFIG_MACH_HX4=y +CONFIG_XGS_IPROC_ARM32_PLATFORM=y +# CONFIG_MACH_HX4 is not set # CONFIG_MACH_HR2 is not set # CONFIG_MACH_KT2 is not set # CONFIG_MACH_GH is not set # CONFIG_MACH_SB2 is not set # CONFIG_MACH_HR3 is not set # CONFIG_MACH_GH2 is not set +# CONFIG_MACH_WH2 is not set # CONFIG_MACH_IPROC_EMULATION is not set # CONFIG_ARCH_KEYSTONE is not set # CONFIG_ARCH_MESON is not set @@ -340,16 +389,19 @@ CONFIG_MACH_HX4=y # CONFIG_SOC_AM33XX is not set # CONFIG_SOC_AM43XX is not set # CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_ROCKCHIP is not set # CONFIG_ARCH_SOCFPGA is not set # CONFIG_PLAT_SPEAR is not set # CONFIG_ARCH_STI is not set # CONFIG_ARCH_S5PV210 is not set # CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_RENESAS is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TANGO is not set # CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_UNIPHIER is not set # CONFIG_ARCH_U8500 is not set @@ -362,6 +414,7 @@ CONFIG_MACH_HX4=y # Processor Type # CONFIG_CPU_V7=y +CONFIG_CPU_THUMB_CAPABLE=y CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y CONFIG_CPU_ABRT_EV7=y @@ -401,7 +454,7 @@ CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_HEAVY_MB=y CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -# CONFIG_ARM_KERNMEM_PERMS is not set +CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_643719 is not set @@ -412,6 +465,11 @@ CONFIG_ARM_ERRATA_764369=y CONFIG_ARM_ERRATA_775420=y # CONFIG_ARM_ERRATA_798181 is not set # CONFIG_ARM_ERRATA_773022 is not set +# CONFIG_ARM_ERRATA_818325_852422 is not set +# CONFIG_ARM_ERRATA_821420 is not set +# CONFIG_ARM_ERRATA_825619 is not set +# CONFIG_ARM_ERRATA_852421 is not set +# CONFIG_ARM_ERRATA_852423 is not set # # Bus support @@ -420,23 +478,41 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS_GENERIC=y CONFIG_PCI_SYSCALL=y +# CONFIG_PCIEPORTBUS is not set CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_REALLOC_ENABLE_AUTO is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCI_PRI is not set # CONFIG_PCI_PASID is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# DesignWare PCI Core Support +# +# CONFIG_PCIE_DW_PLAT is not set +# CONFIG_PCI_LAYERSCAPE is not set # # PCI host controller drivers # +# CONFIG_PCI_FTPCI100 is not set # CONFIG_PCI_HOST_GENERIC is not set -# CONFIG_PCI_LAYERSCAPE is not set CONFIG_PCIE_XGS_IPROC=y -# CONFIG_PCIE_IPROC is not set +CONFIG_PCIE_IPROC_MSI=y # CONFIG_PCIE_ALTERA is not set -# CONFIG_PCIEPORTBUS is not set + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set # CONFIG_PCCARD is not set # @@ -476,6 +552,7 @@ CONFIG_HZ_100=y CONFIG_HZ=100 # CONFIG_SCHED_HRTICK is not set # CONFIG_THUMB2_KERNEL is not set +CONFIG_ARM_PATCH_IDIV=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set @@ -484,7 +561,7 @@ CONFIG_HAVE_ARCH_PFN_VALID=y # CONFIG_HIGHMEM is not set CONFIG_CPU_SW_DOMAIN_PAN=y CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -# CONFIG_ARM_MODULE_PLTS is not set +CONFIG_ARM_MODULE_PLTS=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y @@ -492,12 +569,12 @@ CONFIG_NO_BOOTMEM=y CONFIG_MEMORY_ISOLATION=y # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_COMPACTION is not set +CONFIG_COMPACTION=y CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_ARCH_WANTS_THP_SWAP is not set # CONFIG_CLEANCACHE is not set # CONFIG_FRONTSWAP is not set CONFIG_CMA=y @@ -507,13 +584,17 @@ CONFIG_CMA_AREAS=7 # CONFIG_ZPOOL is not set # CONFIG_ZBUD is not set # CONFIG_ZSMALLOC is not set +CONFIG_GENERIC_EARLY_IOREMAP=y # CONFIG_IDLE_PAGE_TRACKING is not set +# CONFIG_PERCPU_STATS is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set # CONFIG_SECCOMP is not set CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set # CONFIG_XEN is not set # @@ -525,13 +606,14 @@ CONFIG_ATAGS=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 # CONFIG_ARM_APPENDED_DTB is not set -CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=496M" +CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=1 mem=240M" CONFIG_CMDLINE_FROM_BOOTLOADER=y # CONFIG_CMDLINE_EXTEND is not set # CONFIG_CMDLINE_FORCE is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set CONFIG_AUTO_ZRELADDR=y +# CONFIG_EFI is not set # # CPU Power Management @@ -561,7 +643,10 @@ CONFIG_AUTO_ZRELADDR=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set CONFIG_COREDUMP=y @@ -596,11 +681,8 @@ CONFIG_PACKET=y # CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y # CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y +# CONFIG_TLS is not set # CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -629,7 +711,6 @@ CONFIG_INET_TUNNEL=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -645,23 +726,24 @@ CONFIG_IPV6=y # CONFIG_IPV6_ILA is not set # CONFIG_INET6_XFRM_TUNNEL is not set CONFIG_INET6_TUNNEL=y -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -# CONFIG_IPV6_VTI is not set CONFIG_IPV6_SIT=y # CONFIG_IPV6_SIT_6RD is not set CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=y -# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_FOU is not set +# CONFIG_IPV6_FOU_TUNNEL is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NET_PTP_CLASSIFY=y # CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y -CONFIG_NETFILTER_DEBUG=y CONFIG_NETFILTER_ADVANCED=y CONFIG_BRIDGE_NETFILTER=y @@ -674,6 +756,7 @@ CONFIG_NETFILTER_NETLINK=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y +# CONFIG_NF_LOG_NETDEV is not set CONFIG_NF_CONNTRACK_MARK=y # CONFIG_NF_CONNTRACK_ZONES is not set CONFIG_NF_CONNTRACK_PROCFS=y @@ -759,7 +842,6 @@ CONFIG_NETFILTER_XT_MATCH_HL=y # CONFIG_NETFILTER_XT_MATCH_NFACCT is not set # CONFIG_NETFILTER_XT_MATCH_OSF is not set # CONFIG_NETFILTER_XT_MATCH_OWNER is not set -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set # CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set # CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set @@ -767,7 +849,6 @@ CONFIG_NETFILTER_XT_MATCH_HL=y # CONFIG_NETFILTER_XT_MATCH_REALM is not set # CONFIG_NETFILTER_XT_MATCH_RECENT is not set # CONFIG_NETFILTER_XT_MATCH_SCTP is not set -# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set CONFIG_NETFILTER_XT_MATCH_STATE=y # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set # CONFIG_NETFILTER_XT_MATCH_STRING is not set @@ -782,7 +863,7 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=y # CONFIG_NF_DEFRAG_IPV4=y CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_SOCKET_IPV4 is not set # CONFIG_NF_DUP_IPV4 is not set # CONFIG_NF_LOG_ARP is not set # CONFIG_NF_LOG_IPV4 is not set @@ -811,6 +892,7 @@ CONFIG_IP_NF_ARP_MANGLE=y # CONFIG_NF_DEFRAG_IPV6=y CONFIG_NF_CONNTRACK_IPV6=y +# CONFIG_NF_SOCKET_IPV6 is not set # CONFIG_NF_DUP_IPV6 is not set CONFIG_NF_REJECT_IPV6=y # CONFIG_NF_LOG_IPV6 is not set @@ -845,6 +927,7 @@ CONFIG_BRIDGE=y CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_BRIDGE_VLAN_FILTERING is not set CONFIG_HAVE_NET_DSA=y +# CONFIG_NET_DSA is not set CONFIG_VLAN_8021Q=y CONFIG_VLAN_8021Q_GVRP=y # CONFIG_VLAN_8021Q_MVRP is not set @@ -864,12 +947,13 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set -# CONFIG_NETLINK_MMAP is not set # CONFIG_NETLINK_DIAG is not set # CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set # CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_NCSI is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -884,9 +968,10 @@ CONFIG_NET_FLOW_LIMIT=y # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set -# CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set CONFIG_FIB_RULES=y # CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set @@ -895,14 +980,19 @@ CONFIG_FIB_RULES=y # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set # CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set # CONFIG_LWTUNNEL is not set -CONFIG_HAVE_BPF_JIT=y +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +# CONFIG_NET_DEVLINK is not set +CONFIG_MAY_USE_DEVLINK=y +CONFIG_HAVE_EBPF_JIT=y # # Device Drivers # CONFIG_ARM_AMBA=y -# CONFIG_TEGRA_AHB is not set # # Generic Driver Options @@ -920,8 +1010,14 @@ CONFIG_EXTRA_FIRMWARE="" CONFIG_ALLOW_DEV_COREDUMP=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y # CONFIG_DMA_SHARED_BUFFER is not set CONFIG_DMA_CMA=y @@ -934,11 +1030,13 @@ CONFIG_CMA_SIZE_SEL_MBYTES=y # CONFIG_CMA_SIZE_SEL_MIN is not set # CONFIG_CMA_SIZE_SEL_MAX is not set CONFIG_CMA_ALIGNMENT=8 +CONFIG_GENERIC_ARCH_TOPOLOGY=y # # Bus devices # # CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_SIMPLE_PM_BUS is not set # CONFIG_VEXPRESS_CONFIG is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y @@ -949,6 +1047,10 @@ CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_AR7_PARTS is not set +# +# Partition parsers +# + # # User Modules And Translation Layers # @@ -993,19 +1095,21 @@ CONFIG_MTD_CFI_UTIL=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PHYSMAP_OF is not set -# CONFIG_MTD_NOR_XGS_IPROC is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_NOR_XGS_IPROC=y # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80_IPROC=y +CONFIG_MTD_M25P80=y +# CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_SST25L is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set @@ -1025,16 +1129,13 @@ CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_DENALI_DT is not set # CONFIG_MTD_NAND_GPIO is not set # CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set -CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_RICOH is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_DOCG4 is not set # CONFIG_MTD_NAND_CAFE is not set # CONFIG_MTD_NAND_NANDSIM is not set CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_XGS_IPROC=y # CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_NAND_HISI504 is not set # CONFIG_MTD_ONENAND is not set # @@ -1042,10 +1143,10 @@ CONFIG_MTD_NAND_XGS_IPROC=y # # CONFIG_MTD_LPDDR is not set # CONFIG_MTD_LPDDR2_NVM is not set -# CONFIG_MTD_SPI_NOR is not set +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_MT81xx_NOR is not set # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set -CONFIG_MTD_SPI_NOR_IPROC=y -CONFIG_M25PXX_STAY_IN_3BYTE_MODE=y +# CONFIG_SPI_CADENCE_QUADSPI is not set CONFIG_MTD_UBI=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_LIMIT=20 @@ -1057,6 +1158,7 @@ CONFIG_OF=y # CONFIG_OF_UNITTEST is not set CONFIG_OF_FLATTREE=y CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_DYNAMIC=y CONFIG_OF_ADDRESS=y CONFIG_OF_ADDRESS_PCI=y CONFIG_OF_IRQ=y @@ -1064,31 +1166,33 @@ CONFIG_OF_NET=y CONFIG_OF_MDIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y -CONFIG_OF_MTD=y CONFIG_OF_RESERVED_MEM=y -# CONFIG_OF_OVERLAY is not set +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=32768 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set # CONFIG_BLK_DEV_RSXX is not set # CONFIG_BLK_DEV_NVME is not set +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TARGET is not set # # Misc devices @@ -1105,17 +1209,15 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_ISL29003 is not set # CONFIG_ISL29020 is not set # CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_BH1780 is not set # CONFIG_SENSORS_BH1770 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085_I2C is not set -# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_SRAM is not set +# CONFIG_PCI_ENDPOINT_TEST is not set # CONFIG_C2PORT is not set # @@ -1127,6 +1229,7 @@ CONFIG_EEPROM_AT24=y # CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set # CONFIG_CB710_CORE is not set # @@ -1147,6 +1250,10 @@ CONFIG_EEPROM_AT24=y # SCIF Bus Driver # +# +# VOP Bus Driver +# + # # Intel MIC Host Driver # @@ -1162,10 +1269,14 @@ CONFIG_EEPROM_AT24=y # # Intel MIC Coprocessor State Management (COSM) Drivers # + +# +# VOP Driver +# # CONFIG_ECHO is not set # CONFIG_CXL_BASE is not set -# CONFIG_CXL_KERNEL_API is not set -# CONFIG_CXL_EEH is not set +# CONFIG_CXL_AFU_DRIVER_OPS is not set +# CONFIG_CXL_LIB is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1228,6 +1339,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_MPT3SAS is not set # CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_SMARTPQI is not set # CONFIG_SCSI_UFSHCD is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_SNIC is not set @@ -1267,8 +1379,8 @@ CONFIG_BONDING=y # CONFIG_NET_FC is not set # CONFIG_NET_TEAM is not set # CONFIG_MACVLAN is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set +# CONFIG_MACSEC is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -1285,8 +1397,6 @@ CONFIG_BONDING=y # # Distributed Switch Architecture drivers # -# CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set CONFIG_ETHERNET=y CONFIG_NET_VENDOR_3COM=y # CONFIG_VORTEX is not set @@ -1295,14 +1405,18 @@ CONFIG_NET_VENDOR_ADAPTEC=y # CONFIG_ADAPTEC_STARFIRE is not set CONFIG_NET_VENDOR_AGERE=y # CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set CONFIG_NET_VENDOR_ALTEON=y # CONFIG_ACENIC is not set # CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y CONFIG_NET_VENDOR_AMD=y # CONFIG_AMD8111_ETH is not set # CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE_HAVE_ECC is not set +CONFIG_NET_VENDOR_AQUANTIA=y CONFIG_NET_VENDOR_ARC=y -# CONFIG_ARC_EMAC is not set CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL2 is not set # CONFIG_ATL1 is not set @@ -1318,27 +1432,13 @@ CONFIG_NET_VENDOR_BROADCOM=y # CONFIG_BNX2 is not set # CONFIG_CNIC is not set CONFIG_TIGON3=y +CONFIG_TIGON3_HWMON=y # CONFIG_BNX2X is not set +CONFIG_BGMAC=y +CONFIG_BGMAC_PLATFORM=y +# CONFIG_APM is not set # CONFIG_SYSTEMPORT is not set # CONFIG_BNXT is not set -CONFIG_GMAC_XGS_IPROC=y - -# -# Broadcom HND network devices -# -CONFIG_HND=y -CONFIG_ET=y -# CONFIG_ET_NAPI2_POLL is not set -# CONFIG_BCM_IPROC_GMAC_ACP is not set -# CONFIG_BCM_IPROC_GMAC_PREFETCH is not set -# CONFIG_BCM_IPROC_GMAC_LOCK_OPT is not set -# CONFIG_BCM_IPROC_GMAC_RWREG_OPT is not set -# CONFIG_BCM_IPROC_GMAC_SG is not set -CONFIG_IPROC_SDK_MGT_PORT_HANDOFF=y -# CONFIG_IPROC_2STAGE_RX is not set -# CONFIG_SERDES_ASYMMETRIC_MODE is not set -# CONFIG_JUMBO_FRAME is not set -CONFIG_MDIO_XGS_IPROC=y CONFIG_NET_VENDOR_BROCADE=y # CONFIG_BNA is not set CONFIG_NET_VENDOR_CAVIUM=y @@ -1370,12 +1470,15 @@ CONFIG_NET_VENDOR_FARADAY=y # CONFIG_FTGMAC100 is not set CONFIG_NET_VENDOR_HISILICON=y # CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HISI_FEMAC is not set # CONFIG_HIP04_ETH is not set # CONFIG_HNS is not set # CONFIG_HNS_DSAF is not set # CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set CONFIG_NET_VENDOR_HP=y # CONFIG_HP100 is not set +CONFIG_NET_VENDOR_HUAWEI=y CONFIG_NET_VENDOR_INTEL=y # CONFIG_E100 is not set # CONFIG_E1000 is not set @@ -1392,6 +1495,7 @@ CONFIG_NET_VENDOR_I825XX=y # CONFIG_JME is not set CONFIG_NET_VENDOR_MARVELL=y # CONFIG_MVMDIO is not set +# CONFIG_MVNETA_BM is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set CONFIG_NET_VENDOR_MELLANOX=y @@ -1399,6 +1503,7 @@ CONFIG_NET_VENDOR_MELLANOX=y # CONFIG_MLX4_CORE is not set # CONFIG_MLX5_CORE is not set # CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set CONFIG_NET_VENDOR_MICREL=y # CONFIG_KS8842 is not set # CONFIG_KS8851 is not set @@ -1413,6 +1518,8 @@ CONFIG_NET_VENDOR_MYRI=y CONFIG_NET_VENDOR_NATSEMI=y # CONFIG_NATSEMI is not set # CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set CONFIG_NET_VENDOR_8390=y # CONFIG_AX88796 is not set # CONFIG_NE2K_PCI is not set @@ -1430,7 +1537,9 @@ CONFIG_NET_VENDOR_QLOGIC=y # CONFIG_NETXEN_NIC is not set # CONFIG_QED is not set CONFIG_NET_VENDOR_QUALCOMM=y -# CONFIG_QCA7000 is not set +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCOM_EMAC is not set +# CONFIG_RMNET is not set CONFIG_NET_VENDOR_REALTEK=y # CONFIG_8139CP is not set # CONFIG_8139TOO is not set @@ -1447,7 +1556,9 @@ CONFIG_NET_VENDOR_SILAN=y CONFIG_NET_VENDOR_SIS=y # CONFIG_SIS900 is not set # CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SOLARFLARE=y # CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set CONFIG_NET_VENDOR_SMSC=y # CONFIG_SMC91X is not set # CONFIG_EPIC100 is not set @@ -1461,8 +1572,6 @@ CONFIG_NET_VENDOR_SUN=y # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NIU is not set -CONFIG_NET_VENDOR_SYNOPSYS=y -# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set CONFIG_NET_VENDOR_TEHUTI=y # CONFIG_TEHUTI is not set CONFIG_NET_VENDOR_TI=y @@ -1474,41 +1583,56 @@ CONFIG_NET_VENDOR_VIA=y CONFIG_NET_VENDOR_WIZNET=y # CONFIG_WIZNET_W5100 is not set # CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_HISI_FEMAC is not set CONFIG_PHYLIB=y +CONFIG_SWPHY=y +CONFIG_MDIO_XGS_IPROC=y # # MII PHY device drivers # +# CONFIG_AMD_PHY is not set # CONFIG_AQUANTIA_PHY is not set # CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set # CONFIG_BCM7XXX_PHY is not set # CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BROADCOM_PHY=y +CONFIG_XGS_IPROC_SERDES=y +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set # CONFIG_DP83848_PHY is not set # CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICREL_PHY is not set # CONFIG_MICROCHIP_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -# CONFIG_MDIO_BUS_MUX_GPIO is not set -# CONFIG_MDIO_BUS_MUX_MMIOREG is not set -# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -1549,6 +1673,7 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_PS2MULT is not set # CONFIG_SERIO_ARC_PS2 is not set # CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set # CONFIG_USERIO is not set # CONFIG_GAMEPORT is not set @@ -1558,7 +1683,6 @@ CONFIG_SERIO_LIBPS2=y CONFIG_TTY=y # CONFIG_VT is not set CONFIG_UNIX98_PTYS=y -CONFIG_DEVPTS_MULTIPLE_INSTANCES=y # CONFIG_LEGACY_PTYS is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_NOZOMI is not set @@ -1573,13 +1697,16 @@ CONFIG_DEVKMEM=y CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +# CONFIG_SERIAL_8250_FINTEK is not set CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DMA=y CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_EXAR=y CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 CONFIG_SERIAL_8250_EXTENDED=y # CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_ASPEED_VUART is not set CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y @@ -1587,8 +1714,8 @@ CONFIG_SERIAL_8250_FSL=y CONFIG_SERIAL_8250_DW=y # CONFIG_SERIAL_8250_EM is not set # CONFIG_SERIAL_8250_RT288X is not set -# CONFIG_SERIAL_8250_INGENIC is not set -# CONFIG_SERIAL_8250_MID is not set +# CONFIG_SERIAL_8250_MOXA is not set +CONFIG_SERIAL_OF_PLATFORM=y # # Non-8250 serial port support @@ -1602,7 +1729,6 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set -CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SC16IS7XX is not set # CONFIG_SERIAL_BCM63XX is not set @@ -1615,13 +1741,13 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set # CONFIG_SERIAL_ST_ASC is not set -# CONFIG_SERIAL_STM32 is not set +# CONFIG_SERIAL_DEV_BUS is not set # CONFIG_TTY_PRINTK is not set # CONFIG_HVC_DCC is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_HW_RANDOM_XGS_IPROC_RNG is not set +CONFIG_HW_RANDOM_XGS_IPROC_RNG=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_RAW_DRIVER is not set @@ -1634,18 +1760,23 @@ CONFIG_DEVPORT=y # CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_MUX is not set -# CONFIG_I2C_HELPER_AUTO is not set -# CONFIG_I2C_SMBUS is not set +CONFIG_I2C_MUX=y # -# I2C Algorithms +# Multiplexer I2C Chip support # -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +CONFIG_I2C_MUX_GPIO=y +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +CONFIG_I2C_MUX_PCA9541=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_MUX_PCA954X_DESELECT_ON_EXIT=y +CONFIG_I2C_MUX_REG=y +# CONFIG_I2C_MUX_MLXCPLD is not set +CONFIG_I2C_HELPER_AUTO=y # # I2C Hardware Bus support @@ -1672,8 +1803,8 @@ CONFIG_I2C_CHARDEV=y # # I2C system bus drivers (mostly embedded / system-on-chip) # -CONFIG_I2C_XGS_IPROC=y -# CONFIG_SMBUS_XGS_IPROC is not set +# CONFIG_I2C_XGS_IPROC is not set +CONFIG_SMBUS_XGS_IPROC=y # CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_DESIGNWARE_PLATFORM is not set # CONFIG_I2C_DESIGNWARE_PCI is not set @@ -1712,8 +1843,11 @@ CONFIG_SPI_MASTER=y # SPI Master Controller Drivers # # CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +CONFIG_SPI_BCM_QSPI=y # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_DESIGNWARE is not set # CONFIG_SPI_GPIO is not set # CONFIG_SPI_FSL_SPI is not set # CONFIG_SPI_OC_TINY is not set @@ -1725,24 +1859,16 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_ZYNQMP_GQSPI is not set -CONFIG_SPI_XGS_IPROC=y -CONFIG_IPROC_QSPI_SINGLE_MODE=y -# CONFIG_IPROC_QSPI_DUAL_MODE is not set -# CONFIG_IPROC_QSPI_QUAD_MODE is not set -CONFIG_IPROC_QSPI_MAX_HZ=62500000 -# CONFIG_SPI_DESIGNWARE is not set # # SPI Protocol Masters # # CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_LOOPBACK_TEST is not set # CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_SLAVE is not set # CONFIG_SPMI is not set # CONFIG_HSI is not set - -# -# PPS support -# CONFIG_PPS=y # CONFIG_PPS_DEBUG is not set @@ -1766,10 +1892,7 @@ CONFIG_PTP_1588_CLOCK=y # Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. # CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_DEBUG_GPIO is not set @@ -1783,14 +1906,15 @@ CONFIG_GPIO_GENERIC=y # CONFIG_GPIO_ALTERA is not set CONFIG_GPIO_XGS_IPROC=y # CONFIG_GPIO_DWAPB is not set -# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_EXAR is not set +# CONFIG_GPIO_FTGPIO010 is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_MPC8XXX is not set # CONFIG_GPIO_PL061 is not set -# CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_XILINX is not set # CONFIG_GPIO_ZEVIO is not set -# CONFIG_GPIO_ZX is not set # # I2C GPIO expanders @@ -1801,18 +1925,18 @@ CONFIG_GPIO_XGS_IPROC=y # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_TPIC2810 is not set # # MFD GPIO expanders # +# CONFIG_HTC_EGPIO is not set # # PCI GPIO expanders # -# CONFIG_GPIO_AMD8111 is not set # CONFIG_GPIO_BT8XX is not set -# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set # CONFIG_GPIO_RDC321X is not set # @@ -1821,20 +1945,18 @@ CONFIG_GPIO_XGS_IPROC=y # CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_MAX7301 is not set # CONFIG_GPIO_MC33880 is not set - -# -# SPI or I2C GPIO expanders -# -# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set # # USB GPIO expanders # # CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set # CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set +CONFIG_HWMON_VID=y # CONFIG_HWMON_DEBUG_CHIP is not set # @@ -1856,6 +1978,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set @@ -1863,6 +1986,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FTSTEUTATES is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_G760A is not set @@ -1874,6 +1998,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_POWR1220 is not set # CONFIG_SENSORS_LINEAGE is not set # CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2990 is not set # CONFIG_SENSORS_LTC4151 is not set # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4222 is not set @@ -1885,27 +2010,28 @@ CONFIG_HWMON=y # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX1668 is not set # CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31722 is not set # CONFIG_SENSORS_MAX6639 is not set # CONFIG_SENSORS_MAX6642 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX31790 is not set -# CONFIG_SENSORS_HTU21 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set # CONFIG_SENSORS_ADCXX is not set # CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM73 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set +CONFIG_SENSORS_LM70=y +CONFIG_SENSORS_LM73=y +CONFIG_SENSORS_LM75=y +CONFIG_SENSORS_LM77=y +CONFIG_SENSORS_LM78=y +CONFIG_SENSORS_LM80=y +CONFIG_SENSORS_LM83=y +CONFIG_SENSORS_LM85=y +CONFIG_SENSORS_LM87=y +CONFIG_SENSORS_LM90=y +CONFIG_SENSORS_LM92=y +CONFIG_SENSORS_LM93=y # CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set @@ -1920,6 +2046,7 @@ CONFIG_HWMON=y # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set # CONFIG_SENSORS_SHTC1 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1932,6 +2059,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SCH56XX_COMMON is not set # CONFIG_SENSORS_SCH5627 is not set # CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_STTS751 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_ADC128D818 is not set # CONFIG_SENSORS_ADS1015 is not set @@ -1940,10 +2068,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_INA209 is not set # CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set # CONFIG_SENSORS_TC74 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP102 is not set # CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_VIA686A is not set @@ -1958,10 +2088,31 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set -# CONFIG_THERMAL is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_QORIQ_THERMAL is not set + +# +# ACPI INT340X thermal drivers +# CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +# CONFIG_WATCHDOG_SYSFS is not set # # Watchdog Device Drivers @@ -1969,14 +2120,13 @@ CONFIG_WATCHDOG_CORE=y # CONFIG_SOFT_WATCHDOG is not set # CONFIG_GPIO_WATCHDOG is not set # CONFIG_XILINX_WATCHDOG is not set -# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +CONFIG_ARM_SP805_WATCHDOG=y # CONFIG_CADENCE_WATCHDOG is not set # CONFIG_DW_WATCHDOG is not set # CONFIG_MAX63XX_WATCHDOG is not set -CONFIG_XGS_IPROC_SP805_WDT=y # CONFIG_ALIM7101_WDT is not set # CONFIG_I6300ESB_WDT is not set -# CONFIG_BCM7038_WDT is not set # CONFIG_MEN_A21_WDT is not set # @@ -1989,6 +2139,11 @@ CONFIG_XGS_IPROC_SP805_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set CONFIG_SSB_POSSIBLE=y # @@ -1996,16 +2151,13 @@ CONFIG_SSB_POSSIBLE=y # # CONFIG_SSB is not set CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# # CONFIG_BCMA is not set # # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_ACT8945A is not set # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_AS3722 is not set # CONFIG_PMIC_ADP5520 is not set @@ -2013,7 +2165,8 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_ATMEL_FLEXCOM is not set # CONFIG_MFD_ATMEL_HLCDC is not set # CONFIG_MFD_BCM590XX is not set -# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set # CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_PMIC_DA903X is not set @@ -2027,18 +2180,17 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_MC13XXX_SPI is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_LPC_ICH is not set # CONFIG_LPC_SCH is not set -# CONFIG_INTEL_SOC_PMIC is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_KEMPLD is not set # CONFIG_MFD_88PM800 is not set # CONFIG_MFD_88PM805 is not set # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX77843 is not set @@ -2049,10 +2201,11 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set +# CONFIG_MFD_CPCAP is not set # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_RETU is not set # CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_PM8921_CORE is not set +# CONFIG_MFD_PM8XXX is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RTSX_PCI is not set # CONFIG_MFD_RT5033 is not set @@ -2071,16 +2224,19 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set # CONFIG_MFD_PALMAS is not set # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set # CONFIG_MFD_TPS80031 is not set @@ -2108,8 +2264,14 @@ CONFIG_BCMA_POSSIBLE=y # Graphics support # # CONFIG_VGA_ARB is not set +# CONFIG_IMX_IPUV3_CORE is not set # CONFIG_DRM is not set +# +# ACP (Audio CoProcessor) Configuration +# +# CONFIG_DRM_LIB_RANDOM is not set + # # Frame buffer Devices # @@ -2122,6 +2284,7 @@ CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y +CONFIG_USB_PCI=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # @@ -2132,7 +2295,6 @@ CONFIG_USB_DYNAMIC_MINORS=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_ULPI_BUS is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2145,8 +2307,8 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y -CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_EHCI_XGS_IPROC=y +CONFIG_USB_EHCI_HCD_PLATFORM=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1362_HCD is not set @@ -2219,7 +2381,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_IDMOUSE is not set @@ -2234,7 +2395,9 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set @@ -2243,17 +2406,18 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_PHY=y # CONFIG_NOP_USB_XCEIV is not set -# CONFIG_AM335X_PHY_USB is not set # CONFIG_USB_GPIO_VBUS is not set # CONFIG_USB_ISP1301 is not set # CONFIG_USB_ULPI is not set CONFIG_USBPHY_XGS_IPROC=y +# CONFIG_USB_XGS_IPROC_DRD is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_U_SERIAL_CONSOLE is not set # # USB Peripheral Controller @@ -2265,6 +2429,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 # CONFIG_USB_PXA27X is not set # CONFIG_USB_MV_UDC is not set # CONFIG_USB_MV_U3D is not set +# CONFIG_USB_SNP_UDC_PLAT is not set # CONFIG_USB_M66592 is not set # CONFIG_USB_BDC_UDC is not set # CONFIG_USB_AMD5536UDC is not set @@ -2273,7 +2438,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 # CONFIG_USB_GOKU is not set # CONFIG_USB_EG20T is not set # CONFIG_USB_GADGET_XILINX is not set -CONFIG_USB_XGS_IPROC_UDC=m +CONFIG_USB_XGS_IPROC_UDC=y # CONFIG_USB_DUMMY_HCD is not set CONFIG_USB_LIBCOMPOSITE=m CONFIG_USB_F_ACM=m @@ -2294,27 +2459,34 @@ CONFIG_USB_G_SERIAL=m # CONFIG_USB_G_MULTI is not set # CONFIG_USB_G_HID is not set # CONFIG_USB_G_DBGP is not set -# CONFIG_UWB is not set -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set # -# MMC/SD/SDIO Card Drivers +# USB Power Delivery and Type-C drivers # +# CONFIG_TYPEC_UCSI is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_SDIO_UART is not set # CONFIG_MMC_TEST is not set # # MMC/SD/SDIO Host Controller Drivers # +# CONFIG_MMC_DEBUG is not set # CONFIG_MMC_ARMMMCI is not set CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_IO_ACCESSORS=y # CONFIG_MMC_SDHCI_PCI is not set -# CONFIG_MMC_SDHCI_PLTFM is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set # CONFIG_MMC_TIFM_SD is not set # CONFIG_MMC_SPI is not set # CONFIG_MMC_CB710 is not set @@ -2326,15 +2498,159 @@ CONFIG_MMC_SDHCI_IO_ACCESSORS=y # CONFIG_MMC_TOSHIBA_PCI is not set # CONFIG_MMC_MTK is not set CONFIG_MMC_SDHCI_XGS_IPROC=y +# CONFIG_MMC_SDHCI_XENON is not set # CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_USER is not set + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGERS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set CONFIG_EDAC_ATOMIC_SCRUB=y CONFIG_EDAC_SUPPORT=y -# CONFIG_EDAC is not set CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_SYSTOHC is not set +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS1307_HWMON=y +CONFIG_RTC_DRV_DS1307_CENTURY=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_R7301 is not set + +# +# HID Sensor RTC drivers +# CONFIG_DMADEVICES=y CONFIG_DMADEVICES_DEBUG=y CONFIG_DMADEVICES_VDEBUG=y @@ -2344,12 +2660,14 @@ CONFIG_DMADEVICES_VDEBUG=y # CONFIG_DMA_ENGINE=y CONFIG_DMA_OF=y +# CONFIG_ALTERA_MSGDMA is not set # CONFIG_AMBA_PL08X is not set # CONFIG_FSL_EDMA is not set # CONFIG_INTEL_IDMA64 is not set # CONFIG_NBPFAXI_DMA is not set CONFIG_PL330_DMA=y -# CONFIG_XGS_IPROC_DMA330_DMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set # CONFIG_DW_DMAC is not set # CONFIG_DW_DMAC_PCI is not set @@ -2358,6 +2676,11 @@ CONFIG_PL330_DMA=y # # CONFIG_ASYNC_TX_DMA is not set # CONFIG_DMATEST is not set + +# +# DMABUF options +# +# CONFIG_SYNC_FILE is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # CONFIG_VIRT_DRIVERS is not set @@ -2371,7 +2694,9 @@ CONFIG_PL330_DMA=y # # Microsoft Hyper-V guest support # +# CONFIG_HYPERV_TSCPAGE is not set # CONFIG_STAGING is not set +# CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -2380,25 +2705,27 @@ CONFIG_COMMON_CLK=y # # Common Clock Framework # +# CONFIG_CLK_HSDK is not set # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI570 is not set -# CONFIG_COMMON_CLK_CDCE925 is not set -# CONFIG_CLK_QORIQ is not set -# CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_NXP is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_PIC32 is not set +# CONFIG_COMMON_CLK_VC5 is not set CONFIG_COMMON_CLK_IPROC=y CONFIG_CLK_XGS_IPROC=y - -# -# Hardware Spinlock drivers -# +# CONFIG_HWSPINLOCK is not set # # Clock Source drivers # -CONFIG_CLKSRC_OF=y -CONFIG_CLKSRC_PROBE=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y CONFIG_ARM_GLOBAL_TIMER=y # CONFIG_ARM_TIMER_SP804 is not set CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y @@ -2414,12 +2741,13 @@ CONFIG_IOMMU_SUPPORT=y # Generic IOMMU Pagetable Support # # CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set # CONFIG_ARM_SMMU is not set # # Remoteproc drivers # -# CONFIG_STE_MODEM_RPROC is not set +# CONFIG_REMOTEPROC is not set # # Rpmsg drivers @@ -2428,12 +2756,36 @@ CONFIG_IOMMU_SUPPORT=y # # SOC (System On Chip) specific Drivers # + +# +# Amlogic SoC drivers +# + +# +# Broadcom SoC drivers +# # CONFIG_SOC_BRCMSTB is not set -CONFIG_SOC_XGS_IPROC=y + +# +# i.MX SoC drivers +# + +# +# Qualcomm SoC drivers +# # CONFIG_SUNXI_SRAM is not set # CONFIG_SOC_TI is not set # CONFIG_PM_DEVFREQ is not set -# CONFIG_EXTCON is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set # CONFIG_MEMORY is not set # CONFIG_IIO is not set # CONFIG_NTB is not set @@ -2441,6 +2793,7 @@ CONFIG_SOC_XGS_IPROC=y # CONFIG_PWM is not set CONFIG_IRQCHIP=y CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_IPACK_BUS is not set # CONFIG_RESET_CONTROLLER is not set # CONFIG_FMC is not set @@ -2448,38 +2801,41 @@ CONFIG_ARM_GIC=y # # PHY Subsystem # -# CONFIG_GENERIC_PHY is not set +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_POWERCAP is not set # CONFIG_MCB is not set - -# -# Performance monitor support -# # CONFIG_RAS is not set -# CONFIG_THUNDERBOLT is not set # # Android # # CONFIG_ANDROID is not set -# CONFIG_NVMEM is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y # CONFIG_STM is not set -# CONFIG_STM_DUMMY is not set -# CONFIG_STM_SOURCE_CONSOLE is not set # CONFIG_INTEL_TH is not set +# CONFIG_FPGA is not set # -# FPGA Configuration Support +# FSI support # -# CONFIG_FPGA is not set +# CONFIG_FSI is not set +# CONFIG_TEE is not set # # Firmware Drivers # # CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# Tegra firmware driver +# # # File systems @@ -2508,16 +2864,21 @@ CONFIG_FS_MBCACHE=y # CONFIG_F2FS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set CONFIG_FILE_LOCKING=y -# CONFIG_FSNOTIFY is not set +CONFIG_MANDATORY_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y # CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set +CONFIG_INOTIFY_USER=y # CONFIG_FANOTIFY is not set # CONFIG_QUOTA is not set # CONFIG_QUOTACTL is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +# CONFIG_OVERLAY_FS_INDEX is not set # # Caches @@ -2538,6 +2899,7 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set CONFIG_NTFS_FS=y # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_RW is not set @@ -2547,13 +2909,17 @@ CONFIG_NTFS_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y -# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_PROC_PAGE_MONITOR=y # CONFIG_PROC_CHILDREN is not set CONFIG_KERNFS=y CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y # CONFIG_HUGETLB_PAGE is not set CONFIG_CONFIGFS_FS=m CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set @@ -2578,9 +2944,24 @@ CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_ATIME_SUPPORT is not set -# CONFIG_LOGFS is not set +# CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_SECURITY=y # CONFIG_CRAMFS is not set -# CONFIG_SQUASHFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_DECOMP_MULTI=y +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -2680,6 +3061,7 @@ CONFIG_NLS_ISO8859_1=y # printk and dmesg options # # CONFIG_PRINTK_TIME is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -2692,8 +3074,8 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_INFO_SPLIT is not set # CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_GDB_SCRIPTS is not set -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_READABLE_ASM is not set @@ -2703,10 +3085,10 @@ CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y -CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y CONFIG_DEBUG_KERNEL=y # @@ -2714,12 +3096,16 @@ CONFIG_DEBUG_KERNEL=y # # CONFIG_PAGE_EXTENSION is not set # CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_STATS is not set CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_VM is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_SHIRQ is not set @@ -2727,8 +3113,9 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # # Debug Lockups and Hangs # -# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_SOFTLOCKUP_DETECTOR is not set # CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 @@ -2737,7 +3124,6 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set # CONFIG_DEBUG_TIMEKEEPING is not set -# CONFIG_TIMER_STATS is not set CONFIG_DEBUG_PREEMPT=y # @@ -2753,7 +3139,9 @@ CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set # CONFIG_STACKTRACE is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set @@ -2766,29 +3154,35 @@ CONFIG_DEBUG_BUGVERBOSE=y # RCU Debugging # # CONFIG_PROVE_RCU is not set -# CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_PERF_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_TIMEOUT=21 # CONFIG_RCU_TRACE is not set # CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set +# CONFIG_DMA_API_DEBUG is not set # # Runtime Testing # # CONFIG_LKDTM is not set # CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_RBTREE_TEST is not set # CONFIG_INTERVAL_TREE_TEST is not set @@ -2798,28 +3192,35 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set # CONFIG_TEST_RHASHTABLE is not set -# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_HASH is not set # CONFIG_TEST_LKM is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set # CONFIG_TEST_UDELAY is not set -# CONFIG_MEMTEST is not set # CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_MEMTEST is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -# CONFIG_ARM_PTDUMP is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set -# CONFIG_ARM_UNWIND is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y # CONFIG_DEBUG_LL is not set CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" # CONFIG_DEBUG_UART_8250 is not set CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" # CONFIG_PID_IN_CONTEXTIDR is not set -# CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_CORESIGHT is not set # @@ -2827,10 +3228,15 @@ CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" # CONFIG_KEYS=y # CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set # CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEY_DH_OPERATIONS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_STATIC_USERMODEHELPER is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" CONFIG_CRYPTO=y @@ -2849,9 +3255,12 @@ CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=m CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=m -CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_ACOMP2=y # CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_USER is not set @@ -2913,6 +3322,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_SHA1 is not set CONFIG_CRYPTO_SHA256=m # CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA3 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set @@ -2920,6 +3330,7 @@ CONFIG_CRYPTO_SHA256=m # Ciphers # CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set @@ -2940,7 +3351,6 @@ CONFIG_CRYPTO_DES=y # Compression # CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set # CONFIG_CRYPTO_LZ4 is not set @@ -2953,7 +3363,6 @@ CONFIG_CRYPTO_ANSI_CPRNG=m CONFIG_CRYPTO_DRBG_MENU=m CONFIG_CRYPTO_DRBG_HMAC=y # CONFIG_CRYPTO_DRBG_HASH is not set -# CONFIG_CRYPTO_DRBG_CTR is not set CONFIG_CRYPTO_DRBG=m CONFIG_CRYPTO_JITTERENTROPY=m # CONFIG_CRYPTO_USER_API_HASH is not set @@ -2962,12 +3371,13 @@ CONFIG_CRYPTO_JITTERENTROPY=m # CONFIG_CRYPTO_USER_API_AEAD is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set # # Certificates for signature checking # -# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set # CONFIG_ARM_CRYPTO is not set # CONFIG_BINARY_PRINTF is not set @@ -2993,15 +3403,19 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_SLICEBY4 is not set # CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_BIT is not set +# CONFIG_CRC4 is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set +CONFIG_XXHASH=y # CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set # CONFIG_RANDOM32_SELFTEST is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y CONFIG_XZ_DEC=y CONFIG_XZ_DEC_X86=y CONFIG_XZ_DEC_POWERPC=y @@ -3011,19 +3425,30 @@ CONFIG_XZ_DEC_ARMTHUMB=y CONFIG_XZ_DEC_SPARC=y CONFIG_XZ_DEC_BCJ=y # CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y CONFIG_HAS_DMA=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +# CONFIG_IRQ_POLL is not set CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y # CONFIG_SG_SPLIT is not set +CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set # CONFIG_VIRTUALIZATION is not set diff --git a/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/.gitignore b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/.gitignore new file mode 100644 index 00000000..285a565e --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/.gitignore @@ -0,0 +1,2 @@ +linux-4.14* +kernel-4.14* diff --git a/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/Makefile b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/Makefile new file mode 100644 index 00000000..b6692ed6 --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/Makefile @@ -0,0 +1,42 @@ +########################################################### +# +# +# Copyright 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ + +THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +include $(ONL)/make/config.mk + +ifndef K_TARGET_DIR +K_TARGET_DIR := $(THIS_DIR) +endif + +K_PATCH_DIR := $(THIS_DIR)/patches + +include ../../kconfig.mk +K_CONFIG := armhf-iproc-all.config +K_BUILD_TARGET := Image +K_COPY_SRC := arch/arm/boot/Image +K_COPY_GZIP := 1 +ifndef K_COPY_DST +K_COPY_DST := kernel-4.14-lts-armhf-iproc-all.bin.gz +endif + +export ARCH=arm + +include $(ONL)/make/kbuild.mk diff --git a/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/armhf-iproc-all.config b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/armhf-iproc-all.config new file mode 100644 index 00000000..c5bc18eb --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/configs/armhf-iproc-all/armhf-iproc-all.config @@ -0,0 +1,3456 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.14.49 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="arm-linux-gnueabihf-" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="-OpenNetworkLinux-armhf" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_IRQ_DOMAIN_DEBUG=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +CONFIG_GENERIC_SCHED_CLOCK=y +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_POSIX_TIMERS=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_PCI_QUIRKS=y +CONFIG_MEMBARRIER=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y +# CONFIG_PC104 is not set + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_NMI=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_GCC_PLUGINS=y +# CONFIG_GCC_PLUGINS is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_THIN_ARCHIVES=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_HAVE_EXIT_THREAD=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_BITS=8 +# CONFIG_HAVE_ARCH_HASH is not set +# CONFIG_ISA_BUS_API is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y +# CONFIG_CPU_NO_EFFICIENT_FFS is not set +# CONFIG_HAVE_ARCH_VMAP_STACK is not set +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +# CONFIG_REFCOUNT_FULL is not set + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_SCSI_REQUEST=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLK_MQ_PCI=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_ARTPEC is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_DIGICOLOR is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HISI is not set +CONFIG_ARCH_XGS_IPROC=y + +# +# XGS iProc SoC based Machine types +# +CONFIG_XGS_IPROC_ARM32_PLATFORM=y +# CONFIG_MACH_HX4 is not set +# CONFIG_MACH_HR2 is not set +# CONFIG_MACH_KT2 is not set +# CONFIG_MACH_GH is not set +# CONFIG_MACH_SB2 is not set +# CONFIG_MACH_HR3 is not set +# CONFIG_MACH_GH2 is not set +# CONFIG_MACH_WH2 is not set +# CONFIG_MACH_IPROC_EMULATION is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MEDIATEK is not set + +# +# TI OMAP/AM/DM/DRA Family +# +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TANGO is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +# CONFIG_VDSO is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +CONFIG_ARM_ERRATA_754322=y +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set +# CONFIG_ARM_ERRATA_818325_852422 is not set +# CONFIG_ARM_ERRATA_821420 is not set +# CONFIG_ARM_ERRATA_825619 is not set +# CONFIG_ARM_ERRATA_852421 is not set +# CONFIG_ARM_ERRATA_852423 is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCIEPORTBUS is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# DesignWare PCI Core Support +# +# CONFIG_PCIE_DW_PLAT is not set +# CONFIG_PCI_LAYERSCAPE is not set + +# +# PCI host controller drivers +# +# CONFIG_PCI_FTPCI100 is not set +# CONFIG_PCI_HOST_GENERIC is not set +CONFIG_PCIE_XGS_IPROC=y +CONFIG_PCIE_IPROC_MSI=y +# CONFIG_PCIE_ALTERA is not set + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_3G_OPT is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_ARM_PSCI is not set +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_100=y +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +# CONFIG_SCHED_HRTICK is not set +# CONFIG_THUMB2_KERNEL is not set +CONFIG_ARM_PATCH_IDIV=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +# CONFIG_HIGHMEM is not set +CONFIG_CPU_SW_DOMAIN_PAN=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARM_MODULE_PLTS=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_ARCH_WANTS_THP_SWAP is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +CONFIG_CMA_DEBUG=y +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_AREAS=7 +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_IDLE_PAGE_TRACKING is not set +# CONFIG_PERCPU_STATS is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=1 mem=240M" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y +# CONFIG_EFI is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# CPU Idle +# +# CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_FLAT is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_UDP_TUNNEL is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +CONFIG_INET6_TUNNEL=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=y +# CONFIG_IPV6_FOU is not set +# CONFIG_IPV6_FOU_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +# CONFIG_NF_LOG_NETDEV is not set +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +CONFIG_NF_CONNTRACK_FTP=y +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=y +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +CONFIG_NETFILTER_XT_TARGET_CT=y +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +CONFIG_NETFILTER_XT_TARGET_HL=y +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LOG is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +CONFIG_NETFILTER_XT_MATCH_ECN=y +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=y +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +CONFIG_NF_REJECT_IPV4=y +# CONFIG_NF_NAT_IPV4 is not set +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +# CONFIG_IP_NF_NAT is not set +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +CONFIG_IP_NF_TARGET_ECN=y +CONFIG_IP_NF_TARGET_TTL=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +CONFIG_NF_REJECT_IPV6=y +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_NF_NAT_IPV6 is not set +CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_MATCH_RT=y +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_NAT is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=y +CONFIG_GARP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_HAVE_NET_DSA=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=y +CONFIG_VLAN_8021Q_GVRP=y +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_NCSI is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set +CONFIG_FIB_RULES=y +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +# CONFIG_LWTUNNEL is not set +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +# CONFIG_NET_DEVLINK is not set +CONFIG_MAY_USE_DEVLINK=y +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_GENERIC_ARCH_TOPOLOGY=y + +# +# Bus devices +# +# CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_SIMPLE_PM_BUS is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# Partition parsers +# + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_NOR_XGS_IPROC=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI_PCI is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_BRCMNAND=y +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_MT81xx_NOR is not set +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TARGET is not set + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# VOP Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# + +# +# VOP Driver +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_AFU_DRIVER_OPS is not set +# CONFIG_CXL_LIB is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_MACSEC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE_HAVE_ECC is not set +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_NET_VENDOR_ARC=y +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +# CONFIG_NET_VENDOR_AURORA is not set +CONFIG_NET_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +CONFIG_TIGON3=y +CONFIG_TIGON3_HWMON=y +# CONFIG_BNX2X is not set +CONFIG_BGMAC=y +CONFIG_BGMAC_PLATFORM=y +# CONFIG_APM is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_BNXT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HISI_FEMAC is not set +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_HUAWEI=y +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_MVNETA_BM is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_QED is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCOM_EMAC is not set +# CONFIG_RMNET is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SOLARFLARE=y +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_HISI_FEMAC is not set +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +CONFIG_MDIO_XGS_IPROC=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BROADCOM_PHY=y +CONFIG_XGS_IPROC_SERDES=y +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +# CONFIG_SERIAL_8250_FINTEK is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_EXAR=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_ASPEED_VUART is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_MOXA is not set +CONFIG_SERIAL_OF_PLATFORM=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_BCM63XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_SERIAL_DEV_BUS is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_XGS_IPROC_RNG=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +CONFIG_I2C_MUX_GPIO=y +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +CONFIG_I2C_MUX_PCA9541=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_MUX_PCA954X_DESELECT_ON_EXIT=y +CONFIG_I2C_MUX_REG=y +# CONFIG_I2C_MUX_MLXCPLD is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_XGS_IPROC is not set +CONFIG_SMBUS_XGS_IPROC=y +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +CONFIG_SPI_BCM_QSPI=y +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +CONFIG_GPIO_XGS_IPROC=y +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EXAR is not set +# CONFIG_GPIO_FTGPIO010 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_MPC8XXX is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZEVIO is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_TPIC2810 is not set + +# +# MFD GPIO expanders +# +# CONFIG_HTC_EGPIO is not set + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31722 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +CONFIG_SENSORS_LM70=y +CONFIG_SENSORS_LM73=y +CONFIG_SENSORS_LM75=y +CONFIG_SENSORS_LM77=y +CONFIG_SENSORS_LM78=y +CONFIG_SENSORS_LM80=y +CONFIG_SENSORS_LM83=y +CONFIG_SENSORS_LM85=y +CONFIG_SENSORS_LM87=y +CONFIG_SENSORS_LM90=y +CONFIG_SENSORS_LM92=y +CONFIG_SENSORS_LM93=y +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_QORIQ_THERMAL is not set + +# +# ACPI INT340X thermal drivers +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +# CONFIG_WATCHDOG_SYSFS is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +CONFIG_ARM_SP805_WATCHDOG=y +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_PM8XXX is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_DRM is not set + +# +# ACP (Audio CoProcessor) Configuration +# +# CONFIG_DRM_LIB_RANDOM is not set + +# +# Frame buffer Devices +# +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_SOUND is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_PCI=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +CONFIG_USB_DYNAMIC_MINORS=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_XGS_IPROC=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_XGS_IPROC=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +CONFIG_USBPHY_XGS_IPROC=y +# CONFIG_USB_XGS_IPROC_DRD is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_U_SERIAL_CONSOLE is not set + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +CONFIG_USB_XGS_IPROC_UDC=y +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set + +# +# USB Power Delivery and Type-C drivers +# +# CONFIG_TYPEC_UCSI is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_SDHCI_XGS_IPROC=y +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_USER is not set + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGERS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_SYSTOHC is not set +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS1307_HWMON=y +CONFIG_RTC_DRV_DS1307_CENTURY=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_R7301 is not set + +# +# HID Sensor RTC drivers +# +CONFIG_DMADEVICES=y +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_NBPFAXI_DMA is not set +CONFIG_PL330_DMA=y +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set + +# +# DMABUF options +# +# CONFIG_SYNC_FILE is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_HYPERV_TSCPAGE is not set +# CONFIG_STAGING is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_CLK_HSDK is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_NXP is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_PIC32 is not set +# CONFIG_COMMON_CLK_VC5 is not set +CONFIG_COMMON_CLK_IPROC=y +CONFIG_CLK_XGS_IPROC=y +# CONFIG_HWSPINLOCK is not set + +# +# Clock Source drivers +# +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_ARM_GLOBAL_TIMER=y +# CONFIG_ARM_TIMER_SP804 is not set +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_ARM_SMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_REMOTEPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# + +# +# Broadcom SoC drivers +# +# CONFIG_SOC_BRCMSTB is not set + +# +# i.MX SoC drivers +# + +# +# Qualcomm SoC drivers +# +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_NTB is not set +# CONFIG_VME_BUS is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +# CONFIG_RAS is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +# CONFIG_FPGA is not set + +# +# FSI support +# +# CONFIG_FSI is not set +# CONFIG_TEE is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# Tegra firmware driver +# + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +CONFIG_MANDATORY_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set +CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +# CONFIG_OVERLAY_FS_INDEX is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_ATIME_SUPPORT is not set +# CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_SECURITY=y +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_DECOMP_MULTI=y +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_V4 is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_SWAP=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_GDB_SCRIPTS is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_SOFTLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +CONFIG_DEBUG_PREEMPT=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_STACKTRACE is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DMA_API_DEBUG is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_MEMTEST is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_ARM_UNWIND=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_8250 is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=m +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_SEQIV is not set +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +CONFIG_CRYPTO_HMAC=m +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +CONFIG_CRYPTO_SHA256=m +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_DRBG_MENU=m +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +CONFIG_CRYPTO_DRBG=m +CONFIG_CRYPTO_JITTERENTROPY=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + +# +# Certificates for signature checking +# +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# CONFIG_ARM_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC4 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_XXHASH=y +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +# CONFIG_IRQ_POLL is not set +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +# CONFIG_SG_SPLIT is not set +CONFIG_SG_POOL=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set +# CONFIG_VIRTUALIZATION is not set diff --git a/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config index ad3795fc..8aa3ce13 100755 --- a/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config @@ -37,6 +37,7 @@ CONFIG_ZONE_DMA32=y CONFIG_AUDIT_ARCH=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_HAVE_INTEL_TXT=y CONFIG_X86_64_SMP=y CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_FIX_EARLYCON_MEM=y @@ -557,6 +558,7 @@ CONFIG_ARCH_ENABLE_THP_MIGRATION=y CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y +CONFIG_MMU_NOTIFIER=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y @@ -1708,10 +1710,10 @@ CONFIG_MD=y CONFIG_BLK_DEV_MD=y # CONFIG_MD_AUTODETECT is not set # CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID456 is not set +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BCACHE is not set @@ -1719,19 +1721,25 @@ CONFIG_BLK_DEV_DM_BUILTIN=y CONFIG_BLK_DEV_DM=y # CONFIG_DM_MQ_DEFAULT is not set # CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set +CONFIG_DM_BIO_PRISON=y +CONFIG_DM_PERSISTENT_DATA=y CONFIG_DM_CRYPT=y -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_THIN_PROVISIONING is not set +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=y # CONFIG_DM_CACHE is not set # CONFIG_DM_ERA is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_RAID is not set +CONFIG_DM_MIRROR=y +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_RAID=y # CONFIG_DM_ZERO is not set # CONFIG_DM_MULTIPATH is not set # CONFIG_DM_DELAY is not set -# CONFIG_DM_UEVENT is not set +CONFIG_DM_UEVENT=y # CONFIG_DM_FLAKEY is not set -# CONFIG_DM_VERITY is not set +CONFIG_DM_VERITY=y +# CONFIG_DM_VERITY_FEC is not set # CONFIG_DM_SWITCH is not set # CONFIG_DM_LOG_WRITES is not set # CONFIG_DM_INTEGRITY is not set @@ -2270,7 +2278,7 @@ CONFIG_DEVPORT=y # I2C support # CONFIG_I2C=y -# CONFIG_ACPI_I2C_OPREGION is not set +CONFIG_ACPI_I2C_OPREGION=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y @@ -2327,11 +2335,11 @@ CONFIG_I2C_PIIX4=y # CONFIG_I2C_DESIGNWARE_PCI is not set # CONFIG_I2C_EMEV2 is not set # CONFIG_I2C_GPIO is not set -# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OCORES=y CONFIG_I2C_PCA_PLATFORM=y # CONFIG_I2C_PXA_PCI is not set # CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX is not set +CONFIG_I2C_XILINX=y # # External I2C/SMBus adapter drivers @@ -2804,6 +2812,7 @@ CONFIG_MFD_CORE=y CONFIG_LPC_ICH=y CONFIG_LPC_SCH=y # CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_INTEL_SOC_PMIC_BXTWC is not set # CONFIG_INTEL_SOC_PMIC_CHTWC is not set CONFIG_MFD_INTEL_LPSS=y CONFIG_MFD_INTEL_LPSS_ACPI=y @@ -3411,15 +3420,16 @@ CONFIG_SYNC_FILE=y # CONFIG_SW_SYNC is not set # CONFIG_AUXDISPLAY is not set CONFIG_UIO=y -# CONFIG_UIO_CIF is not set -# CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_DMEM_GENIRQ is not set +CONFIG_UIO_CIF=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_DMEM_GENIRQ=y # CONFIG_UIO_AEC is not set # CONFIG_UIO_SERCOS3 is not set -# CONFIG_UIO_PCI_GENERIC is not set +CONFIG_UIO_PCI_GENERIC=y # CONFIG_UIO_NETX is not set # CONFIG_UIO_PRUSS is not set # CONFIG_UIO_MF624 is not set +# CONFIG_VFIO is not set CONFIG_VIRT_DRIVERS=y CONFIG_VIRTIO=y @@ -3463,9 +3473,10 @@ CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_INTEL_RST is not set # CONFIG_INTEL_SMARTCONNECT is not set # CONFIG_PVPANIC is not set -# CONFIG_INTEL_PMC_IPC is not set +CONFIG_INTEL_PMC_IPC=y # CONFIG_SURFACE_PRO3_BUTTON is not set -# CONFIG_INTEL_PUNIT_IPC is not set +CONFIG_INTEL_PUNIT_IPC=y +CONFIG_INTEL_TELEMETRY=y # CONFIG_MLX_PLATFORM is not set # CONFIG_MLX_CPLD_PLATFORM is not set # CONFIG_INTEL_TURBO_MAX_3 is not set @@ -3500,14 +3511,21 @@ CONFIG_CLKBLD_I8253=y CONFIG_MAILBOX=y CONFIG_PCC=y # CONFIG_ALTERA_MBOX is not set +CONFIG_IOMMU_API=y CONFIG_IOMMU_SUPPORT=y # # Generic IOMMU Pagetable Support # -# CONFIG_AMD_IOMMU is not set -# CONFIG_INTEL_IOMMU is not set -# CONFIG_IRQ_REMAP is not set +CONFIG_IOMMU_IOVA=y +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_V2=y +CONFIG_DMAR_TABLE=y +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_SVM is not set +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_FLOPPY_WA=y +CONFIG_IRQ_REMAP=y # # Remoteproc drivers @@ -4017,6 +4035,7 @@ CONFIG_PROVIDE_OHCI1394_DMA_INIT=y # CONFIG_INTERVAL_TREE_TEST is not set # CONFIG_PERCPU_TEST is not set # CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set # CONFIG_TEST_HEXDUMP is not set # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set @@ -4095,6 +4114,7 @@ CONFIG_SECURITY_NETWORK=y CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_SECURITY_NETWORK_XFRM is not set # CONFIG_SECURITY_PATH is not set +# CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y # CONFIG_HARDENED_USERCOPY is not set # CONFIG_FORTIFY_SOURCE is not set @@ -4112,6 +4132,12 @@ CONFIG_INTEGRITY_AUDIT=y # CONFIG_EVM is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ASYNC_PQ=y +CONFIG_ASYNC_RAID6_RECOV=y CONFIG_CRYPTO=y # @@ -4301,6 +4327,7 @@ CONFIG_BINARY_PRINTF=y # # Library routines # +CONFIG_RAID6_PQ=y CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_RATIONAL=y diff --git a/packages/base/any/kernels/4.14-lts/patches/brcm-iproc-4.14.patch b/packages/base/any/kernels/4.14-lts/patches/brcm-iproc-4.14.patch new file mode 100644 index 00000000..d2023acb --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/patches/brcm-iproc-4.14.patch @@ -0,0 +1,32416 @@ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/Kconfig b/arch/arm/Kconfig +--- a/arch/arm/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm/Kconfig 2018-05-10 11:31:28.281398222 +0800 +@@ -759,6 +759,8 @@ source "arch/arm/mach-iop33x/Kconfig" + + source "arch/arm/mach-iop13xx/Kconfig" + ++source "arch/arm/mach-iproc/Kconfig" ++ + source "arch/arm/mach-ixp4xx/Kconfig" + + source "arch/arm/mach-keystone/Kconfig" +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/Makefile b/arch/arm/Makefile +--- a/arch/arm/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm/Makefile 2018-05-10 11:31:28.281398222 +0800 +@@ -177,6 +177,7 @@ machine-$(CONFIG_ARCH_INTEGRATOR) += int + machine-$(CONFIG_ARCH_IOP13XX) += iop13xx + machine-$(CONFIG_ARCH_IOP32X) += iop32x + machine-$(CONFIG_ARCH_IOP33X) += iop33x ++machine-$(CONFIG_ARCH_XGS_IPROC) += iproc + machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx + machine-$(CONFIG_ARCH_KEYSTONE) += keystone + machine-$(CONFIG_ARCH_KS8695) += ks8695 +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/compressed/ashldi3.S b/arch/arm/boot/compressed/ashldi3.S +--- a/arch/arm/boot/compressed/ashldi3.S 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/compressed/ashldi3.S 2018-02-27 17:12:26.660706150 +0800 +@@ -0,0 +1,54 @@ ++/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 ++ Free Software Foundation, Inc. ++ ++This file is free software; you can 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, or (at your option) any ++later version. ++ ++In addition to the permissions in the GNU General Public License, the ++Free Software Foundation gives you unlimited permission to link the ++compiled version of this file into combinations with other programs, ++and to distribute those combinations without any restriction coming ++from the use of this file. (The General Public License restrictions ++do apply in other respects; for example, they cover modification of ++the file, and distribution when not linked into a combine ++executable.) ++ ++This file is distributed in the hope that it will be useful, but ++WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; see the file COPYING. If not, write to ++the Free Software Foundation, 51 Franklin Street, Fifth Floor, ++Boston, MA 02110-1301, USA. */ ++ ++ ++#include ++#include ++ ++#ifdef __ARMEB__ ++#define al r1 ++#define ah r0 ++#else ++#define al r0 ++#define ah r1 ++#endif ++ ++ENTRY(__ashldi3) ++ENTRY(__aeabi_llsl) ++ ++ subs r3, r2, #32 ++ rsb ip, r2, #32 ++ movmi ah, ah, lsl r2 ++ movpl ah, al, lsl r3 ++ ARM( orrmi ah, ah, al, lsr ip ) ++ THUMB( lsrmi r3, al, ip ) ++ THUMB( orrmi ah, ah, r3 ) ++ mov al, al, lsl r2 ++ ret lr ++ ++ENDPROC(__ashldi3) ++ENDPROC(__aeabi_llsl) +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/compressed/bswapsdi2.S b/arch/arm/boot/compressed/bswapsdi2.S +--- a/arch/arm/boot/compressed/bswapsdi2.S 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/compressed/bswapsdi2.S 2018-02-27 17:12:26.688706343 +0800 +@@ -0,0 +1,38 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#include ++#include ++ ++#if __LINUX_ARM_ARCH__ >= 6 ++ENTRY(__bswapsi2) ++ rev r0, r0 ++ bx lr ++ENDPROC(__bswapsi2) ++ ++ENTRY(__bswapdi2) ++ rev r3, r0 ++ rev r0, r1 ++ mov r1, r3 ++ bx lr ++ENDPROC(__bswapdi2) ++#else ++ENTRY(__bswapsi2) ++ eor r3, r0, r0, ror #16 ++ mov r3, r3, lsr #8 ++ bic r3, r3, #0xff00 ++ eor r0, r3, r0, ror #8 ++ ret lr ++ENDPROC(__bswapsi2) ++ ++ENTRY(__bswapdi2) ++ mov ip, r1 ++ eor r3, ip, ip, ror #16 ++ eor r1, r0, r0, ror #16 ++ mov r1, r1, lsr #8 ++ mov r3, r3, lsr #8 ++ bic r3, r3, #0xff00 ++ bic r1, r1, #0xff00 ++ eor r1, r1, r0, ror #8 ++ eor r0, r3, ip, ror #8 ++ ret lr ++ENDPROC(__bswapdi2) ++#endif +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/compressed/hyp-stub.S b/arch/arm/boot/compressed/hyp-stub.S +--- a/arch/arm/boot/compressed/hyp-stub.S 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/compressed/hyp-stub.S 2018-02-27 17:12:26.604705764 +0800 +@@ -0,0 +1,285 @@ ++/* ++ * Copyright (c) 2012 Linaro Limited. ++ * ++ * This program is free software; you can 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 ++ ++#ifndef ZIMAGE ++/* ++ * For the kernel proper, we need to find out the CPU boot mode long after ++ * boot, so we need to store it in a writable variable. ++ * ++ * This is not in .bss, because we set it sufficiently early that the boot-time ++ * zeroing of .bss would clobber it. ++ */ ++.data ++ .align 2 ++ENTRY(__boot_cpu_mode) ++ .long 0 ++.text ++ ++ /* ++ * Save the primary CPU boot mode. Requires 3 scratch registers. ++ */ ++ .macro store_primary_cpu_mode reg1, reg2, reg3 ++ mrs \reg1, cpsr ++ and \reg1, \reg1, #MODE_MASK ++ adr \reg2, .L__boot_cpu_mode_offset ++ ldr \reg3, [\reg2] ++ str \reg1, [\reg2, \reg3] ++ .endm ++ ++ /* ++ * Compare the current mode with the one saved on the primary CPU. ++ * If they don't match, record that fact. The Z bit indicates ++ * if there's a match or not. ++ * Requires 3 additionnal scratch registers. ++ */ ++ .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3 ++ adr \reg2, .L__boot_cpu_mode_offset ++ ldr \reg3, [\reg2] ++ ldr \reg1, [\reg2, \reg3] ++ cmp \mode, \reg1 @ matches primary CPU boot mode? ++ orrne \reg1, \reg1, #BOOT_CPU_MODE_MISMATCH ++ strne \reg1, [\reg2, \reg3] @ record what happened and give up ++ .endm ++ ++#else /* ZIMAGE */ ++ ++ .macro store_primary_cpu_mode reg1:req, reg2:req, reg3:req ++ .endm ++ ++/* ++ * The zImage loader only runs on one CPU, so we don't bother with mult-CPU ++ * consistency checking: ++ */ ++ .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3 ++ cmp \mode, \mode ++ .endm ++ ++#endif /* ZIMAGE */ ++ ++/* ++ * Hypervisor stub installation functions. ++ * ++ * These must be called with the MMU and D-cache off. ++ * They are not ABI compliant and are only intended to be called from the kernel ++ * entry points in head.S. ++ */ ++@ Call this from the primary CPU ++ENTRY(__hyp_stub_install) ++ store_primary_cpu_mode r4, r5, r6 ++ENDPROC(__hyp_stub_install) ++ ++ @ fall through... ++ ++@ Secondary CPUs should call here ++ENTRY(__hyp_stub_install_secondary) ++ mrs r4, cpsr ++ and r4, r4, #MODE_MASK ++ ++ /* ++ * If the secondary has booted with a different mode, give up ++ * immediately. ++ */ ++ compare_cpu_mode_with_primary r4, r5, r6, r7 ++ retne lr ++ ++ /* ++ * Once we have given up on one CPU, we do not try to install the ++ * stub hypervisor on the remaining ones: because the saved boot mode ++ * is modified, it can't compare equal to the CPSR mode field any ++ * more. ++ * ++ * Otherwise... ++ */ ++ ++ cmp r4, #HYP_MODE ++ retne lr @ give up if the CPU is not in HYP mode ++ ++/* ++ * Configure HSCTLR to set correct exception endianness/instruction set ++ * state etc. ++ * Turn off all traps ++ * Eventually, CPU-specific code might be needed -- assume not for now ++ * ++ * This code relies on the "eret" instruction to synchronize the ++ * various coprocessor accesses. This is done when we switch to SVC ++ * (see safe_svcmode_maskall). ++ */ ++ @ Now install the hypervisor stub: ++ W(adr) r7, __hyp_stub_vectors ++ mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR) ++ ++ @ Disable all traps, so we don't get any nasty surprise ++ mov r7, #0 ++ mcr p15, 4, r7, c1, c1, 0 @ HCR ++ mcr p15, 4, r7, c1, c1, 2 @ HCPTR ++ mcr p15, 4, r7, c1, c1, 3 @ HSTR ++ ++THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE ++ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE ++ mcr p15, 4, r7, c1, c0, 0 @ HSCTLR ++ ++ mrc p15, 4, r7, c1, c1, 1 @ HDCR ++ and r7, #0x1f @ Preserve HPMN ++ mcr p15, 4, r7, c1, c1, 1 @ HDCR ++ ++ @ Make sure NS-SVC is initialised appropriately ++ mrc p15, 0, r7, c1, c0, 0 @ SCTLR ++ orr r7, #(1 << 5) @ CP15 barriers enabled ++ bic r7, #(3 << 7) @ Clear SED/ITD for v8 (RES0 for v7) ++ bic r7, #(3 << 19) @ WXN and UWXN disabled ++ mcr p15, 0, r7, c1, c0, 0 @ SCTLR ++ ++ mrc p15, 0, r7, c0, c0, 0 @ MIDR ++ mcr p15, 4, r7, c0, c0, 0 @ VPIDR ++ ++ mrc p15, 0, r7, c0, c0, 5 @ MPIDR ++ mcr p15, 4, r7, c0, c0, 5 @ VMPIDR ++ ++#if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER) ++ @ make CNTP_* and CNTPCT accessible from PL1 ++ mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1 ++ lsr r7, #16 ++ and r7, #0xf ++ cmp r7, #1 ++ bne 1f ++ mrc p15, 4, r7, c14, c1, 0 @ CNTHCTL ++ orr r7, r7, #3 @ PL1PCEN | PL1PCTEN ++ mcr p15, 4, r7, c14, c1, 0 @ CNTHCTL ++ mov r7, #0 ++ mcrr p15, 4, r7, r7, c14 @ CNTVOFF ++ ++ @ Disable virtual timer in case it was counting ++ mrc p15, 0, r7, c14, c3, 1 @ CNTV_CTL ++ bic r7, #1 @ Clear ENABLE ++ mcr p15, 0, r7, c14, c3, 1 @ CNTV_CTL ++1: ++#endif ++ ++#ifdef CONFIG_ARM_GIC_V3 ++ @ Check whether GICv3 system registers are available ++ mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1 ++ ubfx r7, r7, #28, #4 ++ cmp r7, #1 ++ bne 2f ++ ++ @ Enable system register accesses ++ mrc p15, 4, r7, c12, c9, 5 @ ICC_HSRE ++ orr r7, r7, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE) ++ mcr p15, 4, r7, c12, c9, 5 @ ICC_HSRE ++ isb ++ ++ @ SRE bit could be forced to 0 by firmware. ++ @ Check whether it sticks before accessing any other sysreg ++ mrc p15, 4, r7, c12, c9, 5 @ ICC_HSRE ++ tst r7, #ICC_SRE_EL2_SRE ++ beq 2f ++ mov r7, #0 ++ mcr p15, 4, r7, c12, c11, 0 @ ICH_HCR ++2: ++#endif ++ ++ bx lr @ The boot CPU mode is left in r4. ++ENDPROC(__hyp_stub_install_secondary) ++ ++__hyp_stub_do_trap: ++ teq r0, #HVC_SET_VECTORS ++ bne 1f ++ mcr p15, 4, r1, c12, c0, 0 @ set HVBAR ++ b __hyp_stub_exit ++ ++1: teq r0, #HVC_SOFT_RESTART ++ bne 1f ++ bx r1 ++ ++1: teq r0, #HVC_RESET_VECTORS ++ beq __hyp_stub_exit ++ ++ ldr r0, =HVC_STUB_ERR ++ __ERET ++ ++__hyp_stub_exit: ++ mov r0, #0 ++ __ERET ++ENDPROC(__hyp_stub_do_trap) ++ ++/* ++ * __hyp_set_vectors: Call this after boot to set the initial hypervisor ++ * vectors as part of hypervisor installation. On an SMP system, this should ++ * be called on each CPU. ++ * ++ * r0 must be the physical address of the new vector table (which must lie in ++ * the bottom 4GB of physical address space. ++ * ++ * r0 must be 32-byte aligned. ++ * ++ * Before calling this, you must check that the stub hypervisor is installed ++ * everywhere, by waiting for any secondary CPUs to be brought up and then ++ * checking that BOOT_CPU_MODE_HAVE_HYP(__boot_cpu_mode) is true. ++ * ++ * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or ++ * something else went wrong... in such cases, trying to install a new ++ * hypervisor is unlikely to work as desired. ++ * ++ * When you call into your shiny new hypervisor, sp_hyp will contain junk, ++ * so you will need to set that to something sensible at the new hypervisor's ++ * initialisation entry point. ++ */ ++ENTRY(__hyp_set_vectors) ++ mov r1, r0 ++ mov r0, #HVC_SET_VECTORS ++ __HVC(0) ++ ret lr ++ENDPROC(__hyp_set_vectors) ++ ++ENTRY(__hyp_soft_restart) ++ mov r1, r0 ++ mov r0, #HVC_SOFT_RESTART ++ __HVC(0) ++ ret lr ++ENDPROC(__hyp_soft_restart) ++ ++ENTRY(__hyp_reset_vectors) ++ mov r0, #HVC_RESET_VECTORS ++ __HVC(0) ++ ret lr ++ENDPROC(__hyp_reset_vectors) ++ ++#ifndef ZIMAGE ++.align 2 ++.L__boot_cpu_mode_offset: ++ .long __boot_cpu_mode - . ++#endif ++ ++.align 5 ++ENTRY(__hyp_stub_vectors) ++__hyp_stub_reset: W(b) . ++__hyp_stub_und: W(b) . ++__hyp_stub_svc: W(b) . ++__hyp_stub_pabort: W(b) . ++__hyp_stub_dabort: W(b) . ++__hyp_stub_trap: W(b) __hyp_stub_do_trap ++__hyp_stub_irq: W(b) . ++__hyp_stub_fiq: W(b) . ++ENDPROC(__hyp_stub_vectors) ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/compressed/lib1funcs.S b/arch/arm/boot/compressed/lib1funcs.S +--- a/arch/arm/boot/compressed/lib1funcs.S 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/compressed/lib1funcs.S 2018-02-27 17:12:26.632705957 +0800 +@@ -0,0 +1,371 @@ ++/* ++ * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines ++ * ++ * Author: Nicolas Pitre ++ * - contributed to gcc-3.4 on Sep 30, 2003 ++ * - adapted for the Linux kernel on Oct 2, 2003 ++ */ ++ ++/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. ++ ++This file is free software; you can 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, or (at your option) any ++later version. ++ ++In addition to the permissions in the GNU General Public License, the ++Free Software Foundation gives you unlimited permission to link the ++compiled version of this file into combinations with other programs, ++and to distribute those combinations without any restriction coming ++from the use of this file. (The General Public License restrictions ++do apply in other respects; for example, they cover modification of ++the file, and distribution when not linked into a combine ++executable.) ++ ++This file is distributed in the hope that it will be useful, but ++WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; see the file COPYING. If not, write to ++the Free Software Foundation, 59 Temple Place - Suite 330, ++Boston, MA 02111-1307, USA. */ ++ ++ ++#include ++#include ++#include ++ ++.macro ARM_DIV_BODY dividend, divisor, result, curbit ++ ++#if __LINUX_ARM_ARCH__ >= 5 ++ ++ clz \curbit, \divisor ++ clz \result, \dividend ++ sub \result, \curbit, \result ++ mov \curbit, #1 ++ mov \divisor, \divisor, lsl \result ++ mov \curbit, \curbit, lsl \result ++ mov \result, #0 ++ ++#else ++ ++ @ Initially shift the divisor left 3 bits if possible, ++ @ set curbit accordingly. This allows for curbit to be located ++ @ at the left end of each 4 bit nibbles in the division loop ++ @ to save one loop in most cases. ++ tst \divisor, #0xe0000000 ++ moveq \divisor, \divisor, lsl #3 ++ moveq \curbit, #8 ++ movne \curbit, #1 ++ ++ @ Unless the divisor is very big, shift it up in multiples of ++ @ four bits, since this is the amount of unwinding in the main ++ @ division loop. Continue shifting until the divisor is ++ @ larger than the dividend. ++1: cmp \divisor, #0x10000000 ++ cmplo \divisor, \dividend ++ movlo \divisor, \divisor, lsl #4 ++ movlo \curbit, \curbit, lsl #4 ++ blo 1b ++ ++ @ For very big divisors, we must shift it a bit at a time, or ++ @ we will be in danger of overflowing. ++1: cmp \divisor, #0x80000000 ++ cmplo \divisor, \dividend ++ movlo \divisor, \divisor, lsl #1 ++ movlo \curbit, \curbit, lsl #1 ++ blo 1b ++ ++ mov \result, #0 ++ ++#endif ++ ++ @ Division loop ++1: cmp \dividend, \divisor ++ subhs \dividend, \dividend, \divisor ++ orrhs \result, \result, \curbit ++ cmp \dividend, \divisor, lsr #1 ++ subhs \dividend, \dividend, \divisor, lsr #1 ++ orrhs \result, \result, \curbit, lsr #1 ++ cmp \dividend, \divisor, lsr #2 ++ subhs \dividend, \dividend, \divisor, lsr #2 ++ orrhs \result, \result, \curbit, lsr #2 ++ cmp \dividend, \divisor, lsr #3 ++ subhs \dividend, \dividend, \divisor, lsr #3 ++ orrhs \result, \result, \curbit, lsr #3 ++ cmp \dividend, #0 @ Early termination? ++ movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? ++ movne \divisor, \divisor, lsr #4 ++ bne 1b ++ ++.endm ++ ++ ++.macro ARM_DIV2_ORDER divisor, order ++ ++#if __LINUX_ARM_ARCH__ >= 5 ++ ++ clz \order, \divisor ++ rsb \order, \order, #31 ++ ++#else ++ ++ cmp \divisor, #(1 << 16) ++ movhs \divisor, \divisor, lsr #16 ++ movhs \order, #16 ++ movlo \order, #0 ++ ++ cmp \divisor, #(1 << 8) ++ movhs \divisor, \divisor, lsr #8 ++ addhs \order, \order, #8 ++ ++ cmp \divisor, #(1 << 4) ++ movhs \divisor, \divisor, lsr #4 ++ addhs \order, \order, #4 ++ ++ cmp \divisor, #(1 << 2) ++ addhi \order, \order, #3 ++ addls \order, \order, \divisor, lsr #1 ++ ++#endif ++ ++.endm ++ ++ ++.macro ARM_MOD_BODY dividend, divisor, order, spare ++ ++#if __LINUX_ARM_ARCH__ >= 5 ++ ++ clz \order, \divisor ++ clz \spare, \dividend ++ sub \order, \order, \spare ++ mov \divisor, \divisor, lsl \order ++ ++#else ++ ++ mov \order, #0 ++ ++ @ Unless the divisor is very big, shift it up in multiples of ++ @ four bits, since this is the amount of unwinding in the main ++ @ division loop. Continue shifting until the divisor is ++ @ larger than the dividend. ++1: cmp \divisor, #0x10000000 ++ cmplo \divisor, \dividend ++ movlo \divisor, \divisor, lsl #4 ++ addlo \order, \order, #4 ++ blo 1b ++ ++ @ For very big divisors, we must shift it a bit at a time, or ++ @ we will be in danger of overflowing. ++1: cmp \divisor, #0x80000000 ++ cmplo \divisor, \dividend ++ movlo \divisor, \divisor, lsl #1 ++ addlo \order, \order, #1 ++ blo 1b ++ ++#endif ++ ++ @ Perform all needed subtractions to keep only the reminder. ++ @ Do comparisons in batch of 4 first. ++ subs \order, \order, #3 @ yes, 3 is intended here ++ blt 2f ++ ++1: cmp \dividend, \divisor ++ subhs \dividend, \dividend, \divisor ++ cmp \dividend, \divisor, lsr #1 ++ subhs \dividend, \dividend, \divisor, lsr #1 ++ cmp \dividend, \divisor, lsr #2 ++ subhs \dividend, \dividend, \divisor, lsr #2 ++ cmp \dividend, \divisor, lsr #3 ++ subhs \dividend, \dividend, \divisor, lsr #3 ++ cmp \dividend, #1 ++ mov \divisor, \divisor, lsr #4 ++ subges \order, \order, #4 ++ bge 1b ++ ++ tst \order, #3 ++ teqne \dividend, #0 ++ beq 5f ++ ++ @ Either 1, 2 or 3 comparison/subtractions are left. ++2: cmn \order, #2 ++ blt 4f ++ beq 3f ++ cmp \dividend, \divisor ++ subhs \dividend, \dividend, \divisor ++ mov \divisor, \divisor, lsr #1 ++3: cmp \dividend, \divisor ++ subhs \dividend, \dividend, \divisor ++ mov \divisor, \divisor, lsr #1 ++4: cmp \dividend, \divisor ++ subhs \dividend, \dividend, \divisor ++5: ++.endm ++ ++ ++#ifdef CONFIG_ARM_PATCH_IDIV ++ .align 3 ++#endif ++ ++ENTRY(__udivsi3) ++ENTRY(__aeabi_uidiv) ++UNWIND(.fnstart) ++ ++ subs r2, r1, #1 ++ reteq lr ++ bcc Ldiv0 ++ cmp r0, r1 ++ bls 11f ++ tst r1, r2 ++ beq 12f ++ ++ ARM_DIV_BODY r0, r1, r2, r3 ++ ++ mov r0, r2 ++ ret lr ++ ++11: moveq r0, #1 ++ movne r0, #0 ++ ret lr ++ ++12: ARM_DIV2_ORDER r1, r2 ++ ++ mov r0, r0, lsr r2 ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__udivsi3) ++ENDPROC(__aeabi_uidiv) ++ ++ENTRY(__umodsi3) ++UNWIND(.fnstart) ++ ++ subs r2, r1, #1 @ compare divisor with 1 ++ bcc Ldiv0 ++ cmpne r0, r1 @ compare dividend with divisor ++ moveq r0, #0 ++ tsthi r1, r2 @ see if divisor is power of 2 ++ andeq r0, r0, r2 ++ retls lr ++ ++ ARM_MOD_BODY r0, r1, r2, r3 ++ ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__umodsi3) ++ ++#ifdef CONFIG_ARM_PATCH_IDIV ++ .align 3 ++#endif ++ ++ENTRY(__divsi3) ++ENTRY(__aeabi_idiv) ++UNWIND(.fnstart) ++ ++ cmp r1, #0 ++ eor ip, r0, r1 @ save the sign of the result. ++ beq Ldiv0 ++ rsbmi r1, r1, #0 @ loops below use unsigned. ++ subs r2, r1, #1 @ division by 1 or -1 ? ++ beq 10f ++ movs r3, r0 ++ rsbmi r3, r0, #0 @ positive dividend value ++ cmp r3, r1 ++ bls 11f ++ tst r1, r2 @ divisor is power of 2 ? ++ beq 12f ++ ++ ARM_DIV_BODY r3, r1, r0, r2 ++ ++ cmp ip, #0 ++ rsbmi r0, r0, #0 ++ ret lr ++ ++10: teq ip, r0 @ same sign ? ++ rsbmi r0, r0, #0 ++ ret lr ++ ++11: movlo r0, #0 ++ moveq r0, ip, asr #31 ++ orreq r0, r0, #1 ++ ret lr ++ ++12: ARM_DIV2_ORDER r1, r2 ++ ++ cmp ip, #0 ++ mov r0, r3, lsr r2 ++ rsbmi r0, r0, #0 ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__divsi3) ++ENDPROC(__aeabi_idiv) ++ ++ENTRY(__modsi3) ++UNWIND(.fnstart) ++ ++ cmp r1, #0 ++ beq Ldiv0 ++ rsbmi r1, r1, #0 @ loops below use unsigned. ++ movs ip, r0 @ preserve sign of dividend ++ rsbmi r0, r0, #0 @ if negative make positive ++ subs r2, r1, #1 @ compare divisor with 1 ++ cmpne r0, r1 @ compare dividend with divisor ++ moveq r0, #0 ++ tsthi r1, r2 @ see if divisor is power of 2 ++ andeq r0, r0, r2 ++ bls 10f ++ ++ ARM_MOD_BODY r0, r1, r2, r3 ++ ++10: cmp ip, #0 ++ rsbmi r0, r0, #0 ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__modsi3) ++ ++#ifdef CONFIG_AEABI ++ ++ENTRY(__aeabi_uidivmod) ++UNWIND(.fnstart) ++UNWIND(.save {r0, r1, ip, lr} ) ++ ++ stmfd sp!, {r0, r1, ip, lr} ++ bl __aeabi_uidiv ++ ldmfd sp!, {r1, r2, ip, lr} ++ mul r3, r0, r2 ++ sub r1, r1, r3 ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__aeabi_uidivmod) ++ ++ENTRY(__aeabi_idivmod) ++UNWIND(.fnstart) ++UNWIND(.save {r0, r1, ip, lr} ) ++ stmfd sp!, {r0, r1, ip, lr} ++ bl __aeabi_idiv ++ ldmfd sp!, {r1, r2, ip, lr} ++ mul r3, r0, r2 ++ sub r1, r1, r3 ++ ret lr ++ ++UNWIND(.fnend) ++ENDPROC(__aeabi_idivmod) ++ ++#endif ++ ++Ldiv0: ++UNWIND(.fnstart) ++UNWIND(.pad #4) ++UNWIND(.save {lr}) ++ str lr, [sp, #-8]! ++ bl __div0 ++ mov r0, #0 @ About as wrong as it could be. ++ ldr pc, [sp], #8 ++UNWIND(.fnend) ++ENDPROC(Ldiv0) +Binary files a/arch/arm/boot/compressed/piggy_data and b/arch/arm/boot/compressed/piggy_data differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm/boot/dts/Makefile 2018-05-10 11:31:28.285398226 +0800 +@@ -1069,6 +1069,24 @@ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dt + dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ + aspeed-bmc-opp-romulus.dtb \ + aspeed-ast2500-evb.dtb ++dtb-$(CONFIG_MACH_HX4) += bcm956340.dtb ++dtb-$(CONFIG_MACH_KT2) += bcm956450.dtb ++dtb-$(CONFIG_MACH_GH) += bcm95341x.dtb ++dtb-$(CONFIG_MACH_GH2) += bcm956170.dtb ++dtb-$(CONFIG_MACH_SB2) += bcm956260.dtb ++dtb-$(CONFIG_MACH_HR3) += \ ++ bcm956160.dtb \ ++ bcm953444.dtb ++dtb-$(CONFIG_MACH_WH2) += bcm953547.dtb ++dtb-$(CONFIG_XGS_IPROC_ARM32_PLATFORM) += \ ++ bcm956340.dtb \ ++ bcm956450.dtb \ ++ bcm95341x.dtb \ ++ bcm956260.dtb \ ++ bcm956160.dtb \ ++ bcm953444.dtb \ ++ bcm956170.dtb \ ++ bcm953547.dtb + endif + + dtstree := $(srctree)/$(src) +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-greyhound.dtsi b/arch/arm/boot/dts/bcm-greyhound.dtsi +--- a/arch/arm/boot/dts/bcm-greyhound.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-greyhound.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,408 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom GH iProc"; ++ compatible = "brcm,greyhound"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ /*clocks = <&osc_50M>;*/ /* 50MHZ crystal/oscillator */ ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ /* 50MHZ crystal/oscillator clock source */ ++ /* ++ osc_50M: oscillator_50M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <50000000>; ++ }; ++ */ ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@0x1800fc00 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk"; ++ clocks = <&osc>; ++ reg = <0x1800fc00 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18020000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18021000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18021000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18042000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18042000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@1800a000 { ++ compatible = "brcm,iproc-gpio-ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x1800a000 0x50>; ++ ngpios = <12>; ++ pin-reg-bit-shift = <4>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy0 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-gh"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18111000 0x1000>; ++ vbus-gpio = <&gpio_ccg 6 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@18048000 { ++ compatible = "generic-ehci"; ++ reg = <0x18048000 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@18048800 { ++ compatible = "generic-ohci"; ++ reg = <0x18048800 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ /* Over Current Protect Mode fix */ ++ iproc-ocpm-fix; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@1804c000 { ++ compatible = "brcm,usbd-xgs-iproc"; ++ reg = <0x1804c000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18046000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18046000 0x600>, ++ <0xf8105408 0x10>, ++ <0x18046f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18047200 0x188>, ++ <0x18047000 0x124>, ++ <0xf8106408 0x004>, ++ <0x180473a0 0x01c>, ++ <0x1800e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18008000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18008000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_ext: mdio_ext@03210000 { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <2>; ++ bus-type = "external"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ pnor_flash: pnor_flash@18045000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "brcm,iproc-nor"; ++ reg = nor_regs: <0x18045000 0x1000>, ++ nor_mem: <0xE8000000 0x8000000>, ++ nor_strap: <0x18000a5c 0x4>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18032000 { ++ compatible = "brcm,iproc-rng200"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18032000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18009000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18009000 0x1000>, ++ iproc_reset_reg: <0x1800f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18040000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18040000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@03200000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x03200000 0x100000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x20000000, ++ * cpu addr 0x20000000, size 0x0 0x20000000 ++ */ ++ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; ++ wa-list = "pcie_rc", "pcie_perst"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1800f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0x1800f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0x1800fc00 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ reg = idm0: <0x18100000 0x100000>, ++ idm1: <0xf8100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-greyhound2.dtsi b/arch/arm/boot/dts/bcm-greyhound2.dtsi +--- a/arch/arm/boot/dts/bcm-greyhound2.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-greyhound2.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,429 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom GH2 iProc"; ++ compatible = "brcm,greyhound2"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@0x1800fc00 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk"; ++ clocks = <&osc>; ++ reg = <0x1800fc00 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18020000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18021000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18021000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18042000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18042000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@1804a000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x1804a000 0x1000>, ++ <0x1811f000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@1800a000 { ++ compatible = "brcm,iproc-gpio-ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x1800a000 0x50>; ++ ngpios = <12>; ++ pin-reg-bit-shift = <4>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy0 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-gh2"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18111000 0x1000>, ++ idm_utmih: <0x18049500 0x100>; ++ vbus-gpio = <&gpio_ccg 6 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@18048000 { ++ compatible = "generic-ehci"; ++ reg = <0x18048000 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@18048800 { ++ compatible = "generic-ohci"; ++ reg = <0x18048800 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ /* Over Current Protect Mode fix */ ++ iproc-ocpm-fix; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@1804c000 { ++ compatible = "brcm,usbd-xgs-iproc"; ++ reg = <0x1804c000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18046000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18046000 0x600>, ++ <0xf8105408 0x10>, ++ <0x18046f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18047200 0x188>, ++ <0x18047000 0x124>, ++ <0xf8106408 0x004>, ++ <0x180473a0 0x01c>, ++ <0x1800e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18008000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18008000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ ccg_mdio_int: ccg_mdio_int@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_int: mdio_int@03210000 { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_ext: mdio_ext@03210000 { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <2>; ++ bus-type = "external"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ pnor_flash: pnor_flash@18045000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "brcm,iproc-nor"; ++ reg = nor_regs: <0x18045000 0x1000>, ++ nor_mem: <0xE8000000 0x8000000>, ++ nor_strap: <0x18000a5c 0x4>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18032000 { ++ compatible = "brcm,iproc-rng200"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18032000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18009000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18009000 0x1000>, ++ iproc_reset_reg: <0x1800f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18018000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18018000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ crypto: crypto@03100000 { ++ compatible = "brcm,iproc-crypto"; ++ reg = axi: <0x03100000 0x100>, /* SPUM AXI registers */ ++ apb: <0x18037000 0x100>, /* SPUM control registers */ ++ idm: <0x1811a000 0x1000>; /* Crypto control registers */ ++ brcm,max-pkt-size = <65536>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@03200000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x03200000 0x100000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x20000000, ++ * cpu addr 0x20000000, size 0x0 0x20000000 ++ */ ++ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; ++ wa-list = "pcie_rc", "pcie_perst"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1800f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0x1800f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0x1800fc00 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ reg = idm0: <0x18100000 0x100000>, ++ idm1: <0xf8100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-helix4.dtsi b/arch/arm/boot/dts/bcm-helix4.dtsi +--- a/arch/arm/boot/dts/bcm-helix4.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-helix4.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,483 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom HX4 iProc"; ++ compatible = "brcm,helix4"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ enable-method = "brcm,bcm-nsp-smp"; ++ secondary-boot-reg = <0xffff042c>; ++ reg = <0x1>; ++ }; ++ }; ++ ++ mpcore { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ /*arm,parity-enable; ++ interrupts = ;*/ ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@0x1803fc00 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk", "axi-clk-hx4"; ++ clocks = <&osc>; ++ reg = <0x1803fc00 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18000300 { ++ compatible = "ns16550a"; ++ reg = <0x18000300 0x100>; ++ interrupts = ; ++ clock-frequency = <62500000>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18000400 { ++ compatible = "ns16550a"; ++ reg = <0x18000400 0x100>; ++ interrupts = ; ++ clock-frequency = <62500000>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@18037000 { ++ compatible = "ns16550a"; ++ reg = <0x18037000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_cca: gpio@18000060 { ++ compatible = "brcm,iproc-gpio-cca"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x18000060 0x50>, ++ intr: <0x18000000 0x50>; ++ ngpios = <8>; ++ pin-reg-bit-shift = <0>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18022000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18022000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@18023000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18023000 0x1000>, ++ <0x18111000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18026000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18026000 0x600>, ++ <0x1811b408 0x10>, ++ <0x18026f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ }; ++ ++ qspi: spi@18027000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18027200 0x188>, ++ <0x18027000 0x124>, ++ <0x1811c408 0x004>, ++ <0x180273a0 0x01c>, ++ <0x1803e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = ++ "spi_lr_fullness_reached", ++ "spi_lr_session_aborted", ++ "spi_lr_impatient", ++ "spi_lr_session_done", ++ "spi_lr_overread", ++ "mspi_done", ++ "mspi_halted"; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy0 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-hx4"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18116000 0x1000>; ++ vbus-gpio = <&gpio_cca 1 GPIO_ACTIVE_LOW>; ++ usbdev-gpio = <&gpio_cca 0 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@1802a000 { ++ compatible = "generic-ehci"; ++ reg = <0x1802a000 0x1000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@18042000 { ++ compatible = "brcm,usbd-xgs-hx4"; ++ reg = <0x18042000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18038000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18038000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x1803b000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@18032000 { ++ compatible = "brcm,iproc-ccb-mdio"; ++ reg = <0x18032000 0x1000>, ++ <0x1803fc3c 0x4>; ++ reg-names = "mdio-base", "iproc-mdio-enable"; ++ iproc-mdio-sel-bit = <4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ mdio_ext: mdio_ext@18032000 { ++ compatible = "brcm,iproc-ccb-mdio"; ++ reg = <0x18032000 0x1000>, ++ <0x1803fc3c 0x4>; ++ reg-names = "mdio-base", "iproc-mdio-enable"; ++ iproc-mdio-sel-bit = <4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "external"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18033000 { ++ compatible = "brcm,iproc-rng100"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18033000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@0x18039000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18039000 0x1000>, ++ iproc_reset_reg: <0x1803f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18020000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18020000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ /*arm,primecell-periphid = <0x00041330>;*/ ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@48000000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x48000000 0x40000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x08000000, ++ * cpu addr 0x08000000, size 0x0 0x08000000 ++ */ ++ ranges = <0x82000000 0 0x08000000 0x08000000 0 0x08000000>; ++ wa-list = "pcie_wrong_gen2"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ brcm,pcie-msi-inten; ++ }; ++ }; ++ ++ pcie1: pcie@18013000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18013000 0x1000>; ++ linux,pci-domain = <1>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x40000000, ++ * cpu addr 0x40000000, size 0x0 0x08000000 ++ */ ++ ranges = <0x82000000 0 0x40000000 0x40000000 0 0x08000000>; ++ wa-list = "pcie_wrong_gen2"; ++ status = "disabled"; ++ ++ msi-parent = <&msi1>; ++ msi1: msi@18013000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ brcm,pcie-msi-inten; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1803f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1803f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1803fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1803fc00 0x100>; ++ /* offset to 0x1803fc00, ctrl bit, mdio bit */ ++ amac-serdes-mdio-ctrl-sel = <0x3c>, <0x2>, <0x3>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-hurricane3.dtsi b/arch/arm/boot/dts/bcm-hurricane3.dtsi +--- a/arch/arm/boot/dts/bcm-hurricane3.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-hurricane3.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,416 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom HR3 iProc"; ++ compatible = "brcm,hurricane3"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ /*clocks = <&osc_50M>;*/ /* 50MHZ crystal/oscillator */ ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ /* 50MHZ crystal/oscillator clock source */ ++ /* ++ osc_50M: oscillator_50M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <50000000>; ++ }; ++ */ ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@1800fc00 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk"; ++ clocks = <&osc>; ++ reg = <0x1800fc00 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18020000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18021000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18021000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18042000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18042000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@1800a000 { ++ compatible = "brcm,iproc-gpio-ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x1800a000 0x50>; ++ ngpios = <12>; ++ pin-reg-bit-shift = <4>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy@1800fc40 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-gh"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18111000 0x1000>; ++ vbus-gpio = <&gpio_ccg 3 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@18048000 { ++ compatible = "generic-ehci"; ++ reg = <0x18048000 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@18048800 { ++ compatible = "generic-ohci"; ++ reg = <0x18048800 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ /* Over Current Protect Mode fix */ ++ iproc-ocpm-fix; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@1804c000 { ++ compatible = "brcm,usbd-xgs-iproc"; ++ reg = <0x1804c000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ sdio: sdio@18041000 { ++ compatible = "brcm,iproc-hr3-sdio"; ++ reg = <0x18041000 0x1000>, ++ <0x18116408 0x1000>; ++ reg-names = "sdio", "iproc-idm"; ++ interrupts = ; ++ bus-width = <8>; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18046000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18046000 0x600>, ++ <0x1811d408 0x10>, ++ <0x18046f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18047200 0x188>, ++ <0x18047000 0x124>, ++ <0x1811f408 0x004>, ++ <0x180473a0 0x01c>, ++ <0x1800e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18008000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18008000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_ext: mdio_ext { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <2>; ++ bus-type = "external"; ++ /* Currently clocks is not used by driver */ ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ pnor_flash: pnor_flash@18045000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "brcm,iproc-nor"; ++ reg = nor_regs: <0x18045000 0x1000>, ++ nor_mem: <0xE8000000 0x8000000>, ++ nor_strap: <0x18000a5c 0x4>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18032000 { ++ compatible = "brcm,iproc-rng200"; ++ reg = <0x18032000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18009000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18009000 0x1000>, ++ iproc_reset_reg: <0x1800f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18018000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18018000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ /*arm,primecell-periphid = <0x00041330>;*/ ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@03200000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x03200000 0x100000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x20000000, ++ * cpu addr 0x20000000, size 0x0 0x20000000 ++ */ ++ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; ++ wa-list = "pcie_rc", "pcie_perst"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1800f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0x1800f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0x1800fc00 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ reg = <0x18100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-katana2.dtsi b/arch/arm/boot/dts/bcm-katana2.dtsi +--- a/arch/arm/boot/dts/bcm-katana2.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-katana2.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,480 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom KT2 iProc"; ++ compatible = "brcm,katana2"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ enable-method = "brcm,bcm-nsp-smp"; ++ secondary-boot-reg = <0xffff042c>; ++ reg = <0x1>; ++ }; ++ }; ++ ++ mpcore { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: axi_clk_fixed_495M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <495000000>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18000300 { ++ compatible = "ns16550a"; ++ reg = <0x18000300 0x100>; ++ interrupts = ; ++ clock-frequency = <61875000>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18000400 { ++ compatible = "ns16550a"; ++ reg = <0x18000400 0x100>; ++ interrupts = ; ++ clock-frequency = <61875000>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@18037000 { ++ compatible = "ns16550a"; ++ reg = <0x18037000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_cca: gpio@18000060 { ++ compatible = "brcm,iproc-gpio-cca"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x18000060 0x50>, ++ intr: <0x18000000 0x50>; ++ ngpios = <8>; ++ pin-reg-bit-shift = <0>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18022000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18022000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@18023000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18023000 0x1000>, ++ <0x18111000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18026000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18026000 0x600>, ++ <0x1811b408 0x10>, ++ <0x18026f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ }; ++ ++ qspi: spi@18027000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18027200 0x188>, ++ <0x18027000 0x124>, ++ <0x1811c408 0x004>, ++ <0x180273a0 0x01c>, ++ <0x1803e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = ++ "spi_lr_fullness_reached", ++ "spi_lr_session_aborted", ++ "spi_lr_impatient", ++ "spi_lr_session_done", ++ "spi_lr_overread", ++ "mspi_done", ++ "mspi_halted"; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy0 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-kt2"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18116000 0x1000>; ++ vbus-gpio = <&gpio_cca 1 GPIO_ACTIVE_LOW>; ++ usbdev-gpio = <&gpio_cca 0 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@1802a000 { ++ compatible = "generic-ehci"; ++ reg = <0x1802a000 0x1000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@18042000 { ++ compatible = "brcm,usbd-xgs-hx4"; ++ reg = <0x18042000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@0x18038000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18038000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x1803b000 0x100>; ++ interrupts = ; ++ #bus-id = <1>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@18032000 { ++ compatible = "brcm,iproc-ccb-mdio"; ++ reg = <0x18032000 0x1000>, ++ <0x1803fc24 0x4>; ++ reg-names = "mdio-base", "iproc-mdio-enable"; ++ iproc-mdio-sel-bit = <3>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ mdio_ext: mdio_ext@18032000 { ++ compatible = "brcm,iproc-ccb-mdio"; ++ reg = <0x18032000 0x1000>, ++ <0x1803fc24 0x4>; ++ reg-names = "mdio-base", "iproc-mdio-enable"; ++ iproc-mdio-sel-bit = <3>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "external"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18033000 { ++ compatible = "brcm,iproc-rng100"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18033000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18039000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18039000 0x1000>, ++ iproc_reset_reg: <0x1803f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18020000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18020000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ /*arm,primecell-periphid = <0x00041330>;*/ ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@48000000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x48000000 0x40000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x08000000, ++ * cpu addr 0x08000000, size 0x0 0x08000000 ++ */ ++ ranges = <0x82000000 0 0x08000000 0x08000000 0 0x08000000>; ++ wa-list = "pcie_wrong_gen2"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ brcm,pcie-msi-inten; ++ }; ++ }; ++ ++ pcie1: pcie@18013000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18013000 0x1000>; ++ linux,pci-domain = <1>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x40000000, ++ * cpu addr 0x40000000, size 0x0 0x08000000 ++ */ ++ ranges = <0x82000000 0 0x40000000 0x40000000 0 0x08000000>; ++ wa-list = "pcie_wrong_gen2"; ++ status = "disabled"; ++ ++ msi-parent = <&msi1>; ++ msi1: msi@18013000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ brcm,pcie-msi-inten; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1803f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1803f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1803fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1803fc00 0x100>; ++ /* offset to 0x1803fc00, ctrl bit, mdio bit */ ++ amac-serdes-mdio-ctrl-sel = <0x24>, <0x1>, <0x2>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-saber2.dtsi b/arch/arm/boot/dts/bcm-saber2.dtsi +--- a/arch/arm/boot/dts/bcm-saber2.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-saber2.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,396 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++/ { ++ model = "Broadcom SB2 iProc"; ++ compatible = "brcm,saber2"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator_25M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ osc_1: oscillator_50M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <50000000>; ++ }; ++ ++ periph_clk: periph_clk@19000000 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@1800fc50 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk", "axi-clk-sb2"; ++ clocks = <&osc_1>; ++ reg = <0x1800fc50 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18020000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18021000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18021000 0x1000>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18047200 0x188>, ++ <0x18047000 0x124>, ++ <0xf8106408 0x004>, ++ <0x180473a0 0x01c>, ++ <0x1800e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18042000 { ++ compatible = "brcm,xgs-iproc-amac"; ++ reg = <0x18042000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy0 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-sb2"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18111000 0x1000>; ++ vbus-gpio = <&gpio_ccg 1 GPIO_ACTIVE_LOW>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@18048000 { ++ compatible = "generic-ehci"; ++ reg = <0x18048000 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@18048800 { ++ compatible = "generic-ohci"; ++ reg = <0x18048800 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@1804c000 { ++ compatible = "brcm,usbd-xgs-iproc"; ++ reg = usb2d: <0x1804c000 0x2000>, ++ idm_usb: <0x18111000 0x1000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@1800a000 { ++ compatible = "brcm,iproc-gpio-ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x1800a000 0x50>; ++ ngpios = <16>; ++ pin-reg-bit-shift = <0>; ++ pin-base = <0>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18046000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x18046000 0x600>, ++ <0xf8105408 0x10>, ++ <0x18046f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18008000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18008000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>, ++ <0x1800fc40 0x4>; ++ reg-names = "mdio-base", "ipoc-mdio-enable"; ++ iproc-mdio-sel-bit = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ mdio_ext: mdio_ext@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>, ++ <0x1800fc40 0x4>; ++ reg-names = "mdio-base", "iproc-mdio-enable"; ++ iproc-mdio-sel-bit = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "external"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18032000 { ++ compatible = "brcm,iproc-rng200"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x18032000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18009000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18009000 0x1000>, ++ iproc_reset_reg: <0x1800f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18018000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18018000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@03200000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x03200000 0x100000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x20000000, ++ * cpu addr 0x20000000, size 0x0 0x20000000 ++ */ ++ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; ++ wa-list = "pcie_rc"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1800f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0x1800f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0x1800fc00 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ reg = idm0: <0x18100000 0x100000>, ++ idm1: <0xf8100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-wolfhound2.dtsi b/arch/arm/boot/dts/bcm-wolfhound2.dtsi +--- a/arch/arm/boot/dts/bcm-wolfhound2.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm-wolfhound2.dtsi 2018-05-10 11:31:28.309398252 +0800 +@@ -0,0 +1,385 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include "skeleton.dtsi" ++ ++ ++/ { ++ model = "Broadcom HR3 iProc"; ++ compatible = "brcm,hurricane3"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x0>; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19000000 0x00023000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ a9pll: arm_clk@00000 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-armpll"; ++ clocks = <&osc>; ++ reg = <0x0 0x1000>; ++ }; ++ ++ gic: interrupt-controller@21000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x21000 0x1000>, <0x20100 0x100>; ++ }; ++ ++ twd-timer@20600 { ++ compatible = "arm,cortex-a9-twd-timer"; ++ reg = <0x20600 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ timer@20200 { ++ compatible = "arm,cortex-a9-global-timer"; ++ reg = <0x20200 0x100>; ++ interrupts = ; ++ clocks = <&periph_clk>; ++ }; ++ ++ L2: l2-cache { ++ compatible = "arm,pl310-cache"; ++ reg = <0x22000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ arm,filter-ranges = <0x60000000 0x80000000>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc: oscillator { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ }; ++ ++ periph_clk: periph_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&a9pll>; ++ clock-div = <2>; ++ clock-mult = <1>; ++ }; ++ ++ iproc_axi_clk: iproc_axi_clk@1800fc00 { ++ #clock-cells = <0>; ++ compatible = "brcm,xgs-iproc-axi-clk"; ++ clocks = <&osc>; ++ reg = <0x1800fc00 0x1c>; ++ }; ++ ++ iproc_apb_clk: iproc_apb_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&iproc_axi_clk>; ++ clock-div = <4>; ++ clock-mult = <1>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@18020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18020000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@18021000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x18021000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_apb_clk>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@18042000 { ++ compatible = "brcm,xgs-wh2-amac"; ++ reg = <0x18042000 0x1000>, ++ <0x18110000 0x1000>; ++ reg-names = "amac_base", "idm_base"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@1800a000 { ++ compatible = "brcm,iproc-gpio-ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x1800a000 0x50>; ++ ngpios = <12>; ++ pin-reg-bit-shift = <4>; ++ pin-base = <4>; ++ gpio-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbphy0: usbphy@1800fc40 { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy-gh"; ++ reg = idm_usb2h: <0x18115000 0x1000>, ++ idm_usb2d: <0x18111000 0x1000>; ++ vbus-gpio = <&gpio_ccg 3 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@18048000 { ++ compatible = "generic-ehci"; ++ reg = <0x18048000 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@18048800 { ++ compatible = "generic-ohci"; ++ reg = <0x18048800 0x800>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ /* Over Current Protect Mode fix */ ++ iproc-ocpm-fix; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@1804c000 { ++ compatible = "brcm,usbd-xgs-iproc"; ++ reg = <0x1804c000 0x2000>; ++ interrupts = ; ++ usb-phy = <&usbphy0>; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x18047200 0x188>, ++ <0x18047000 0x124>, ++ <0x1811f408 0x004>, ++ <0x180473a0 0x01c>, ++ <0x1800e000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ num-cs = <2>; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@18008000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x18008000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_int0: mdio_int0@03210000 { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd cmic_common mdio */ ++ mdio_int1: mdio_int1@03210000 { ++ compatible = "brcm,iproc-cmicd-mdio"; ++ reg = <0x03210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <1>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ /* CCG mdio */ ++ mdio_int2: mdio_int2@18002000 { ++ compatible = "brcm,iproc-ccg-mdio"; ++ reg = <0x18002000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-type = "internal"; ++ clocks = <&iproc_apb_clk>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@18032000 { ++ compatible = "brcm,iproc-rng200"; ++ reg = <0x18032000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@18009000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x18009000 0x1000>, ++ iproc_reset_reg: <0x1800f014 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@18018000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = pl330_base: <0x18018000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ /*arm,primecell-periphid = <0x00041330>;*/ ++ clocks = <&iproc_apb_clk>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ /* cmicd */ ++ iproc_cmicd: iproc_cmicd@03200000 { ++ compatible = "brcm,iproc-cmicd"; ++ reg = <0x03200000 0x100000>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ }; ++ ++ pcie0: pcie@18012000 { ++ compatible = "brcm,iproc-pcie"; ++ reg = <0x18012000 0x1000>; ++ linux,pci-domain = <0>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ ++ /* ++ * non-prefetchable mem space, pcie addr 0x0 0x20000000, ++ * cpu addr 0x20000000, size 0x0 0x20000000 ++ */ ++ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; ++ wa-list = "pcie_rc", "pcie_perst"; ++ status = "disabled"; ++ ++ msi-parent = <&msi0>; ++ msi0: msi@18012000 { ++ compatible = "brcm,iproc-msi"; ++ msi-controller; ++ interrupt-parent = <&gic>; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@1800f000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0x1800f000 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0x1800fc00 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@18100000 { ++ compatible = "brcm,iproc-idm"; ++ reg = <0x18100000 0x100000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++}; +Binary files a/arch/arm/boot/dts/bcm95341x.dtb and b/arch/arm/boot/dts/bcm95341x.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm95341x.dts b/arch/arm/boot/dts/bcm95341x.dts +--- a/arch/arm/boot/dts/bcm95341x.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm95341x.dts 2018-05-10 11:31:28.313398255 +0800 +@@ -0,0 +1,220 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-greyhound.dtsi" ++ ++/ { ++ model = "Broadcom GH SVK (BCM95341x)"; ++ compatible = "brcm,bcm95341x", "brcm,greyhound"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "gmii"; /* "gmii-id", "gmii-rxid" */ ++}; ++ ++&usbphy0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x30000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&pnor_flash { ++ status = "okay"; ++ ++ partition@0 { ++ label = "pboot"; ++ reg = <0x0 0xc0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "penv"; ++ reg = <0xc0000 0x40000>; ++ }; ++ partition@2 { ++ label = "psystem"; ++ reg = <0x100000 0xf00000>; ++ }; ++ partition@3 { ++ label = "prootfs"; ++ reg = <0x1000000 0x1000000>; ++ }; ++ partition@4 { ++ label = "pcustfs"; ++ reg = <0x2000000 0x2000000>; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <24>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; +Binary files a/arch/arm/boot/dts/bcm953444.dtb and b/arch/arm/boot/dts/bcm953444.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm953444.dts b/arch/arm/boot/dts/bcm953444.dts +--- a/arch/arm/boot/dts/bcm953444.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm953444.dts 2018-05-10 11:31:28.313398255 +0800 +@@ -0,0 +1,135 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-hurricane3.dtsi" ++ ++/ { ++ model = "Broadcom HR3 SVK (BCM953444K)"; ++ compatible = "brcm,bcm953444k", "brcm,hurricane3"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "gmii"; /* "gmii-id", "gmii-rxid" */ ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++}; ++ ++&mdio_ext { ++ #bus-id = <1>; ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <24>; ++ }; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; ++ +Binary files a/arch/arm/boot/dts/bcm953547.dtb and b/arch/arm/boot/dts/bcm953547.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm953547.dts b/arch/arm/boot/dts/bcm953547.dts +--- a/arch/arm/boot/dts/bcm953547.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm953547.dts 2018-05-10 11:31:28.313398255 +0800 +@@ -0,0 +1,167 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-wolfhound2.dtsi" ++ ++/ { ++ model = "Broadcom WH2 SVK (BCM953547K)"; ++ compatible = "brcm,bcm953547k", "brcm,wolfhound2"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "gmii"; /* "gmii-id", "gmii-rxid" */ ++ serdes-phy-handle = <&amac_serdes0>; ++}; ++ ++&usbphy0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&mdio_int0 { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <24>; ++ }; ++}; ++ ++&mdio_int1 { ++ status = "okay"; ++ amac_serdes0: amac_serdes@0 { ++ reg = <20>; ++ lane-num = <3>; ++ }; ++}; ++ ++&mdio_int2 { ++ status = "okay"; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; ++ +Binary files a/arch/arm/boot/dts/bcm956160.dtb and b/arch/arm/boot/dts/bcm956160.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956160.dts b/arch/arm/boot/dts/bcm956160.dts +--- a/arch/arm/boot/dts/bcm956160.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm956160.dts 2018-05-10 11:31:28.313398255 +0800 +@@ -0,0 +1,225 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-hurricane3.dtsi" ++ ++/ { ++ model = "Broadcom HR3 SVK (BCM956160K)"; ++ compatible = "brcm,bcm956160k", "brcm,hurricane3"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "gmii"; /* "gmii-id", "gmii-rxid" */ ++}; ++ ++&usbphy0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x30000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&pnor_flash { ++ status = "okay"; ++ ++ partition@0 { ++ label = "pboot"; ++ reg = <0x0 0xc0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "penv"; ++ reg = <0xc0000 0x40000>; ++ }; ++ partition@2 { ++ label = "psystem"; ++ reg = <0x100000 0xf00000>; ++ }; ++ partition@3 { ++ label = "prootfs"; ++ reg = <0x1000000 0x1000000>; ++ }; ++ partition@4 { ++ label = "pcustfs"; ++ reg = <0x2000000 0x2000000>; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <24>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; ++ +Binary files a/arch/arm/boot/dts/bcm956170.dtb and b/arch/arm/boot/dts/bcm956170.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956170.dts b/arch/arm/boot/dts/bcm956170.dts +--- a/arch/arm/boot/dts/bcm956170.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm956170.dts 2018-05-10 17:50:42.895946853 +0800 +@@ -0,0 +1,248 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-greyhound2.dtsi" ++ ++/ { ++ model = "Broadcom GH2 SVK (BCM956170)"; ++ compatible = "brcm,bcm956170", "brcm,greyhound2"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "sgmii"; ++ serdes-handle = <&amac_serdes0>; ++}; ++ ++&gmac1 { ++ status = "okay"; ++ phy-handle = <&amac_phy1>; ++ phy-mode = "sgmii"; ++ serdes-handle = <&amac_serdes1>; ++}; ++ ++&usbphy0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x30000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&pnor_flash { ++ status = "okay"; ++ ++ partition@0 { ++ label = "pboot"; ++ reg = <0x0 0xc0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "penv"; ++ reg = <0xc0000 0x40000>; ++ }; ++ partition@2 { ++ label = "psystem"; ++ reg = <0x100000 0xf00000>; ++ }; ++ partition@3 { ++ label = "prootfs"; ++ reg = <0x1000000 0x1000000>; ++ }; ++ partition@4 { ++ label = "pcustfs"; ++ reg = <0x2000000 0x2000000>; ++ }; ++}; ++ ++&ccg_mdio_int { ++ status = "okay"; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ amac_serdes0: amac_serdes@0 { ++ reg = <25>; ++ lane-num = <0>; ++ }; ++ amac_serdes1: amac_serdes@1 { ++ reg = <26>; ++ lane-num = <1>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <16>; ++ }; ++ amac_phy1: amac_phy@1 { ++ reg = <17>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&crypto { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; +Binary files a/arch/arm/boot/dts/bcm956260.dtb and b/arch/arm/boot/dts/bcm956260.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956260.dts b/arch/arm/boot/dts/bcm956260.dts +--- a/arch/arm/boot/dts/bcm956260.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm956260.dts 2018-05-10 11:31:28.317398259 +0800 +@@ -0,0 +1,203 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-saber2.dtsi" ++ ++/ { ++ model = "Broadcom SB2 SVK (BCM956260K)"; ++ compatible = "brcm,bcm956260k", "brcm,saber2"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "sgmii"; ++ serdes-handle = <&amac_serdes0>; ++}; ++ ++&usbphy0 { ++ status = "okay"; ++ mdio-phy-handle = <&usb_phy>; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c64"; ++ reg = <0x50>; ++ pagesize = <32>; ++ }; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x70000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x01000000>; ++ }; ++ }; ++}; ++ ++ ++&mdio_int { ++ status = "okay"; ++ amac_serdes0: amac_serdes@0 { ++ reg = <1>; ++ }; ++ pcie_phy0: pcie_phy@0 { ++ reg = <2>; ++ }; ++ usb_phy: usb_phy@0 { ++ reg = <3>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <1>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; +Binary files a/arch/arm/boot/dts/bcm956340.dtb and b/arch/arm/boot/dts/bcm956340.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956340.dts b/arch/arm/boot/dts/bcm956340.dts +--- a/arch/arm/boot/dts/bcm956340.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm956340.dts 2018-05-10 11:31:28.317398259 +0800 +@@ -0,0 +1,230 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-helix4.dtsi" ++ ++/ { ++ model = "Broadcom HX4 SVK (BCM956340K)"; ++ compatible = "brcm,bcm956340k", "brcm,helix4"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ sdk-serdes-lane2 = &amac_serdes2; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */ ++ serdes-handle = <&amac_serdes0>; ++}; ++ ++&gmac1 { ++ status = "okay"; ++ phy-handle = <&amac_phy1>; ++ phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */ ++ serdes-handle = <&amac_serdes1>; ++}; ++ ++&usbphy0 { ++ status = "okay"; ++ mdio-phy-handle = <&usb_phy>; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_cca { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&pcie1 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy1>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x70000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x01000000>; ++ }; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ /* 3 AMAC serdes, amac_serdes2 is for switch front port */ ++ amac_serdes0: amac_serdes@0 { ++ reg = <1>; ++ }; ++ amac_serdes1: amac_serdes@1 { ++ reg = <2>; ++ }; ++ amac_serdes2: amac_serdes@2 { ++ reg = <3>; ++ }; ++ usb_phy: usb_phy@0 { ++ reg = <6>; ++ }; ++ pcie_phy0: pcie_phy@0 { ++ reg = <7>; ++ }; ++ pcie_phy1: pcie_phy@1 { ++ reg = <8>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <1>; ++ }; ++ amac_phy1: amac_phy@1 { ++ reg = <2>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; ++ +Binary files a/arch/arm/boot/dts/bcm956450.dtb and b/arch/arm/boot/dts/bcm956450.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956450.dts b/arch/arm/boot/dts/bcm956450.dts +--- a/arch/arm/boot/dts/bcm956450.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/bcm956450.dts 2018-05-10 11:31:28.317398259 +0800 +@@ -0,0 +1,229 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-katana2.dtsi" ++ ++/ { ++ model = "Broadcom KT2 SVK (BCM956450K)"; ++ compatible = "brcm,bcm956450k", "brcm,katana2"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ sdk-serdes-lane2 = &amac_serdes2; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&amac_phy0>; ++ phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */ ++ serdes-handle = <&amac_serdes0>; ++}; ++ ++&gmac1 { ++ status = "okay"; ++ phy-handle = <&amac_phy1>; ++ phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */ ++ serdes-handle = <&amac_serdes1>; ++}; ++ ++&usbphy0 { ++ status = "okay"; ++ mdio-phy-handle = <&usb_phy>; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++ ++&gpio_cca { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy0>; ++}; ++ ++&pcie1 { ++ status = "okay"; ++ mdio-phy-handle = <&pcie_phy1>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c01"; ++ reg = <0x50>; ++ pagesize = <8>; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ /*nand-bus-width = <8>;*/ ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x0 0x200000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x200000 0x400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x600000 0xa00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x1000000 0xf000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x70000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ /*read-only;*/ ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x01000000>; ++ }; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ /* 3 AMAC serdes, amac_serdes2 is for switch front port */ ++ amac_serdes0: amac_serdes@0 { ++ reg = <1>; ++ }; ++ amac_serdes1: amac_serdes@1 { ++ reg = <2>; ++ }; ++ amac_serdes2: amac_serdes@2 { ++ reg = <3>; ++ }; ++ usb_phy: usb_phy@0 { ++ reg = <6>; ++ }; ++ pcie_phy0: pcie_phy@0 { ++ reg = <7>; ++ }; ++ pcie_phy1: pcie_phy@1 { ++ reg = <8>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ amac_phy0: amac_phy@0 { ++ reg = <1>; ++ }; ++ amac_phy1: amac_phy@1 { ++ reg = <2>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&iproc_cmicd { ++ status = "okay"; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/greyhound.its b/arch/arm/boot/dts/greyhound.its +--- a/arch/arm/boot/dts/greyhound.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/greyhound.its 2018-05-10 11:31:28.333398276 +0800 +@@ -0,0 +1,62 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm95341x.dtb"; ++ data = /incbin/("./bcm95341x.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++/* ++ fdt@2 { ++ description = "Flattened Device Tree blob - bcm95606x.dtb"; ++ data = /incbin/("./bcm95606x.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "md5"; ++ }; ++ }; ++*/ ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++/* ++ conf@2 { ++ description = "Boot Linux kernel with FDT blob"; ++ kernel = "kernel@1"; ++ fdt = "fdt@2"; ++ }; ++*/ ++ }; ++}; ++ +\ No newline at end of file +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/greyhound2.its b/arch/arm/boot/dts/greyhound2.its +--- a/arch/arm/boot/dts/greyhound2.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/greyhound2.its 2018-05-10 11:31:28.333398276 +0800 +@@ -0,0 +1,62 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm956170.dtb"; ++ data = /incbin/("./bcm956170.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ /*fdt@2 { ++ description = "Flattened Device Tree blob - bcm95357x.dtb"; ++ data = /incbin/("./bcm95357x.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ };*/ ++ ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++/* ++ conf@2 { ++ description = "Boot Linux kernel with FDT blob"; ++ kernel = "kernel@1"; ++ fdt = "fdt@2"; ++ }; ++*/ ++ }; ++}; ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/helix4.its b/arch/arm/boot/dts/helix4.its +--- a/arch/arm/boot/dts/helix4.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/helix4.its 2018-05-10 11:31:28.333398276 +0800 +@@ -0,0 +1,42 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm956340.dtb"; ++ data = /incbin/("./bcm956340.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/hurricane3.its b/arch/arm/boot/dts/hurricane3.its +--- a/arch/arm/boot/dts/hurricane3.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/hurricane3.its 2018-05-10 11:31:28.333398276 +0800 +@@ -0,0 +1,59 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm956160.dtb"; ++ data = /incbin/("./bcm956160.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@2 { ++ description = "Flattened Device Tree blob - bcm953444.dtb"; ++ data = /incbin/("./bcm953444.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob 1"; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++ ++ conf@2 { ++ description = "Boot Linux kernel with FDT blob 2"; ++ kernel = "kernel@1"; ++ fdt = "fdt@2"; ++ }; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/katana2.its b/arch/arm/boot/dts/katana2.its +--- a/arch/arm/boot/dts/katana2.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/katana2.its 2018-05-10 11:31:28.361398305 +0800 +@@ -0,0 +1,43 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm956450.dtb"; ++ data = /incbin/("./bcm956450.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++ }; ++}; ++ +\ No newline at end of file +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/saber2.its b/arch/arm/boot/dts/saber2.its +--- a/arch/arm/boot/dts/saber2.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/saber2.its 2018-05-10 11:31:28.397398343 +0800 +@@ -0,0 +1,42 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm956260.dtb"; ++ data = /incbin/("./bcm956260.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/wolfhound2.its b/arch/arm/boot/dts/wolfhound2.its +--- a/arch/arm/boot/dts/wolfhound2.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/wolfhound2.its 2018-05-10 11:31:28.421398368 +0800 +@@ -0,0 +1,60 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel@1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt@1 { ++ description = "Flattened Device Tree blob - bcm953547.dtb"; ++ data = /incbin/("./bcm953547.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ /* fdt@2 { ++ description = "Flattened Device Tree blob - bcm953444.dtb"; ++ data = /incbin/("./bcm953444.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; */ ++ }; ++ ++ configurations { ++ default = "conf@1"; ++ conf@1 { ++ description = "Boot Linux kernel with FDT blob 1"; ++ kernel = "kernel@1"; ++ fdt = "fdt@1"; ++ }; ++ ++ /* conf@2 { ++ description = "Boot Linux kernel with FDT blob 2"; ++ kernel = "kernel@1"; ++ fdt = "fdt@2"; ++ }; */ ++ }; ++}; ++ +\ No newline at end of file +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/xgs-iproc-arm32.its b/arch/arm/boot/dts/xgs-iproc-arm32.its +--- a/arch/arm/boot/dts/xgs-iproc-arm32.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/boot/dts/xgs-iproc-arm32.its 2018-05-10 11:31:28.421398368 +0800 +@@ -0,0 +1,163 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel_iproc { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../zImage"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_hx4 { ++ description = "Helix4 Device Tree blob - bcm956340.dtb"; ++ data = /incbin/("./bcm956340.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_kt2 { ++ description = "Katana2 Device Tree blob - bcm956450.dtb"; ++ data = /incbin/("./bcm956450.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_sb2 { ++ description = "Saber2 Device Tree blob - bcm956260.dtb"; ++ data = /incbin/("./bcm956260.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_gh { ++ description = "Greyhound Device Tree blob - bcm95341x.dtb"; ++ data = /incbin/("./bcm95341x.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_hr3 { ++ description = "Hurricane3 Device Tree blob - bcm956160.dtb"; ++ data = /incbin/("./bcm956160.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_hr3_lite { ++ description = "Hurricane3 Lite Device Tree blob - bcm953444.dtb"; ++ data = /incbin/("./bcm953444.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_gh2 { ++ description = "Greyhound2 Device Tree blob - bcm956170.dtb"; ++ data = /incbin/("./bcm956170.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_wh2 { ++ description = "Wolfhound2 Device Tree blob - bcm953547.dtb"; ++ data = /incbin/("./bcm953547.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "hx4"; ++ /* use "bootm 0x64000000#katana2" for booting Katana2 */ ++ hx4 { ++ description = "Boot Linux kernel with Helix4 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_hx4"; ++ }; ++ ++ kt2 { ++ description = "Boot Linux kernel with Katana2 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_kt2"; ++ }; ++ ++ sb2 { ++ description = "Boot Linux kernel with Saber2 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_sb2"; ++ }; ++ ++ gh { ++ description = "Boot Linux kernel with Greyhound FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_gh"; ++ }; ++ ++ hr3 { ++ description = "Boot Linux kernel with Hurricane3 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_hr3"; ++ }; ++ ++ hr3_lite { ++ description = "Boot Linux kernel with Hurricane3 Lite FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_hr3_lite"; ++ }; ++ ++ gh2 { ++ description = "Boot Linux kernel with Greyhound2 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_gh2"; ++ }; ++ ++ wh2 { ++ description = "Boot Linux kernel with Wolfhound2 FDT blob "; ++ kernel = "kernel_iproc"; ++ fdt = "fdt_wh2"; ++ }; ++ ++ }; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/configs/iproc_arm32_be_defconfig b/arch/arm/configs/iproc_arm32_be_defconfig +--- a/arch/arm/configs/iproc_arm32_be_defconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/configs/iproc_arm32_be_defconfig 2018-05-10 11:31:28.429398377 +0800 +@@ -0,0 +1,210 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_USELIB=y ++CONFIG_IRQ_DOMAIN_DEBUG=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_SHMEM is not set ++CONFIG_EMBEDDED=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_ARCH_XGS_IPROC=y ++CONFIG_CPU_BIG_ENDIAN=y ++# CONFIG_ARM_ERRATA_643719 is not set ++CONFIG_PCI=y ++CONFIG_PCI_MSI=y ++CONFIG_PCIE_XGS_IPROC=y ++CONFIG_PCIE_IPROC_MSI=y ++CONFIG_SMP=y ++CONFIG_PREEMPT=y ++CONFIG_ARM_MODULE_PLTS=y ++CONFIG_CMA=y ++CONFIG_CMA_DEBUG=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=1 mem=240M" ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET6_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET6_XFRM_MODE_BEET is not set ++CONFIG_IPV6_TUNNEL=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=y ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_TARGET_CT=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_RPFILTER=y ++CONFIG_IP6_NF_MATCH_RT=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_MTD=y ++CONFIG_MTD_TESTS=m ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_LE_BYTE_SWAP=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_NOR_XGS_IPROC=y ++CONFIG_MTD_M25P80=y ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_BRCMNAND=y ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_MTD_UBI=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++CONFIG_CHR_DEV_SG=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=y ++CONFIG_TIGON3=y ++CONFIG_MDIO_XGS_IPROC=y ++CONFIG_BROADCOM_PHY=y ++CONFIG_XGS_IPROC_SERDES=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_XGS_IPROC_RNG=y ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_SPI=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_WATCHDOG=y ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_XGS_IPROC=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_XGS_IPROC=y ++CONFIG_USB_STORAGE=y ++CONFIG_USBPHY_XGS_IPROC=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_XGS_IPROC_UDC=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SDHCI_XGS_IPROC=y ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++CONFIG_PL330_DMA=y ++CONFIG_GENERIC_PHY=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++# CONFIG_DNOTIFY is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=y ++CONFIG_JFFS2_FS=y ++CONFIG_UBIFS_FS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFSD=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_DEBUG_INFO=y ++CONFIG_DEBUG_FS=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_FTRACE is not set ++CONFIG_DEBUG_USER=y ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=m ++CONFIG_XZ_DEC=y +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/configs/iproc_arm32_defconfig b/arch/arm/configs/iproc_arm32_defconfig +--- a/arch/arm/configs/iproc_arm32_defconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/configs/iproc_arm32_defconfig 2018-05-10 11:31:28.429398377 +0800 +@@ -0,0 +1,207 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_USELIB=y ++CONFIG_IRQ_DOMAIN_DEBUG=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_SHMEM is not set ++CONFIG_EMBEDDED=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_ARCH_XGS_IPROC=y ++# CONFIG_ARM_ERRATA_643719 is not set ++CONFIG_PCI=y ++CONFIG_PCI_MSI=y ++CONFIG_PCIE_XGS_IPROC=y ++CONFIG_PCIE_IPROC_MSI=y ++CONFIG_SMP=y ++CONFIG_PREEMPT=y ++CONFIG_ARM_MODULE_PLTS=y ++CONFIG_CMA=y ++CONFIG_CMA_DEBUG=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=1 mem=240M" ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET6_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET6_XFRM_MODE_BEET is not set ++CONFIG_IPV6_TUNNEL=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=y ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_TARGET_CT=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_RPFILTER=y ++CONFIG_IP6_NF_MATCH_RT=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_MTD=y ++CONFIG_MTD_TESTS=m ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_NOR_XGS_IPROC=y ++CONFIG_MTD_M25P80=y ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_BRCMNAND=y ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_MTD_UBI=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++CONFIG_CHR_DEV_SG=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=y ++CONFIG_TIGON3=y ++CONFIG_MDIO_XGS_IPROC=y ++CONFIG_BROADCOM_PHY=y ++CONFIG_XGS_IPROC_SERDES=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_XGS_IPROC_RNG=y ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_SPI=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_WATCHDOG=y ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_XGS_IPROC=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_XGS_IPROC=y ++CONFIG_USB_STORAGE=y ++CONFIG_USBPHY_XGS_IPROC=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_XGS_IPROC_UDC=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SDHCI_XGS_IPROC=y ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++CONFIG_PL330_DMA=y ++CONFIG_GENERIC_PHY=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++# CONFIG_DNOTIFY is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=y ++CONFIG_JFFS2_FS=y ++CONFIG_UBIFS_FS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFSD=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_DEBUG_INFO=y ++CONFIG_DEBUG_FS=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_FTRACE is not set ++CONFIG_DEBUG_USER=y ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=m ++CONFIG_XZ_DEC=y +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig +--- a/arch/arm/mach-iproc/Kconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/Kconfig 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,77 @@ ++menuconfig ARCH_XGS_IPROC ++ bool "Broadcom XGS iProc Support" if ARCH_MULTI_V7 ++ select HAVE_ARM_TWD if SMP ++ select HAVE_ARM_SCU if SMP ++ select ARM_GLOBAL_TIMER ++ select ARM_GIC ++ select ARCH_REQUIRE_GPIOLIB ++ select CACHE_L2X0 ++ select ARM_AMBA ++ select ARCH_SUPPORTS_BIG_ENDIAN ++ select CPU_ENDIAN_BE8 if CPU_BIG_ENDIAN ++ select ARM_ERRATA_754322 ++ select ARM_ERRATA_764369 if SMP ++ select ARM_ERRATA_775420 ++ help ++ This enables support for Broadcom XGS iProc based SoC chips ++ ++if ARCH_XGS_IPROC ++ ++comment "XGS iProc SoC based Machine types" ++ ++choice ++ prompt "XGS iProc SoC based Machine types" ++ default XGS_IPROC_ARM32_PLATFORM ++ ++config XGS_IPROC_ARM32_PLATFORM ++ bool "Support all XGS iProc ARM32 platforms" ++ help ++ Support for all XGS iProc ARM32 platforms. ++ ++config MACH_HX4 ++ bool "Support Broadcom Helix4 bring-up board" ++ help ++ Support for the Broadcom Helix4 bring-up board. ++ ++config MACH_HR2 ++ bool "Support Broadcom Hurricane2 bring-up board" ++ help ++ Support for the Broadcom Hurricane2 bring-up board. ++ ++config MACH_KT2 ++ bool "Support Broadcom Katana2 bring-up board" ++ help ++ Support for the Broadcom Katana2 bring-up board. ++ ++config MACH_GH ++ bool "Support Broadcom Greyhound bring-up board" ++ help ++ Support for the Broadcom Greyhound bring-up board. ++ ++config MACH_SB2 ++ bool "Support Broadcom Saber2 bring-up board" ++ help ++ Support for the Broadcom Saber2 bring-up board. ++ ++config MACH_HR3 ++ bool "Support Broadcom Hurricane3 bring-up board" ++ help ++ Support for the Broadcom Hurricane3 bring-up board. ++ ++config MACH_GH2 ++ bool "Support Broadcom Greyhound2 bring-up board" ++ help ++ Support for the Broadcom Greyhound2 bring-up board. ++ ++config MACH_WH2 ++ bool "Support Broadcom wolfhound2 bring-up board" ++ help ++ Support for the Broadcom Wolfhound2 bring-up board. ++endchoice ++ ++config MACH_IPROC_EMULATION ++ bool "Support iProc emulation" ++ help ++ Support for the iProc emulation. ++ ++endif +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/Makefile b/arch/arm/mach-iproc/Makefile +--- a/arch/arm/mach-iproc/Makefile 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/Makefile 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,3 @@ ++obj-y := board_bu.o ++obj-y += shm.o ++obj-$(CONFIG_SMP) += platsmp.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c +--- a/arch/arm/mach-iproc/board_bu.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/board_bu.c 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++#define DMU_CRU_RESET_BASE 0x200 ++ ++enum xgs_iproc_dev_id { ++ XGS_IPROC_HX4=0, ++ XGS_IPROC_KT2, ++ XGS_IPROC_HR2, ++ XGS_IPROC_GH, ++ XGS_IPROC_SB2, ++ XGS_IPROC_HR3, ++ XGS_IPROC_GH2, ++ XGS_IPROC_WH2, ++ XGS_IPROC_GENERIC, ++}; ++ ++const char *const xgs_iproc_dt_compat[] = { ++ "brcm,helix4", ++ "brcm,katana2", ++ "brcm,hurricane2", ++ "brcm,greyhound", ++ "brcm,saber2", ++ "brcm,hurricane3", ++ "brcm,greyhound2", ++ "brcm,wolfhound2", ++ "brcm,xgs-iproc", ++ NULL, ++}; ++ ++void __init xgs_iproc_init_early(void) ++{ ++ /* ++ * SDK allocates coherent buffers from atomic context. ++ * Increase size of atomic coherent pool to make sure such ++ * allocations won't fail. ++ */ ++ /* can be overrided by "coherent_pool" in kernel boot argument */ ++ if (IS_ENABLED(CONFIG_DMA_CMA)) ++ init_dma_coherent_pool_size(SZ_1M * 16); ++} ++ ++static void __init xgs_iproc_init(void) ++{ ++ int ret; ++ ++ ret = xgs_iproc_misc_setup(); ++ if (ret < 0) ++ return; ++ ++ /* Init idm and setup idm timeout handler for debug purpose */ ++ /* xgs_iproc_idm_init should be init before reset dmac */ ++ ret = xgs_iproc_idm_init(); ++ if (ret < 0) ++ return; ++ ++ xgs_iproc_idm_dmac_reset(); ++ ++ /* Populate platform devices */ ++ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++} ++ ++ ++static void xgs_iproc_restart(enum reboot_mode mode, const char *cmd) ++{ ++ void * __iomem reg_addr; ++ u32 reg; ++ ++ /* CRU_RESET register */ ++ reg_addr = (void * __iomem)(get_iproc_dmu_pcu_base() + ++ DMU_CRU_RESET_BASE); ++ /* set iproc_reset_n to 0 */ ++ reg = readl(reg_addr); ++ reg &= ~((u32) 1 << 1); ++ ++ writel(reg, reg_addr); ++ ++ /* Wait for reset */ ++ while (1) ++ cpu_do_idle(); ++} ++ ++DT_MACHINE_START(XGS_iProc_DT, "BRCM XGS iProc") ++ .init_early = xgs_iproc_init_early, ++ .init_machine = xgs_iproc_init, ++ .dt_compat = xgs_iproc_dt_compat, ++ .restart = xgs_iproc_restart, ++ .l2c_aux_val = 0, ++ .l2c_aux_mask = ~0, ++MACHINE_END +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/include/plat/shm.h b/arch/arm/mach-iproc/include/plat/shm.h +--- a/arch/arm/mach-iproc/include/plat/shm.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/include/plat/shm.h 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. ++ */ ++/* ++ * Header for declaring shim layer exports. ++ */ ++ ++#ifndef __SHM_DOT_H_INCLUDED__ ++#define __SHM_DOT_H_INCLUDED__ ++ ++#include ++#include ++#include ++ ++ ++#define iproc_class_create(owner, name) \ ++({ \ ++ static struct lock_class_key __key; \ ++ iproc__class_create(owner, name, &__key); \ ++}) ++ ++extern int iproc_platform_get_irq(struct platform_device *dev, unsigned int num); ++extern struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name); ++extern struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num); ++extern int iproc_platform_device_add_resources(struct platform_device *pdev, const struct resource *res, unsigned int num); ++ ++extern int iproc_platform_device_register(struct platform_device * pdev); ++extern void iproc_platform_device_unregister(struct platform_device * pdev); ++extern int iproc_platform_driver_register(struct platform_driver *drv); ++extern void iproc_platform_driver_unregister(struct platform_driver *drv); ++ ++extern struct platform_device *iproc_platform_device_alloc(const char *name, int id); ++ ++extern int iproc_platform_device_add(struct platform_device *pdev); ++extern void iproc_platform_device_put(struct platform_device *pdev); ++ ++extern void iproc_platform_device_put(struct platform_device *pdev); ++extern int iproc_platform_device_add(struct platform_device *pdev); ++extern void iproc_platform_device_del(struct platform_device *pdev); ++extern int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); ++extern void iproc_sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp); ++ ++ ++extern struct class *iproc__class_create(struct module *owner, const char *name, ++ struct lock_class_key *key); ++extern void iproc_class_destroy(struct class *cls); ++extern int iproc_device_create_file(struct device *dev, ++ const struct device_attribute *attr); ++extern struct device *iproc_device_create(struct class *class, ++ struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); ++extern void iproc_device_destroy(struct class *class, dev_t devt); ++extern void iproc_device_remove_file(struct device *dev, ++ const struct device_attribute *attr); ++extern int iproc_platform_get_irq_byname(struct platform_device *, const char *); ++ ++extern int iproc_gpio_to_irq(unsigned gpio); ++#endif /*#ifndef __SHM_DOT_H_INCLUDED__*/ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/platsmp.c b/arch/arm/mach-iproc/platsmp.c +--- a/arch/arm/mach-iproc/platsmp.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/platsmp.c 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,309 @@ ++/* ++ * Copyright (C) 2014-2015 Broadcom Corporation ++ * Copyright 2014 Linaro Limited ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include "../mach-bcm/platsmp.c" ++ ++#if 0 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Size of mapped Cortex A9 SCU address space */ ++#define CORTEX_A9_SCU_SIZE 0x58 ++ ++#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */ ++#define BOOT_ADDR_CPUID_MASK 0x3 ++ ++/* Name of device node property defining secondary boot register location */ ++#define OF_SECONDARY_BOOT "secondary-boot-reg" ++#define MPIDR_CPUID_BITMASK 0x3 ++ ++/* ++ * Enable the Cortex A9 Snoop Control Unit ++ * ++ * By the time this is called we already know there are multiple ++ * cores present. We assume we're running on a Cortex A9 processor, ++ * so any trouble getting the base address register or getting the ++ * SCU base is a problem. ++ * ++ * Return 0 if successful or an error code otherwise. ++ */ ++static int __init scu_a9_enable(void) ++{ ++ unsigned long config_base; ++ void __iomem *scu_base; ++ ++ if (!scu_a9_has_base()) { ++ pr_err("no configuration base address register!\n"); ++ return -ENXIO; ++ } ++ ++ /* Config base address register value is zero for uniprocessor */ ++ config_base = scu_a9_get_base(); ++ if (!config_base) { ++ pr_err("hardware reports only one core\n"); ++ return -ENOENT; ++ } ++ ++ scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); ++ if (!scu_base) { ++ pr_err("failed to remap config base (%lu/%u) for SCU\n", ++ config_base, CORTEX_A9_SCU_SIZE); ++ return -ENOMEM; ++ } ++ ++ scu_enable(scu_base); ++ ++ iounmap(scu_base); /* That's the last we'll need of this */ ++ ++ return 0; ++} ++ ++static u32 secondary_boot_addr_for(unsigned int cpu) ++{ ++ u32 secondary_boot_addr = 0; ++ struct device_node *cpu_node = of_get_cpu_node(cpu, NULL); ++ ++ if (!cpu_node) { ++ pr_err("Failed to find device tree node for CPU%u\n", cpu); ++ return 0; ++ } ++ ++ if (of_property_read_u32(cpu_node, ++ OF_SECONDARY_BOOT, ++ &secondary_boot_addr)) ++ pr_err("required secondary boot register not specified for CPU%u\n", ++ cpu); ++ ++ of_node_put(cpu_node); ++ ++ return secondary_boot_addr; ++} ++ ++static int nsp_write_lut(unsigned int cpu) ++{ ++ void __iomem *sku_rom_lut; ++ phys_addr_t secondary_startup_phy; ++ const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); ++ ++ if (!secondary_boot_addr) ++ return -EINVAL; ++ ++ sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, ++ sizeof(phys_addr_t)); ++ if (!sku_rom_lut) { ++ pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu); ++ return -ENOMEM; ++ } ++ ++ secondary_startup_phy = virt_to_phys(secondary_startup); ++ BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX); ++ ++ writel_relaxed(secondary_startup_phy, sku_rom_lut); ++ ++ /* Ensure the write is visible to the secondary core */ ++ smp_wmb(); ++ ++ iounmap(sku_rom_lut); ++ ++ return 0; ++} ++ ++static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; ++ ++ /* Enable the SCU on Cortex A9 based SoCs */ ++ if (scu_a9_enable()) { ++ /* Update the CPU present map to reflect uniprocessor mode */ ++ pr_warn("failed to enable A9 SCU - disabling SMP\n"); ++ init_cpu_present(&only_cpu_0); ++ } ++} ++ ++/* ++ * The ROM code has the secondary cores looping, waiting for an event. ++ * When an event occurs each core examines the bottom two bits of the ++ * secondary boot register. When a core finds those bits contain its ++ * own core id, it performs initialization, including computing its boot ++ * address by clearing the boot register value's bottom two bits. The ++ * core signals that it is beginning its execution by writing its boot ++ * address back to the secondary boot register, and finally jumps to ++ * that address. ++ * ++ * So to start a core executing we need to: ++ * - Encode the (hardware) CPU id with the bottom bits of the secondary ++ * start address. ++ * - Write that value into the secondary boot register. ++ * - Generate an event to wake up the secondary CPU(s). ++ * - Wait for the secondary boot register to be re-written, which ++ * indicates the secondary core has started. ++ */ ++static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ void __iomem *boot_reg; ++ phys_addr_t boot_func; ++ u64 start_clock; ++ u32 cpu_id; ++ u32 boot_val; ++ bool timeout = false; ++ const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); ++ ++ cpu_id = cpu_logical_map(cpu); ++ if (cpu_id & ~BOOT_ADDR_CPUID_MASK) { ++ pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK); ++ return -EINVAL; ++ } ++ ++ if (!secondary_boot_addr) ++ return -EINVAL; ++ ++ boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr, ++ sizeof(phys_addr_t)); ++ if (!boot_reg) { ++ pr_err("unable to map boot register for cpu %u\n", cpu_id); ++ return -ENOMEM; ++ } ++ ++ /* ++ * Secondary cores will start in secondary_startup(), ++ * defined in "arch/arm/kernel/head.S" ++ */ ++ boot_func = virt_to_phys(secondary_startup); ++ BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK); ++ BUG_ON(boot_func > (phys_addr_t)U32_MAX); ++ ++ /* The core to start is encoded in the low bits */ ++ boot_val = (u32)boot_func | cpu_id; ++ writel_relaxed(boot_val, boot_reg); ++ ++ sev(); ++ ++ /* The low bits will be cleared once the core has started */ ++ start_clock = local_clock(); ++ while (!timeout && readl_relaxed(boot_reg) == boot_val) ++ timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS; ++ ++ iounmap(boot_reg); ++ ++ if (!timeout) ++ return 0; ++ ++ pr_err("timeout waiting for cpu %u to start\n", cpu_id); ++ ++ return -ENXIO; ++} ++ ++/* Cluster Dormant Control command to bring CPU into a running state */ ++#define CDC_CMD 6 ++#define CDC_CMD_OFFSET 0 ++#define CDC_CMD_REG(cpu) (CDC_CMD_OFFSET + 4*(cpu)) ++ ++/* ++ * BCM23550 has a Cluster Dormant Control block that keeps the core in ++ * idle state. A command needs to be sent to the block to bring the CPU ++ * into running state. ++ */ ++static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ void __iomem *cdc_base; ++ struct device_node *dn; ++ char *name; ++ int ret; ++ ++ /* Make sure a CDC node exists before booting the ++ * secondary core. ++ */ ++ name = "brcm,bcm23550-cdc"; ++ dn = of_find_compatible_node(NULL, NULL, name); ++ if (!dn) { ++ pr_err("unable to find cdc node\n"); ++ return -ENODEV; ++ } ++ ++ cdc_base = of_iomap(dn, 0); ++ of_node_put(dn); ++ ++ if (!cdc_base) { ++ pr_err("unable to remap cdc base register\n"); ++ return -ENOMEM; ++ } ++ ++ /* Boot the secondary core */ ++ ret = kona_boot_secondary(cpu, idle); ++ if (ret) ++ goto out; ++ ++ /* Bring this CPU to RUN state so that nIRQ nFIQ ++ * signals are unblocked. ++ */ ++ writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu)); ++ ++out: ++ iounmap(cdc_base); ++ ++ return ret; ++} ++ ++static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ int ret; ++ ++ /* ++ * After wake up, secondary core branches to the startup ++ * address programmed at SKU ROM LUT location. ++ */ ++ ret = nsp_write_lut(cpu); ++ if (ret) { ++ pr_err("unable to write startup addr to SKU ROM LUT\n"); ++ goto out; ++ } ++ ++ /* Send a CPU wakeup interrupt to the secondary core */ ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ ++out: ++ return ret; ++} ++ ++static const struct smp_operations kona_smp_ops __initconst = { ++ .smp_prepare_cpus = bcm_smp_prepare_cpus, ++ .smp_boot_secondary = kona_boot_secondary, ++}; ++CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", ++ &kona_smp_ops); ++ ++static const struct smp_operations bcm23550_smp_ops __initconst = { ++ .smp_boot_secondary = bcm23550_boot_secondary, ++}; ++CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550", ++ &bcm23550_smp_ops); ++ ++static const struct smp_operations nsp_smp_ops __initconst = { ++ .smp_prepare_cpus = bcm_smp_prepare_cpus, ++ .smp_boot_secondary = nsp_boot_secondary, ++}; ++CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); ++#endif +\ No newline at end of file +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/shm.c b/arch/arm/mach-iproc/shm.c +--- a/arch/arm/mach-iproc/shm.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm/mach-iproc/shm.c 2018-05-10 11:31:28.505398457 +0800 +@@ -0,0 +1,309 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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/plat/shm.h" ++/** ++ * iproc_platform_get_irq - get an IRQ for a device ++ * wrapper function for platform_get_irq ++ * @dev: platform device ++ * @num: IRQ number index ++ */ ++int iproc_platform_get_irq(struct platform_device *dev, unsigned int num) ++{ ++ return platform_get_irq(dev, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_irq); ++ ++ ++/** ++ * iproc_platform_get_resource_byname - ++ * wrapper function for platform_get_resource_byname ++ * @dev: platform device ++ * @type: resource type ++ * @name: resource name ++ */ ++struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, ++ unsigned int type, ++ const char *name) ++{ ++ return platform_get_resource_byname(dev, type, name); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource_byname); ++ ++ ++/** ++ * iproc_platform_get_resource - ++ * wrapper function for platform_get_resource ++ * @dev: platform device ++ * @type: resource type ++ * @num: resource index ++ */ ++struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num) ++{ ++ return platform_get_resource(dev, type, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource); ++ ++ ++/** ++ * iproc_platform_driver_register - ++ * wrapper function for platform_driver_register ++ * @drv: platform driver structure ++ */ ++int iproc_platform_driver_register(struct platform_driver *drv) ++{ ++ return platform_driver_register(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_register); ++ ++ ++/** ++ * iproc_platform_driver_unregister ++ * wrapper function for platform_driver_unregister ++ * @drv: platform driver structure ++ */ ++void iproc_platform_driver_unregister(struct platform_driver *drv) ++{ ++ return platform_driver_unregister(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_unregister); ++ ++ ++/** ++ * iproc_platform_device_register - add a platform-level device ++ * wrapper function for platform_device_register ++ * @pdev: platform device we're adding ++ * ++ */ ++int iproc_platform_device_register(struct platform_device * pdev) ++{ ++ return platform_device_register(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_register); ++ ++ ++/** ++ * iproc_platform_device_unregister - ++ * wrapper function for platform_device_unregister ++ * @pdev: platform device we're unregistering ++ */ ++void iproc_platform_device_unregister(struct platform_device * pdev) ++{ ++ return platform_device_unregister(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_unregister); ++ ++ ++/** ++ * iproc_platform_device_alloc - ++ * wrapper function for platform_device_alloc ++ * @name: base name of the device we're adding ++ * @id: instance id ++ */ ++struct platform_device *iproc_platform_device_alloc(const char *name, int id) ++{ ++ return platform_device_alloc(name, id); ++} ++EXPORT_SYMBOL(iproc_platform_device_alloc); ++ ++/** ++ * iproc_platform_device_add - ++ * wrapper function for platform_device_add ++ * @pdev: platform device we're adding ++ */ ++int iproc_platform_device_add(struct platform_device *pdev) ++{ ++ return platform_device_add(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_add); ++ ++/** ++ * iproc_platform_device_del - ++ * wrapper function for platform_device_del ++ * @pdev: platform device we're removing ++ */ ++void iproc_platform_device_del(struct platform_device *pdev) ++{ ++ platform_device_del(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_del); ++ ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for platform_device_put ++ * @pdev: platform device to free ++ */ ++void iproc_platform_device_put(struct platform_device *pdev) ++{ ++ platform_device_put(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_put); ++ ++ ++/** ++ * iproc_platform_device_add_resources - ++ * wrapper function for platform_device_add_resources ++ * @pdev: platform device allocated by platform_device_alloc to add resources to ++ * @res: set of resources that needs to be allocated for the device ++ * @num: number of resources ++ */ ++int iproc_platform_device_add_resources(struct platform_device *pdev, ++ const struct resource *res, unsigned int num) ++{ ++ return platform_device_add_resources(pdev, res, num); ++} ++EXPORT_SYMBOL(iproc_platform_device_add_resources); ++ ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for sysfs_create_group ++ * @kobj: The kobject to create the group on ++ * @grp: The attribute group to create ++ */ ++int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) ++{ ++ return sysfs_create_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_create_group); ++ ++ ++/** ++ * iproc_sysfs_remove_group - ++ * wrapper function for sysfs_remove_group ++ * @kobj: The kobject which the group is on ++ * @grp: The attribute group to remove ++ */ ++void iproc_sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) ++{ ++ sysfs_remove_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_remove_group); ++ ++/** ++ * iproc__class_create - ++ * wrapper function for __class_create ++ * @ower: pointer to the module that is to "own" this struct class ++ * @name: pointer to a string for the name of this class. ++ * @key: the lock_class_key for this class; used by mutex lock debugging ++ */ ++struct class *iproc__class_create(struct module *owner, const char *name, ++ struct lock_class_key *key) ++{ ++ return __class_create(owner, name, key); ++} ++EXPORT_SYMBOL(iproc__class_create); ++ ++/** ++ * iproc_class_destroy - ++ * wrapper function for class_destroy ++ * @cls: pointer to the struct class that is to be destroyed ++ */ ++void iproc_class_destroy(struct class *cls) ++{ ++ class_destroy(cls); ++} ++EXPORT_SYMBOL(iproc_class_destroy); ++ ++/** ++ * iproc_device_create_file - ++ * wrapper function for device_create_file ++ * @dev: device. ++ * @attr: device attribute descriptor. ++ */ ++int iproc_device_create_file(struct device *dev, ++ const struct device_attribute *attr) ++{ ++ return device_create_file(dev, attr); ++} ++EXPORT_SYMBOL(iproc_device_create_file); ++ ++/** ++ * iproc_device_create - ++ * wrapper function for device_create ++ * ++ * @class: pointer to the struct class that this device should be ++ * registered to ++ * @parent: pointer to the parent struct device of this new device, if any ++ * @devt: the dev_t for the char device to be added ++ * @drvdata: the data to be added to the device for callbacks ++ * @fmt: string for the device's name ++ */ ++struct device *iproc_device_create(struct class *class, ++ struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) ++{ ++ va_list args; ++ struct device *r; ++ ++ va_start(args, fmt); ++ r = device_create_vargs(class, parent, devt, drvdata, fmt, args); ++ va_end(args); ++ ++ return r; ++} ++EXPORT_SYMBOL(iproc_device_create); ++ ++/** ++ * iproc_device_destroy - ++ * wrapper function for device_destroy ++ * @class: pointer to the struct class that this device was registered with ++ * @devt: the dev_t of the device that was previously registered ++ */ ++void iproc_device_destroy(struct class *class, dev_t devt) ++{ ++ return device_destroy(class, devt); ++} ++EXPORT_SYMBOL(iproc_device_destroy); ++ ++/** ++ * proc_device_remove_file - ++ * wrapper function for device_remove_file ++ * @dev: device. ++ * @attr: device attribute descriptor. ++ */ ++void iproc_device_remove_file(struct device *dev, ++ const struct device_attribute *attr) ++{ ++ return device_remove_file(dev, attr); ++} ++EXPORT_SYMBOL(iproc_device_remove_file); ++ ++/** ++ * iproc_platform_get_irq_byname - ++ * wrapper function for platform_get_irq_byname ++ * @dev: platform device ++ * @name: IRQ name ++ */ ++int iproc_platform_get_irq_byname(struct platform_device *dev, const char *n) ++{ ++ return platform_get_irq_byname(dev,n); ++} ++EXPORT_SYMBOL(iproc_platform_get_irq_byname); ++ ++/** ++ * iproc_gpio_to_irq - ++ * wrapper function for gpio_to_irq ++ * @gpio: gpio whose IRQ will be returned (already requested) ++ */ ++int iproc_gpio_to_irq(unsigned gpio) ++{ ++ return gpio_to_irq(gpio); ++} ++EXPORT_SYMBOL(iproc_gpio_to_irq); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm/mm/init.c b/arch/arm/mm/init.c +--- a/arch/arm/mm/init.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm/mm/init.c 2018-05-10 11:31:28.609398566 +0800 +@@ -721,6 +721,16 @@ static void update_sections_early(struct + for_each_process(t) { + if (t->flags & PF_KTHREAD) + continue; ++ ++ /* ++ * A process in getting shut down state (PF_EXITING), with its ++ * task mmu pointer (mm) being NULL, causes hang in ++ * set_section_perms(). ++ * NOTE: update_sections_early() runs if CONFIG_DEBUG_RODATA=y ++ */ ++ if (t->flags & PF_EXITING) ++ continue; ++ + for_each_thread(t, s) + set_section_perms(perms, n, true, s->mm); + } +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +--- a/arch/arm64/Kconfig.platforms 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm64/Kconfig.platforms 2018-05-10 11:31:28.629398587 +0800 +@@ -254,6 +254,14 @@ config ARCH_XGENE + help + This enables support for AppliedMicro X-Gene SOC Family + ++config ARCH_XGS_IPROC ++ bool "Broadcom iProc XGS SoC Family" ++ select ARCH_REQUIRE_GPIOLIB ++ select ARM_ARCH_TIMER ++ select ARM_GIC ++ help ++ This enables support for Broadcom XGS iProcbased SoC chips ++ + config ARCH_ZX + bool "ZTE ZX SoC Family" + select PINCTRL +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile +--- a/arch/arm64/boot/dts/broadcom/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/arch/arm64/boot/dts/broadcom/Makefile 2018-05-10 11:31:28.637398596 +0800 +@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp + + dts-dirs += northstar2 + dts-dirs += stingray ++dts-dirs += helix5 + always := $(dtb-y) + subdir-y := $(dts-dirs) + clean-files := *.dtb +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/boot/dts/broadcom/helix5/Makefile b/arch/arm64/boot/dts/broadcom/helix5/Makefile +--- a/arch/arm64/boot/dts/broadcom/helix5/Makefile 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/boot/dts/broadcom/helix5/Makefile 2018-05-10 11:31:28.637398596 +0800 +@@ -0,0 +1,5 @@ ++dtb-$(CONFIG_ARCH_XGS_IPROC) += bcm956370.dtb ++ ++always := $(dtb-y) ++subdir-y := $(dts-dirs) ++clean-files := *.dtb +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/boot/dts/broadcom/helix5/bcm-helix5.dtsi b/arch/arm64/boot/dts/broadcom/helix5/bcm-helix5.dtsi +--- a/arch/arm64/boot/dts/broadcom/helix5/bcm-helix5.dtsi 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/boot/dts/broadcom/helix5/bcm-helix5.dtsi 2018-05-31 15:24:26.192724756 +0800 +@@ -0,0 +1,377 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGdLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++ ++/ { ++ model = "Broadcom HX5 iProc"; ++ compatible = "brcm,helix5"; ++ interrupt-parent = <&gic>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a72", "arm,armv8"; ++ next-level-cache = <&L2>; ++ reg = <0 0>; ++ }; ++ ++ L2: l2-cache@000 { ++ compatible = "cache"; ++ }; ++ }; ++ ++ core { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ gic: interrupt-controller@10781000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x10781000 0x1000>, ++ <0x10782000 0x2000>, ++ <0x10784000 0x2000>, ++ <0x10786000 0x2000>; ++ interrupts = ; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ osc: oscillator_50M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <50000000>; ++ // clock-frequency = <35029>; ++ }; ++ ++ iproc_clk: iproc_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&osc>; ++ clock-div = <7>; ++ clock-mult = <120>; ++ }; ++ ++ iproc_clk250: iproc_clk250 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&osc>; ++ clock-div = <24>; ++ clock-mult = <120>; ++// compatible = "fixed-clock"; ++// clock-frequency = <153600>; ++ }; ++ ++ iproc_clk200: iproc_clk200 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&osc>; ++ clock-div = <1>; ++ clock-mult = <4>; ++ }; ++ }; ++ ++ axi { ++ compatible = "simple-bus"; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@10200000 { ++ compatible = "ns16550a"; ++ reg = <0x10200000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_clk250>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@10201000 { ++ compatible = "ns16550a"; ++ reg = <0x10201000 0x100>; ++ interrupts = ; ++ clocks = <&iproc_clk250>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@18047000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "brcm,spi-bcm-qspi", "brcm,spi-xgs-iproc-qspi"; ++ reg = <0x15000200 0x188>, ++ <0x15000000 0x050>, ++ <0x10236460 0x004>, ++ <0x150003a0 0x01c>, ++ <0x10241000 0x004>; ++ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg", "cru_ctrl"; ++ interrupts = ; ++ #chip-select = <0>; ++ clocks = <&iproc_clk250>; ++ status = "disabled"; ++ }; ++ ++ nand: nand@18046000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; ++ reg = <0x15001000 0x600>, ++ <0x1023787c 0x10>, ++ <0x15001f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ brcm,nand-has-wp; ++ status = "disabled"; ++ }; ++ ++ gmac0: ethernet@10239000 { ++ compatible = "brcm,xgs-iproc-apm,hx5"; ++ reg = <0x10239000 0x1000>, ++ <0x1025e000 0x1000>; ++ reg-names = "apm_base", "idm_base"; ++ pm-type = "pm4x10"; ++ land-idx = <0>; ++ tx-channels = <1>; ++ strict-mode = <1>; ++ interrupts = , ++ , ++ ; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@1023a000 { ++ compatible = "brcm,xgs-iproc-apm,hx5"; ++ reg = <0x1023a000 0x1000>, ++ <0x1025f000 0x1000>; ++ reg-names = "apm_base", "idm_base"; ++ pm-type = "pm4x10"; ++ land-idx = <2>; ++ tx-channels = <1>; ++ strict-mode = <1>; ++ interrupts = , ++ , ++ ; ++ status = "disabled"; ++ }; ++ ++ usbphy: usbphy { ++ #phy-cells = <0>; ++ compatible = "brcm,usb-phy,hx5"; ++ reg = icfg_usb: <0x102378c0 0x50>; ++ status = "disabled"; ++ }; ++ ++ xhci: usb@10243000 { ++ compatible = "generic-xhci"; ++ reg = <0x10243000 0x1000>; ++ interrupts = ; ++ usb-phy = <&usbphy>; ++ status = "disabled"; ++ }; ++ ++ usbd: usbd@10242000 { ++ compatible = "brcm,bdc,hx5"; ++ reg = <0x10242000 0x1000>; ++ interrupts = ; ++ usb-phy = <&usbphy>; ++ status = "disabled"; ++ }; ++ ++ gpio_ccg: gpio@10207000 { ++ compatible = "brcm,iproc-gpio,ccg"; ++ #gpio-cells = <2>; ++ reg = gpio: <0x10207000 0x50>; ++ ngpios = <10>; ++ pin-reg-bit-shift = <0>; ++ pin-base = <0>; ++ gpio-controller; ++ interrupt-controller; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@10202000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x10202000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@10203000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x10203000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@10204000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x10204000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@10205000 { ++ compatible = "brcm,iproc-i2c"; ++ reg = <0x10205000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ mdio_int: mdio_int@10019000 { ++ compatible = "brcm,iproc-cmicx-mdio"; ++ reg = <0x10019000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <3>; ++ bus-type = "internal"; ++ clocks = <&iproc_clk250>; ++ status = "disabled"; ++ }; ++ ++ mdio_ext: mdio_ext@10019000 { ++ compatible = "brcm,iproc-cmicx-mdio"; ++ reg = <0x10019000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #bus-id = <3>; ++ bus-type = "external"; ++ clocks = <&iproc_clk250>; ++ status = "disabled"; ++ }; ++ ++ hwrng: hwrng@1021e000 { ++ compatible = "brcm,iproc-rng200"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1021e000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ iproc_wdt: iproc_wdt@10211000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = iproc_wdt_base: <0x10211000 0x1000>, ++ iproc_reset_reg: <0x10220020 0x4>; ++ wdt_boot_status_bit = <0x0>; ++ interrupts = ; ++ clocks = <&iproc_clk250>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dmac0: dma@10234000 { ++ compatible = "brcm,dma330", "arm,primecell"; ++ reg = dma330_base: <0x10234000 0x1000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&iproc_clk250>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <16>; ++ status = "disabled"; ++ }; ++ ++ pl022: dma@10206000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ reg = pl022_base: <0x10206000 0x1000>; ++ interrupts = ; ++ clocks = <&iproc_clk250>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ }; ++ ++ dmu_pcu: dmu_pcu@10220000 { ++ compatible = "brcm,iproc-dmu-pcu"; ++ reg = <0 0x10220000 0 0xc00>; ++ }; ++ ++ iproc_wrap_ctrl: iproc_wrap_ctrl@10220c00 { ++ compatible = "brcm,iproc-wrap-ctrl"; ++ reg = <0 0x10220c00 0 0x100>; ++ }; ++ ++ iproc_idm: iproc_idm@10250000 { ++ compatible = "brcm,iproc-idm"; ++ reg = idm0: <0x10250000 0x100000>; ++ interrupts = ; ++ }; ++ ++ iproc_cmicx: iproc_cmicx@10100000 { ++ compatible = "brcm,iproc-cmicx"; ++ reg = cmicx: <0x10100000 0x200000>; ++ top-blkid = <7>; ++ amac-blkid = <38>; ++ interrupts = ; ++ }; ++}; +Binary files a/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dtb and b/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dtb differ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dts b/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dts +--- a/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dts 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/boot/dts/broadcom/helix5/bcm956370.dts 2018-05-31 15:24:26.196724803 +0800 +@@ -0,0 +1,216 @@ ++/* ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Broadcom Corporation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm-helix5.dtsi" ++ ++/ { ++ model = "Broadcom HX5 SVK (BCM956370K)"; ++ compatible = "brcm,bcm956370k", "brcm,helix5"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++ phy-handle = <&apm_phy0>; ++ phy-mode = "sgmii"; ++}; ++ ++&gmac1 { ++ status = "okay"; ++ phy-handle = <&apm_phy1>; ++ phy-mode = "sgmii"; ++}; ++/* ++&usbphy { ++ status = "okay"; ++}; ++ ++&xhci { ++ status = "okay"; ++}; ++ ++&usbd { ++ status = "okay"; ++}; ++*/ ++&gpio_ccg { ++ status = "okay"; ++}; ++ ++/* ++&pcie0 { ++ status = "okay"; ++}; ++*/ ++ ++&i2c0 { ++ status = "okay"; ++ eeprom@0x50 { ++ compatible = "atmel,24c64"; ++ reg = <0x50>; ++ pagesize = <32>; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&i2c2 { ++ status = "okay"; ++}; ++ ++&i2c3 { ++ status = "okay"; ++}; ++ ++&nand { ++ status = "okay"; ++ nandcs@1 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ nand-on-flash-bbt; ++ //nand-bus-width = <8>; ++ nand-ecc-strength = <24>; ++ nand-ecc-step-size = <1024>; ++ brcm,nand-oob-sector-size = <27>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "nboot"; ++ reg = <0x00000000 0x00200000>; ++ /* read-only; */ ++ }; ++ partition@1 { ++ label = "nenv"; ++ reg = <0x00200000 0x00400000>; ++ }; ++ partition@2 { ++ label = "nsystem"; ++ reg = <0x00600000 0x00a00000>; ++ }; ++ partition@3 { ++ label = "nrootfs"; ++ reg = <0x01000000 0x00f000000>; ++ }; ++ partition@4 { ++ label = "ncustfs"; ++ reg = <0x10000000 0x070000000>; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ flash: m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "m25p80"; ++ m25p,fast-read = <1>; ++ spi-max-frequency = <62500000>; ++ reg = <0x0>; ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x000c0000>; ++ //read-only; ++ }; ++ partition@1 { ++ label = "env"; ++ reg = <0x000c0000 0x00040000>; ++ }; ++ partition@2 { ++ label = "system"; ++ reg = <0x00100000 0x00f00000>; ++ }; ++ partition@3 { ++ label = "rootfs"; ++ reg = <0x01000000 0x03000000>; ++ }; ++ }; ++}; ++ ++&mdio_int { ++ status = "okay"; ++ apm_serdes0: apm_serdes@0 { ++ reg = <3>; ++ }; ++ apm_serdes1: apm_serdes@1 { ++ reg = <5>; ++ }; ++}; ++ ++&mdio_ext { ++ status = "okay"; ++ apm_phy0: apm_phy@0 { ++ reg = <16>; ++ }; ++ apm_phy1: apm_phy@1 { ++ reg = <17>; ++ }; ++}; ++ ++&hwrng { ++ status = "okay"; ++}; ++ ++&iproc_wdt { ++ status = "okay"; ++}; ++ ++&dmac0 { ++ status = "okay"; ++}; ++ ++&pl022 { ++ status = "okay"; ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/boot/dts/broadcom/helix5/helix5.its b/arch/arm64/boot/dts/broadcom/helix5/helix5.its +--- a/arch/arm64/boot/dts/broadcom/helix5/helix5.its 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/boot/dts/broadcom/helix5/helix5.its 2018-05-10 11:31:28.641398600 +0800 +@@ -0,0 +1,44 @@ ++/dts-v1/; ++ ++/ { ++ description = "Linux kernel and FDT blob"; ++ #address-cells = <1>; ++ ++ images { ++ kernel_1 { ++ description = "Broadcom iProc Linux"; ++ data = /incbin/("../../../Image.gz"); ++ type = "kernel"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <0x60080000>; ++ entry = <0x60080000>; ++ hash_1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ fdt_1 { ++ description = "Flattened Device Tree blob - bcm956370.dtb"; ++ data = /incbin/("./bcm956370.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ compression = "none"; ++ load = <0x60000000>; ++ hash_1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ default = "conf_1"; ++ conf_1 { ++ description = "Boot Linux kernel with FDT blob "; ++ kernel = "kernel_1"; ++ fdt = "fdt_1"; ++ }; ++ }; ++}; ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/configs/iproc_a72_be_defconfig b/arch/arm64/configs/iproc_a72_be_defconfig +--- a/arch/arm64/configs/iproc_a72_be_defconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/configs/iproc_a72_be_defconfig 2018-05-30 15:50:51.028753148 +0800 +@@ -0,0 +1,217 @@ ++CONFIG_CROSS_COMPILE="$CROSS_COMPILE" ++CONFIG_SYSVIPC=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=13 ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_BASE_FULL is not set ++# CONFIG_EPOLL is not set ++# CONFIG_SIGNALFD is not set ++# CONFIG_TIMERFD is not set ++# CONFIG_EVENTFD is not set ++# CONFIG_SHMEM is not set ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_ARCH_XGS_IPROC=y ++CONFIG_PCI=y ++CONFIG_CPU_BIG_ENDIAN=y ++CONFIG_NR_CPUS=4 ++CONFIG_PREEMPT=y ++CONFIG_HZ_100=y ++# CONFIG_COMPACTION is not set ++CONFIG_CMA=y ++CONFIG_CMA_DEBUG=y ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=496M" ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++CONFIG_IPV6_TUNNEL=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=y ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_TARGET_CT=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_RPFILTER=y ++CONFIG_IP6_NF_MATCH_RT=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_MTD=y ++CONFIG_MTD_TESTS=m ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_LE_BYTE_SWAP=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_M25P80=y ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_BRCMNAND=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_UBI=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++CONFIG_CHR_DEV_SG=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=y ++CONFIG_TIGON3=y ++# CONFIG_BGMAC_PLATFORM is not set ++CONFIG_APM=y ++CONFIG_MDIO_XGS_IPROC=y ++CONFIG_BROADCOM_PHY=y ++CONFIG_XGS_IPROC_SERDES=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_XGS_IPROC_RNG=y ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_SPI=y ++CONFIG_SPI_PL022=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_WATCHDOG=y ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_XGS_IPROC_DRD=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_BDC_UDC=y ++CONFIG_USB_BDC_XGS_IPROC=y ++CONFIG_USB_G_SERIAL=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++CONFIG_PL330_DMA=y ++# CONFIG_COMMON_CLK_XGENE is not set ++CONFIG_ACPI=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++# CONFIG_DNOTIFY is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=y ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_JFFS2_FS=y ++CONFIG_UBIFS_FS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFSD=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_DEBUG_FS=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM64_CE=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/configs/iproc_a72_defconfig b/arch/arm64/configs/iproc_a72_defconfig +--- a/arch/arm64/configs/iproc_a72_defconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/configs/iproc_a72_defconfig 2018-05-30 15:50:51.028753148 +0800 +@@ -0,0 +1,214 @@ ++CONFIG_CROSS_COMPILE="$CROSS_COMPILE" ++CONFIG_SYSVIPC=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=13 ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_BASE_FULL is not set ++# CONFIG_EPOLL is not set ++# CONFIG_SIGNALFD is not set ++# CONFIG_TIMERFD is not set ++# CONFIG_EVENTFD is not set ++# CONFIG_SHMEM is not set ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_ARCH_XGS_IPROC=y ++CONFIG_PCI=y ++CONFIG_NR_CPUS=4 ++CONFIG_PREEMPT=y ++CONFIG_HZ_100=y ++# CONFIG_COMPACTION is not set ++CONFIG_CMA=y ++CONFIG_CMA_DEBUG=y ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=496M" ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++CONFIG_IPV6_TUNNEL=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=y ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_TARGET_CT=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_RPFILTER=y ++CONFIG_IP6_NF_MATCH_RT=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_MTD=y ++CONFIG_MTD_TESTS=m ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_M25P80=y ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_BRCMNAND=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_UBI=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++CONFIG_CHR_DEV_SG=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=y ++CONFIG_TIGON3=y ++# CONFIG_BGMAC_PLATFORM is not set ++CONFIG_APM=y ++CONFIG_MDIO_XGS_IPROC=y ++CONFIG_BROADCOM_PHY=y ++CONFIG_XGS_IPROC_SERDES=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_XGS_IPROC_RNG=y ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_SPI=y ++CONFIG_SPI_PL022=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_WATCHDOG=y ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_XGS_IPROC_DRD=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_BDC_UDC=y ++CONFIG_USB_BDC_XGS_IPROC=y ++CONFIG_USB_G_SERIAL=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++CONFIG_PL330_DMA=y ++# CONFIG_COMMON_CLK_XGENE is not set ++CONFIG_ACPI=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++# CONFIG_DNOTIFY is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=y ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_JFFS2_FS=y ++CONFIG_UBIFS_FS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFSD=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_DEBUG_FS=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM64_CE=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/arch/arm64/crypto/sha256-core.S b/arch/arm64/crypto/sha256-core.S +--- a/arch/arm64/crypto/sha256-core.S 1970-01-01 08:00:00.000000000 +0800 ++++ b/arch/arm64/crypto/sha256-core.S 2018-05-10 12:01:00.939666414 +0800 +@@ -0,0 +1,2061 @@ ++// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. ++// ++// Licensed under the OpenSSL license (the "License"). You may not use ++// this file except in compliance with the License. You can obtain a copy ++// in the file LICENSE in the source distribution or at ++// https://www.openssl.org/source/license.html ++ ++// ==================================================================== ++// Written by Andy Polyakov for the OpenSSL ++// project. The module is, however, dual licensed under OpenSSL and ++// CRYPTOGAMS licenses depending on where you obtain it. For further ++// details see http://www.openssl.org/~appro/cryptogams/. ++// ++// Permission to use under GPLv2 terms is granted. ++// ==================================================================== ++// ++// SHA256/512 for ARMv8. ++// ++// Performance in cycles per processed byte and improvement coefficient ++// over code generated with "default" compiler: ++// ++// SHA256-hw SHA256(*) SHA512 ++// Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) ++// Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) ++// Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) ++// Denver 2.01 10.5 (+26%) 6.70 (+8%) ++// X-Gene 20.0 (+100%) 12.8 (+300%(***)) ++// Mongoose 2.36 13.0 (+50%) 8.36 (+33%) ++// ++// (*) Software SHA256 results are of lesser relevance, presented ++// mostly for informational purposes. ++// (**) The result is a trade-off: it's possible to improve it by ++// 10% (or by 1 cycle per round), but at the cost of 20% loss ++// on Cortex-A53 (or by 4 cycles per round). ++// (***) Super-impressive coefficients over gcc-generated code are ++// indication of some compiler "pathology", most notably code ++// generated with -mgeneral-regs-only is significanty faster ++// and the gap is only 40-90%. ++// ++// October 2016. ++// ++// Originally it was reckoned that it makes no sense to implement NEON ++// version of SHA256 for 64-bit processors. This is because performance ++// improvement on most wide-spread Cortex-A5x processors was observed ++// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was ++// observed that 32-bit NEON SHA256 performs significantly better than ++// 64-bit scalar version on *some* of the more recent processors. As ++// result 64-bit NEON version of SHA256 was added to provide best ++// all-round performance. For example it executes ~30% faster on X-Gene ++// and Mongoose. [For reference, NEON version of SHA512 is bound to ++// deliver much less improvement, likely *negative* on Cortex-A5x. ++// Which is why NEON support is limited to SHA256.] ++ ++#ifndef __KERNEL__ ++# include "arm_arch.h" ++#endif ++ ++.text ++ ++.extern OPENSSL_armcap_P ++.globl sha256_block_data_order ++.type sha256_block_data_order,%function ++.align 6 ++sha256_block_data_order: ++#ifndef __KERNEL__ ++# ifdef __ILP32__ ++ ldrsw x16,.LOPENSSL_armcap_P ++# else ++ ldr x16,.LOPENSSL_armcap_P ++# endif ++ adr x17,.LOPENSSL_armcap_P ++ add x16,x16,x17 ++ ldr w16,[x16] ++ tst w16,#ARMV8_SHA256 ++ b.ne .Lv8_entry ++ tst w16,#ARMV7_NEON ++ b.ne .Lneon_entry ++#endif ++ stp x29,x30,[sp,#-128]! ++ add x29,sp,#0 ++ ++ stp x19,x20,[sp,#16] ++ stp x21,x22,[sp,#32] ++ stp x23,x24,[sp,#48] ++ stp x25,x26,[sp,#64] ++ stp x27,x28,[sp,#80] ++ sub sp,sp,#4*4 ++ ++ ldp w20,w21,[x0] // load context ++ ldp w22,w23,[x0,#2*4] ++ ldp w24,w25,[x0,#4*4] ++ add x2,x1,x2,lsl#6 // end of input ++ ldp w26,w27,[x0,#6*4] ++ adr x30,.LK256 ++ stp x0,x2,[x29,#96] ++ ++.Loop: ++ ldp w3,w4,[x1],#2*4 ++ ldr w19,[x30],#4 // *K++ ++ eor w28,w21,w22 // magic seed ++ str x1,[x29,#112] ++#ifndef __AARCH64EB__ ++ rev w3,w3 // 0 ++#endif ++ ror w16,w24,#6 ++ add w27,w27,w19 // h+=K[i] ++ eor w6,w24,w24,ror#14 ++ and w17,w25,w24 ++ bic w19,w26,w24 ++ add w27,w27,w3 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w20,w21 // a^b, b^c in next round ++ eor w16,w16,w6,ror#11 // Sigma1(e) ++ ror w6,w20,#2 ++ add w27,w27,w17 // h+=Ch(e,f,g) ++ eor w17,w20,w20,ror#9 ++ add w27,w27,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w23,w23,w27 // d+=h ++ eor w28,w28,w21 // Maj(a,b,c) ++ eor w17,w6,w17,ror#13 // Sigma0(a) ++ add w27,w27,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w27,w27,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w4,w4 // 1 ++#endif ++ ldp w5,w6,[x1],#2*4 ++ add w27,w27,w17 // h+=Sigma0(a) ++ ror w16,w23,#6 ++ add w26,w26,w28 // h+=K[i] ++ eor w7,w23,w23,ror#14 ++ and w17,w24,w23 ++ bic w28,w25,w23 ++ add w26,w26,w4 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w27,w20 // a^b, b^c in next round ++ eor w16,w16,w7,ror#11 // Sigma1(e) ++ ror w7,w27,#2 ++ add w26,w26,w17 // h+=Ch(e,f,g) ++ eor w17,w27,w27,ror#9 ++ add w26,w26,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w22,w22,w26 // d+=h ++ eor w19,w19,w20 // Maj(a,b,c) ++ eor w17,w7,w17,ror#13 // Sigma0(a) ++ add w26,w26,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w26,w26,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w5,w5 // 2 ++#endif ++ add w26,w26,w17 // h+=Sigma0(a) ++ ror w16,w22,#6 ++ add w25,w25,w19 // h+=K[i] ++ eor w8,w22,w22,ror#14 ++ and w17,w23,w22 ++ bic w19,w24,w22 ++ add w25,w25,w5 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w26,w27 // a^b, b^c in next round ++ eor w16,w16,w8,ror#11 // Sigma1(e) ++ ror w8,w26,#2 ++ add w25,w25,w17 // h+=Ch(e,f,g) ++ eor w17,w26,w26,ror#9 ++ add w25,w25,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w21,w21,w25 // d+=h ++ eor w28,w28,w27 // Maj(a,b,c) ++ eor w17,w8,w17,ror#13 // Sigma0(a) ++ add w25,w25,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w25,w25,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w6,w6 // 3 ++#endif ++ ldp w7,w8,[x1],#2*4 ++ add w25,w25,w17 // h+=Sigma0(a) ++ ror w16,w21,#6 ++ add w24,w24,w28 // h+=K[i] ++ eor w9,w21,w21,ror#14 ++ and w17,w22,w21 ++ bic w28,w23,w21 ++ add w24,w24,w6 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w25,w26 // a^b, b^c in next round ++ eor w16,w16,w9,ror#11 // Sigma1(e) ++ ror w9,w25,#2 ++ add w24,w24,w17 // h+=Ch(e,f,g) ++ eor w17,w25,w25,ror#9 ++ add w24,w24,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w20,w20,w24 // d+=h ++ eor w19,w19,w26 // Maj(a,b,c) ++ eor w17,w9,w17,ror#13 // Sigma0(a) ++ add w24,w24,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w24,w24,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w7,w7 // 4 ++#endif ++ add w24,w24,w17 // h+=Sigma0(a) ++ ror w16,w20,#6 ++ add w23,w23,w19 // h+=K[i] ++ eor w10,w20,w20,ror#14 ++ and w17,w21,w20 ++ bic w19,w22,w20 ++ add w23,w23,w7 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w24,w25 // a^b, b^c in next round ++ eor w16,w16,w10,ror#11 // Sigma1(e) ++ ror w10,w24,#2 ++ add w23,w23,w17 // h+=Ch(e,f,g) ++ eor w17,w24,w24,ror#9 ++ add w23,w23,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w27,w27,w23 // d+=h ++ eor w28,w28,w25 // Maj(a,b,c) ++ eor w17,w10,w17,ror#13 // Sigma0(a) ++ add w23,w23,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w23,w23,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w8,w8 // 5 ++#endif ++ ldp w9,w10,[x1],#2*4 ++ add w23,w23,w17 // h+=Sigma0(a) ++ ror w16,w27,#6 ++ add w22,w22,w28 // h+=K[i] ++ eor w11,w27,w27,ror#14 ++ and w17,w20,w27 ++ bic w28,w21,w27 ++ add w22,w22,w8 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w23,w24 // a^b, b^c in next round ++ eor w16,w16,w11,ror#11 // Sigma1(e) ++ ror w11,w23,#2 ++ add w22,w22,w17 // h+=Ch(e,f,g) ++ eor w17,w23,w23,ror#9 ++ add w22,w22,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w26,w26,w22 // d+=h ++ eor w19,w19,w24 // Maj(a,b,c) ++ eor w17,w11,w17,ror#13 // Sigma0(a) ++ add w22,w22,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w22,w22,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w9,w9 // 6 ++#endif ++ add w22,w22,w17 // h+=Sigma0(a) ++ ror w16,w26,#6 ++ add w21,w21,w19 // h+=K[i] ++ eor w12,w26,w26,ror#14 ++ and w17,w27,w26 ++ bic w19,w20,w26 ++ add w21,w21,w9 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w22,w23 // a^b, b^c in next round ++ eor w16,w16,w12,ror#11 // Sigma1(e) ++ ror w12,w22,#2 ++ add w21,w21,w17 // h+=Ch(e,f,g) ++ eor w17,w22,w22,ror#9 ++ add w21,w21,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w25,w25,w21 // d+=h ++ eor w28,w28,w23 // Maj(a,b,c) ++ eor w17,w12,w17,ror#13 // Sigma0(a) ++ add w21,w21,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w21,w21,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w10,w10 // 7 ++#endif ++ ldp w11,w12,[x1],#2*4 ++ add w21,w21,w17 // h+=Sigma0(a) ++ ror w16,w25,#6 ++ add w20,w20,w28 // h+=K[i] ++ eor w13,w25,w25,ror#14 ++ and w17,w26,w25 ++ bic w28,w27,w25 ++ add w20,w20,w10 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w21,w22 // a^b, b^c in next round ++ eor w16,w16,w13,ror#11 // Sigma1(e) ++ ror w13,w21,#2 ++ add w20,w20,w17 // h+=Ch(e,f,g) ++ eor w17,w21,w21,ror#9 ++ add w20,w20,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w24,w24,w20 // d+=h ++ eor w19,w19,w22 // Maj(a,b,c) ++ eor w17,w13,w17,ror#13 // Sigma0(a) ++ add w20,w20,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w20,w20,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w11,w11 // 8 ++#endif ++ add w20,w20,w17 // h+=Sigma0(a) ++ ror w16,w24,#6 ++ add w27,w27,w19 // h+=K[i] ++ eor w14,w24,w24,ror#14 ++ and w17,w25,w24 ++ bic w19,w26,w24 ++ add w27,w27,w11 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w20,w21 // a^b, b^c in next round ++ eor w16,w16,w14,ror#11 // Sigma1(e) ++ ror w14,w20,#2 ++ add w27,w27,w17 // h+=Ch(e,f,g) ++ eor w17,w20,w20,ror#9 ++ add w27,w27,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w23,w23,w27 // d+=h ++ eor w28,w28,w21 // Maj(a,b,c) ++ eor w17,w14,w17,ror#13 // Sigma0(a) ++ add w27,w27,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w27,w27,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w12,w12 // 9 ++#endif ++ ldp w13,w14,[x1],#2*4 ++ add w27,w27,w17 // h+=Sigma0(a) ++ ror w16,w23,#6 ++ add w26,w26,w28 // h+=K[i] ++ eor w15,w23,w23,ror#14 ++ and w17,w24,w23 ++ bic w28,w25,w23 ++ add w26,w26,w12 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w27,w20 // a^b, b^c in next round ++ eor w16,w16,w15,ror#11 // Sigma1(e) ++ ror w15,w27,#2 ++ add w26,w26,w17 // h+=Ch(e,f,g) ++ eor w17,w27,w27,ror#9 ++ add w26,w26,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w22,w22,w26 // d+=h ++ eor w19,w19,w20 // Maj(a,b,c) ++ eor w17,w15,w17,ror#13 // Sigma0(a) ++ add w26,w26,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w26,w26,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w13,w13 // 10 ++#endif ++ add w26,w26,w17 // h+=Sigma0(a) ++ ror w16,w22,#6 ++ add w25,w25,w19 // h+=K[i] ++ eor w0,w22,w22,ror#14 ++ and w17,w23,w22 ++ bic w19,w24,w22 ++ add w25,w25,w13 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w26,w27 // a^b, b^c in next round ++ eor w16,w16,w0,ror#11 // Sigma1(e) ++ ror w0,w26,#2 ++ add w25,w25,w17 // h+=Ch(e,f,g) ++ eor w17,w26,w26,ror#9 ++ add w25,w25,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w21,w21,w25 // d+=h ++ eor w28,w28,w27 // Maj(a,b,c) ++ eor w17,w0,w17,ror#13 // Sigma0(a) ++ add w25,w25,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w25,w25,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w14,w14 // 11 ++#endif ++ ldp w15,w0,[x1],#2*4 ++ add w25,w25,w17 // h+=Sigma0(a) ++ str w6,[sp,#12] ++ ror w16,w21,#6 ++ add w24,w24,w28 // h+=K[i] ++ eor w6,w21,w21,ror#14 ++ and w17,w22,w21 ++ bic w28,w23,w21 ++ add w24,w24,w14 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w25,w26 // a^b, b^c in next round ++ eor w16,w16,w6,ror#11 // Sigma1(e) ++ ror w6,w25,#2 ++ add w24,w24,w17 // h+=Ch(e,f,g) ++ eor w17,w25,w25,ror#9 ++ add w24,w24,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w20,w20,w24 // d+=h ++ eor w19,w19,w26 // Maj(a,b,c) ++ eor w17,w6,w17,ror#13 // Sigma0(a) ++ add w24,w24,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w24,w24,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w15,w15 // 12 ++#endif ++ add w24,w24,w17 // h+=Sigma0(a) ++ str w7,[sp,#0] ++ ror w16,w20,#6 ++ add w23,w23,w19 // h+=K[i] ++ eor w7,w20,w20,ror#14 ++ and w17,w21,w20 ++ bic w19,w22,w20 ++ add w23,w23,w15 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w24,w25 // a^b, b^c in next round ++ eor w16,w16,w7,ror#11 // Sigma1(e) ++ ror w7,w24,#2 ++ add w23,w23,w17 // h+=Ch(e,f,g) ++ eor w17,w24,w24,ror#9 ++ add w23,w23,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w27,w27,w23 // d+=h ++ eor w28,w28,w25 // Maj(a,b,c) ++ eor w17,w7,w17,ror#13 // Sigma0(a) ++ add w23,w23,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w23,w23,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w0,w0 // 13 ++#endif ++ ldp w1,w2,[x1] ++ add w23,w23,w17 // h+=Sigma0(a) ++ str w8,[sp,#4] ++ ror w16,w27,#6 ++ add w22,w22,w28 // h+=K[i] ++ eor w8,w27,w27,ror#14 ++ and w17,w20,w27 ++ bic w28,w21,w27 ++ add w22,w22,w0 // h+=X[i] ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w23,w24 // a^b, b^c in next round ++ eor w16,w16,w8,ror#11 // Sigma1(e) ++ ror w8,w23,#2 ++ add w22,w22,w17 // h+=Ch(e,f,g) ++ eor w17,w23,w23,ror#9 ++ add w22,w22,w16 // h+=Sigma1(e) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ add w26,w26,w22 // d+=h ++ eor w19,w19,w24 // Maj(a,b,c) ++ eor w17,w8,w17,ror#13 // Sigma0(a) ++ add w22,w22,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ //add w22,w22,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w1,w1 // 14 ++#endif ++ ldr w6,[sp,#12] ++ add w22,w22,w17 // h+=Sigma0(a) ++ str w9,[sp,#8] ++ ror w16,w26,#6 ++ add w21,w21,w19 // h+=K[i] ++ eor w9,w26,w26,ror#14 ++ and w17,w27,w26 ++ bic w19,w20,w26 ++ add w21,w21,w1 // h+=X[i] ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w22,w23 // a^b, b^c in next round ++ eor w16,w16,w9,ror#11 // Sigma1(e) ++ ror w9,w22,#2 ++ add w21,w21,w17 // h+=Ch(e,f,g) ++ eor w17,w22,w22,ror#9 ++ add w21,w21,w16 // h+=Sigma1(e) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ add w25,w25,w21 // d+=h ++ eor w28,w28,w23 // Maj(a,b,c) ++ eor w17,w9,w17,ror#13 // Sigma0(a) ++ add w21,w21,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ //add w21,w21,w17 // h+=Sigma0(a) ++#ifndef __AARCH64EB__ ++ rev w2,w2 // 15 ++#endif ++ ldr w7,[sp,#0] ++ add w21,w21,w17 // h+=Sigma0(a) ++ str w10,[sp,#12] ++ ror w16,w25,#6 ++ add w20,w20,w28 // h+=K[i] ++ ror w9,w4,#7 ++ and w17,w26,w25 ++ ror w8,w1,#17 ++ bic w28,w27,w25 ++ ror w10,w21,#2 ++ add w20,w20,w2 // h+=X[i] ++ eor w16,w16,w25,ror#11 ++ eor w9,w9,w4,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w21,w22 // a^b, b^c in next round ++ eor w16,w16,w25,ror#25 // Sigma1(e) ++ eor w10,w10,w21,ror#13 ++ add w20,w20,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w8,w8,w1,ror#19 ++ eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) ++ add w20,w20,w16 // h+=Sigma1(e) ++ eor w19,w19,w22 // Maj(a,b,c) ++ eor w17,w10,w21,ror#22 // Sigma0(a) ++ eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) ++ add w3,w3,w12 ++ add w24,w24,w20 // d+=h ++ add w20,w20,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w3,w3,w9 ++ add w20,w20,w17 // h+=Sigma0(a) ++ add w3,w3,w8 ++.Loop_16_xx: ++ ldr w8,[sp,#4] ++ str w11,[sp,#0] ++ ror w16,w24,#6 ++ add w27,w27,w19 // h+=K[i] ++ ror w10,w5,#7 ++ and w17,w25,w24 ++ ror w9,w2,#17 ++ bic w19,w26,w24 ++ ror w11,w20,#2 ++ add w27,w27,w3 // h+=X[i] ++ eor w16,w16,w24,ror#11 ++ eor w10,w10,w5,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w20,w21 // a^b, b^c in next round ++ eor w16,w16,w24,ror#25 // Sigma1(e) ++ eor w11,w11,w20,ror#13 ++ add w27,w27,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w9,w9,w2,ror#19 ++ eor w10,w10,w5,lsr#3 // sigma0(X[i+1]) ++ add w27,w27,w16 // h+=Sigma1(e) ++ eor w28,w28,w21 // Maj(a,b,c) ++ eor w17,w11,w20,ror#22 // Sigma0(a) ++ eor w9,w9,w2,lsr#10 // sigma1(X[i+14]) ++ add w4,w4,w13 ++ add w23,w23,w27 // d+=h ++ add w27,w27,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w4,w4,w10 ++ add w27,w27,w17 // h+=Sigma0(a) ++ add w4,w4,w9 ++ ldr w9,[sp,#8] ++ str w12,[sp,#4] ++ ror w16,w23,#6 ++ add w26,w26,w28 // h+=K[i] ++ ror w11,w6,#7 ++ and w17,w24,w23 ++ ror w10,w3,#17 ++ bic w28,w25,w23 ++ ror w12,w27,#2 ++ add w26,w26,w4 // h+=X[i] ++ eor w16,w16,w23,ror#11 ++ eor w11,w11,w6,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w27,w20 // a^b, b^c in next round ++ eor w16,w16,w23,ror#25 // Sigma1(e) ++ eor w12,w12,w27,ror#13 ++ add w26,w26,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w10,w10,w3,ror#19 ++ eor w11,w11,w6,lsr#3 // sigma0(X[i+1]) ++ add w26,w26,w16 // h+=Sigma1(e) ++ eor w19,w19,w20 // Maj(a,b,c) ++ eor w17,w12,w27,ror#22 // Sigma0(a) ++ eor w10,w10,w3,lsr#10 // sigma1(X[i+14]) ++ add w5,w5,w14 ++ add w22,w22,w26 // d+=h ++ add w26,w26,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w5,w5,w11 ++ add w26,w26,w17 // h+=Sigma0(a) ++ add w5,w5,w10 ++ ldr w10,[sp,#12] ++ str w13,[sp,#8] ++ ror w16,w22,#6 ++ add w25,w25,w19 // h+=K[i] ++ ror w12,w7,#7 ++ and w17,w23,w22 ++ ror w11,w4,#17 ++ bic w19,w24,w22 ++ ror w13,w26,#2 ++ add w25,w25,w5 // h+=X[i] ++ eor w16,w16,w22,ror#11 ++ eor w12,w12,w7,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w26,w27 // a^b, b^c in next round ++ eor w16,w16,w22,ror#25 // Sigma1(e) ++ eor w13,w13,w26,ror#13 ++ add w25,w25,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w11,w11,w4,ror#19 ++ eor w12,w12,w7,lsr#3 // sigma0(X[i+1]) ++ add w25,w25,w16 // h+=Sigma1(e) ++ eor w28,w28,w27 // Maj(a,b,c) ++ eor w17,w13,w26,ror#22 // Sigma0(a) ++ eor w11,w11,w4,lsr#10 // sigma1(X[i+14]) ++ add w6,w6,w15 ++ add w21,w21,w25 // d+=h ++ add w25,w25,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w6,w6,w12 ++ add w25,w25,w17 // h+=Sigma0(a) ++ add w6,w6,w11 ++ ldr w11,[sp,#0] ++ str w14,[sp,#12] ++ ror w16,w21,#6 ++ add w24,w24,w28 // h+=K[i] ++ ror w13,w8,#7 ++ and w17,w22,w21 ++ ror w12,w5,#17 ++ bic w28,w23,w21 ++ ror w14,w25,#2 ++ add w24,w24,w6 // h+=X[i] ++ eor w16,w16,w21,ror#11 ++ eor w13,w13,w8,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w25,w26 // a^b, b^c in next round ++ eor w16,w16,w21,ror#25 // Sigma1(e) ++ eor w14,w14,w25,ror#13 ++ add w24,w24,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w12,w12,w5,ror#19 ++ eor w13,w13,w8,lsr#3 // sigma0(X[i+1]) ++ add w24,w24,w16 // h+=Sigma1(e) ++ eor w19,w19,w26 // Maj(a,b,c) ++ eor w17,w14,w25,ror#22 // Sigma0(a) ++ eor w12,w12,w5,lsr#10 // sigma1(X[i+14]) ++ add w7,w7,w0 ++ add w20,w20,w24 // d+=h ++ add w24,w24,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w7,w7,w13 ++ add w24,w24,w17 // h+=Sigma0(a) ++ add w7,w7,w12 ++ ldr w12,[sp,#4] ++ str w15,[sp,#0] ++ ror w16,w20,#6 ++ add w23,w23,w19 // h+=K[i] ++ ror w14,w9,#7 ++ and w17,w21,w20 ++ ror w13,w6,#17 ++ bic w19,w22,w20 ++ ror w15,w24,#2 ++ add w23,w23,w7 // h+=X[i] ++ eor w16,w16,w20,ror#11 ++ eor w14,w14,w9,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w24,w25 // a^b, b^c in next round ++ eor w16,w16,w20,ror#25 // Sigma1(e) ++ eor w15,w15,w24,ror#13 ++ add w23,w23,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w13,w13,w6,ror#19 ++ eor w14,w14,w9,lsr#3 // sigma0(X[i+1]) ++ add w23,w23,w16 // h+=Sigma1(e) ++ eor w28,w28,w25 // Maj(a,b,c) ++ eor w17,w15,w24,ror#22 // Sigma0(a) ++ eor w13,w13,w6,lsr#10 // sigma1(X[i+14]) ++ add w8,w8,w1 ++ add w27,w27,w23 // d+=h ++ add w23,w23,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w8,w8,w14 ++ add w23,w23,w17 // h+=Sigma0(a) ++ add w8,w8,w13 ++ ldr w13,[sp,#8] ++ str w0,[sp,#4] ++ ror w16,w27,#6 ++ add w22,w22,w28 // h+=K[i] ++ ror w15,w10,#7 ++ and w17,w20,w27 ++ ror w14,w7,#17 ++ bic w28,w21,w27 ++ ror w0,w23,#2 ++ add w22,w22,w8 // h+=X[i] ++ eor w16,w16,w27,ror#11 ++ eor w15,w15,w10,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w23,w24 // a^b, b^c in next round ++ eor w16,w16,w27,ror#25 // Sigma1(e) ++ eor w0,w0,w23,ror#13 ++ add w22,w22,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w14,w14,w7,ror#19 ++ eor w15,w15,w10,lsr#3 // sigma0(X[i+1]) ++ add w22,w22,w16 // h+=Sigma1(e) ++ eor w19,w19,w24 // Maj(a,b,c) ++ eor w17,w0,w23,ror#22 // Sigma0(a) ++ eor w14,w14,w7,lsr#10 // sigma1(X[i+14]) ++ add w9,w9,w2 ++ add w26,w26,w22 // d+=h ++ add w22,w22,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w9,w9,w15 ++ add w22,w22,w17 // h+=Sigma0(a) ++ add w9,w9,w14 ++ ldr w14,[sp,#12] ++ str w1,[sp,#8] ++ ror w16,w26,#6 ++ add w21,w21,w19 // h+=K[i] ++ ror w0,w11,#7 ++ and w17,w27,w26 ++ ror w15,w8,#17 ++ bic w19,w20,w26 ++ ror w1,w22,#2 ++ add w21,w21,w9 // h+=X[i] ++ eor w16,w16,w26,ror#11 ++ eor w0,w0,w11,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w22,w23 // a^b, b^c in next round ++ eor w16,w16,w26,ror#25 // Sigma1(e) ++ eor w1,w1,w22,ror#13 ++ add w21,w21,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w15,w15,w8,ror#19 ++ eor w0,w0,w11,lsr#3 // sigma0(X[i+1]) ++ add w21,w21,w16 // h+=Sigma1(e) ++ eor w28,w28,w23 // Maj(a,b,c) ++ eor w17,w1,w22,ror#22 // Sigma0(a) ++ eor w15,w15,w8,lsr#10 // sigma1(X[i+14]) ++ add w10,w10,w3 ++ add w25,w25,w21 // d+=h ++ add w21,w21,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w10,w10,w0 ++ add w21,w21,w17 // h+=Sigma0(a) ++ add w10,w10,w15 ++ ldr w15,[sp,#0] ++ str w2,[sp,#12] ++ ror w16,w25,#6 ++ add w20,w20,w28 // h+=K[i] ++ ror w1,w12,#7 ++ and w17,w26,w25 ++ ror w0,w9,#17 ++ bic w28,w27,w25 ++ ror w2,w21,#2 ++ add w20,w20,w10 // h+=X[i] ++ eor w16,w16,w25,ror#11 ++ eor w1,w1,w12,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w21,w22 // a^b, b^c in next round ++ eor w16,w16,w25,ror#25 // Sigma1(e) ++ eor w2,w2,w21,ror#13 ++ add w20,w20,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w0,w0,w9,ror#19 ++ eor w1,w1,w12,lsr#3 // sigma0(X[i+1]) ++ add w20,w20,w16 // h+=Sigma1(e) ++ eor w19,w19,w22 // Maj(a,b,c) ++ eor w17,w2,w21,ror#22 // Sigma0(a) ++ eor w0,w0,w9,lsr#10 // sigma1(X[i+14]) ++ add w11,w11,w4 ++ add w24,w24,w20 // d+=h ++ add w20,w20,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w11,w11,w1 ++ add w20,w20,w17 // h+=Sigma0(a) ++ add w11,w11,w0 ++ ldr w0,[sp,#4] ++ str w3,[sp,#0] ++ ror w16,w24,#6 ++ add w27,w27,w19 // h+=K[i] ++ ror w2,w13,#7 ++ and w17,w25,w24 ++ ror w1,w10,#17 ++ bic w19,w26,w24 ++ ror w3,w20,#2 ++ add w27,w27,w11 // h+=X[i] ++ eor w16,w16,w24,ror#11 ++ eor w2,w2,w13,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w20,w21 // a^b, b^c in next round ++ eor w16,w16,w24,ror#25 // Sigma1(e) ++ eor w3,w3,w20,ror#13 ++ add w27,w27,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w1,w1,w10,ror#19 ++ eor w2,w2,w13,lsr#3 // sigma0(X[i+1]) ++ add w27,w27,w16 // h+=Sigma1(e) ++ eor w28,w28,w21 // Maj(a,b,c) ++ eor w17,w3,w20,ror#22 // Sigma0(a) ++ eor w1,w1,w10,lsr#10 // sigma1(X[i+14]) ++ add w12,w12,w5 ++ add w23,w23,w27 // d+=h ++ add w27,w27,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w12,w12,w2 ++ add w27,w27,w17 // h+=Sigma0(a) ++ add w12,w12,w1 ++ ldr w1,[sp,#8] ++ str w4,[sp,#4] ++ ror w16,w23,#6 ++ add w26,w26,w28 // h+=K[i] ++ ror w3,w14,#7 ++ and w17,w24,w23 ++ ror w2,w11,#17 ++ bic w28,w25,w23 ++ ror w4,w27,#2 ++ add w26,w26,w12 // h+=X[i] ++ eor w16,w16,w23,ror#11 ++ eor w3,w3,w14,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w27,w20 // a^b, b^c in next round ++ eor w16,w16,w23,ror#25 // Sigma1(e) ++ eor w4,w4,w27,ror#13 ++ add w26,w26,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w2,w2,w11,ror#19 ++ eor w3,w3,w14,lsr#3 // sigma0(X[i+1]) ++ add w26,w26,w16 // h+=Sigma1(e) ++ eor w19,w19,w20 // Maj(a,b,c) ++ eor w17,w4,w27,ror#22 // Sigma0(a) ++ eor w2,w2,w11,lsr#10 // sigma1(X[i+14]) ++ add w13,w13,w6 ++ add w22,w22,w26 // d+=h ++ add w26,w26,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w13,w13,w3 ++ add w26,w26,w17 // h+=Sigma0(a) ++ add w13,w13,w2 ++ ldr w2,[sp,#12] ++ str w5,[sp,#8] ++ ror w16,w22,#6 ++ add w25,w25,w19 // h+=K[i] ++ ror w4,w15,#7 ++ and w17,w23,w22 ++ ror w3,w12,#17 ++ bic w19,w24,w22 ++ ror w5,w26,#2 ++ add w25,w25,w13 // h+=X[i] ++ eor w16,w16,w22,ror#11 ++ eor w4,w4,w15,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w26,w27 // a^b, b^c in next round ++ eor w16,w16,w22,ror#25 // Sigma1(e) ++ eor w5,w5,w26,ror#13 ++ add w25,w25,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w3,w3,w12,ror#19 ++ eor w4,w4,w15,lsr#3 // sigma0(X[i+1]) ++ add w25,w25,w16 // h+=Sigma1(e) ++ eor w28,w28,w27 // Maj(a,b,c) ++ eor w17,w5,w26,ror#22 // Sigma0(a) ++ eor w3,w3,w12,lsr#10 // sigma1(X[i+14]) ++ add w14,w14,w7 ++ add w21,w21,w25 // d+=h ++ add w25,w25,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w14,w14,w4 ++ add w25,w25,w17 // h+=Sigma0(a) ++ add w14,w14,w3 ++ ldr w3,[sp,#0] ++ str w6,[sp,#12] ++ ror w16,w21,#6 ++ add w24,w24,w28 // h+=K[i] ++ ror w5,w0,#7 ++ and w17,w22,w21 ++ ror w4,w13,#17 ++ bic w28,w23,w21 ++ ror w6,w25,#2 ++ add w24,w24,w14 // h+=X[i] ++ eor w16,w16,w21,ror#11 ++ eor w5,w5,w0,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w25,w26 // a^b, b^c in next round ++ eor w16,w16,w21,ror#25 // Sigma1(e) ++ eor w6,w6,w25,ror#13 ++ add w24,w24,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w4,w4,w13,ror#19 ++ eor w5,w5,w0,lsr#3 // sigma0(X[i+1]) ++ add w24,w24,w16 // h+=Sigma1(e) ++ eor w19,w19,w26 // Maj(a,b,c) ++ eor w17,w6,w25,ror#22 // Sigma0(a) ++ eor w4,w4,w13,lsr#10 // sigma1(X[i+14]) ++ add w15,w15,w8 ++ add w20,w20,w24 // d+=h ++ add w24,w24,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w15,w15,w5 ++ add w24,w24,w17 // h+=Sigma0(a) ++ add w15,w15,w4 ++ ldr w4,[sp,#4] ++ str w7,[sp,#0] ++ ror w16,w20,#6 ++ add w23,w23,w19 // h+=K[i] ++ ror w6,w1,#7 ++ and w17,w21,w20 ++ ror w5,w14,#17 ++ bic w19,w22,w20 ++ ror w7,w24,#2 ++ add w23,w23,w15 // h+=X[i] ++ eor w16,w16,w20,ror#11 ++ eor w6,w6,w1,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w24,w25 // a^b, b^c in next round ++ eor w16,w16,w20,ror#25 // Sigma1(e) ++ eor w7,w7,w24,ror#13 ++ add w23,w23,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w5,w5,w14,ror#19 ++ eor w6,w6,w1,lsr#3 // sigma0(X[i+1]) ++ add w23,w23,w16 // h+=Sigma1(e) ++ eor w28,w28,w25 // Maj(a,b,c) ++ eor w17,w7,w24,ror#22 // Sigma0(a) ++ eor w5,w5,w14,lsr#10 // sigma1(X[i+14]) ++ add w0,w0,w9 ++ add w27,w27,w23 // d+=h ++ add w23,w23,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w0,w0,w6 ++ add w23,w23,w17 // h+=Sigma0(a) ++ add w0,w0,w5 ++ ldr w5,[sp,#8] ++ str w8,[sp,#4] ++ ror w16,w27,#6 ++ add w22,w22,w28 // h+=K[i] ++ ror w7,w2,#7 ++ and w17,w20,w27 ++ ror w6,w15,#17 ++ bic w28,w21,w27 ++ ror w8,w23,#2 ++ add w22,w22,w0 // h+=X[i] ++ eor w16,w16,w27,ror#11 ++ eor w7,w7,w2,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w23,w24 // a^b, b^c in next round ++ eor w16,w16,w27,ror#25 // Sigma1(e) ++ eor w8,w8,w23,ror#13 ++ add w22,w22,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w6,w6,w15,ror#19 ++ eor w7,w7,w2,lsr#3 // sigma0(X[i+1]) ++ add w22,w22,w16 // h+=Sigma1(e) ++ eor w19,w19,w24 // Maj(a,b,c) ++ eor w17,w8,w23,ror#22 // Sigma0(a) ++ eor w6,w6,w15,lsr#10 // sigma1(X[i+14]) ++ add w1,w1,w10 ++ add w26,w26,w22 // d+=h ++ add w22,w22,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w1,w1,w7 ++ add w22,w22,w17 // h+=Sigma0(a) ++ add w1,w1,w6 ++ ldr w6,[sp,#12] ++ str w9,[sp,#8] ++ ror w16,w26,#6 ++ add w21,w21,w19 // h+=K[i] ++ ror w8,w3,#7 ++ and w17,w27,w26 ++ ror w7,w0,#17 ++ bic w19,w20,w26 ++ ror w9,w22,#2 ++ add w21,w21,w1 // h+=X[i] ++ eor w16,w16,w26,ror#11 ++ eor w8,w8,w3,ror#18 ++ orr w17,w17,w19 // Ch(e,f,g) ++ eor w19,w22,w23 // a^b, b^c in next round ++ eor w16,w16,w26,ror#25 // Sigma1(e) ++ eor w9,w9,w22,ror#13 ++ add w21,w21,w17 // h+=Ch(e,f,g) ++ and w28,w28,w19 // (b^c)&=(a^b) ++ eor w7,w7,w0,ror#19 ++ eor w8,w8,w3,lsr#3 // sigma0(X[i+1]) ++ add w21,w21,w16 // h+=Sigma1(e) ++ eor w28,w28,w23 // Maj(a,b,c) ++ eor w17,w9,w22,ror#22 // Sigma0(a) ++ eor w7,w7,w0,lsr#10 // sigma1(X[i+14]) ++ add w2,w2,w11 ++ add w25,w25,w21 // d+=h ++ add w21,w21,w28 // h+=Maj(a,b,c) ++ ldr w28,[x30],#4 // *K++, w19 in next round ++ add w2,w2,w8 ++ add w21,w21,w17 // h+=Sigma0(a) ++ add w2,w2,w7 ++ ldr w7,[sp,#0] ++ str w10,[sp,#12] ++ ror w16,w25,#6 ++ add w20,w20,w28 // h+=K[i] ++ ror w9,w4,#7 ++ and w17,w26,w25 ++ ror w8,w1,#17 ++ bic w28,w27,w25 ++ ror w10,w21,#2 ++ add w20,w20,w2 // h+=X[i] ++ eor w16,w16,w25,ror#11 ++ eor w9,w9,w4,ror#18 ++ orr w17,w17,w28 // Ch(e,f,g) ++ eor w28,w21,w22 // a^b, b^c in next round ++ eor w16,w16,w25,ror#25 // Sigma1(e) ++ eor w10,w10,w21,ror#13 ++ add w20,w20,w17 // h+=Ch(e,f,g) ++ and w19,w19,w28 // (b^c)&=(a^b) ++ eor w8,w8,w1,ror#19 ++ eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) ++ add w20,w20,w16 // h+=Sigma1(e) ++ eor w19,w19,w22 // Maj(a,b,c) ++ eor w17,w10,w21,ror#22 // Sigma0(a) ++ eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) ++ add w3,w3,w12 ++ add w24,w24,w20 // d+=h ++ add w20,w20,w19 // h+=Maj(a,b,c) ++ ldr w19,[x30],#4 // *K++, w28 in next round ++ add w3,w3,w9 ++ add w20,w20,w17 // h+=Sigma0(a) ++ add w3,w3,w8 ++ cbnz w19,.Loop_16_xx ++ ++ ldp x0,x2,[x29,#96] ++ ldr x1,[x29,#112] ++ sub x30,x30,#260 // rewind ++ ++ ldp w3,w4,[x0] ++ ldp w5,w6,[x0,#2*4] ++ add x1,x1,#14*4 // advance input pointer ++ ldp w7,w8,[x0,#4*4] ++ add w20,w20,w3 ++ ldp w9,w10,[x0,#6*4] ++ add w21,w21,w4 ++ add w22,w22,w5 ++ add w23,w23,w6 ++ stp w20,w21,[x0] ++ add w24,w24,w7 ++ add w25,w25,w8 ++ stp w22,w23,[x0,#2*4] ++ add w26,w26,w9 ++ add w27,w27,w10 ++ cmp x1,x2 ++ stp w24,w25,[x0,#4*4] ++ stp w26,w27,[x0,#6*4] ++ b.ne .Loop ++ ++ ldp x19,x20,[x29,#16] ++ add sp,sp,#4*4 ++ ldp x21,x22,[x29,#32] ++ ldp x23,x24,[x29,#48] ++ ldp x25,x26,[x29,#64] ++ ldp x27,x28,[x29,#80] ++ ldp x29,x30,[sp],#128 ++ ret ++.size sha256_block_data_order,.-sha256_block_data_order ++ ++.align 6 ++.type .LK256,%object ++.LK256: ++ .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 ++ .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 ++ .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 ++ .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 ++ .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc ++ .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da ++ .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 ++ .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 ++ .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 ++ .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 ++ .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 ++ .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 ++ .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 ++ .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 ++ .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 ++ .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 ++ .long 0 //terminator ++.size .LK256,.-.LK256 ++#ifndef __KERNEL__ ++.align 3 ++.LOPENSSL_armcap_P: ++# ifdef __ILP32__ ++ .long OPENSSL_armcap_P-. ++# else ++ .quad OPENSSL_armcap_P-. ++# endif ++#endif ++.asciz "SHA256 block transform for ARMv8, CRYPTOGAMS by " ++.align 2 ++#ifndef __KERNEL__ ++.type sha256_block_armv8,%function ++.align 6 ++sha256_block_armv8: ++.Lv8_entry: ++ stp x29,x30,[sp,#-16]! ++ add x29,sp,#0 ++ ++ ld1 {v0.4s,v1.4s},[x0] ++ adr x3,.LK256 ++ ++.Loop_hw: ++ ld1 {v4.16b-v7.16b},[x1],#64 ++ sub x2,x2,#1 ++ ld1 {v16.4s},[x3],#16 ++ rev32 v4.16b,v4.16b ++ rev32 v5.16b,v5.16b ++ rev32 v6.16b,v6.16b ++ rev32 v7.16b,v7.16b ++ orr v18.16b,v0.16b,v0.16b // offload ++ orr v19.16b,v1.16b,v1.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v4.4s ++ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v5.4s ++ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v6.4s ++ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v7.4s ++ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v4.4s ++ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v5.4s ++ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v6.4s ++ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v7.4s ++ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v4.4s ++ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v5.4s ++ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v6.4s ++ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v7.4s ++ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b ++ ld1 {v17.4s},[x3],#16 ++ add v16.4s,v16.4s,v4.4s ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ ++ ld1 {v16.4s},[x3],#16 ++ add v17.4s,v17.4s,v5.4s ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ ++ ld1 {v17.4s},[x3] ++ add v16.4s,v16.4s,v6.4s ++ sub x3,x3,#64*4-16 // rewind ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s ++ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s ++ ++ add v17.4s,v17.4s,v7.4s ++ orr v2.16b,v0.16b,v0.16b ++ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s ++ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s ++ ++ add v0.4s,v0.4s,v18.4s ++ add v1.4s,v1.4s,v19.4s ++ ++ cbnz x2,.Loop_hw ++ ++ st1 {v0.4s,v1.4s},[x0] ++ ++ ldr x29,[sp],#16 ++ ret ++.size sha256_block_armv8,.-sha256_block_armv8 ++#endif ++#ifdef __KERNEL__ ++.globl sha256_block_neon ++#endif ++.type sha256_block_neon,%function ++.align 4 ++sha256_block_neon: ++.Lneon_entry: ++ stp x29, x30, [sp, #-16]! ++ mov x29, sp ++ sub sp,sp,#16*4 ++ ++ adr x16,.LK256 ++ add x2,x1,x2,lsl#6 // len to point at the end of inp ++ ++ ld1 {v0.16b},[x1], #16 ++ ld1 {v1.16b},[x1], #16 ++ ld1 {v2.16b},[x1], #16 ++ ld1 {v3.16b},[x1], #16 ++ ld1 {v4.4s},[x16], #16 ++ ld1 {v5.4s},[x16], #16 ++ ld1 {v6.4s},[x16], #16 ++ ld1 {v7.4s},[x16], #16 ++ rev32 v0.16b,v0.16b // yes, even on ++ rev32 v1.16b,v1.16b // big-endian ++ rev32 v2.16b,v2.16b ++ rev32 v3.16b,v3.16b ++ mov x17,sp ++ add v4.4s,v4.4s,v0.4s ++ add v5.4s,v5.4s,v1.4s ++ add v6.4s,v6.4s,v2.4s ++ st1 {v4.4s-v5.4s},[x17], #32 ++ add v7.4s,v7.4s,v3.4s ++ st1 {v6.4s-v7.4s},[x17] ++ sub x17,x17,#32 ++ ++ ldp w3,w4,[x0] ++ ldp w5,w6,[x0,#8] ++ ldp w7,w8,[x0,#16] ++ ldp w9,w10,[x0,#24] ++ ldr w12,[sp,#0] ++ mov w13,wzr ++ eor w14,w4,w5 ++ mov w15,wzr ++ b .L_00_48 ++ ++.align 4 ++.L_00_48: ++ ext v4.16b,v0.16b,v1.16b,#4 ++ add w10,w10,w12 ++ add w3,w3,w15 ++ and w12,w8,w7 ++ bic w15,w9,w7 ++ ext v7.16b,v2.16b,v3.16b,#4 ++ eor w11,w7,w7,ror#5 ++ add w3,w3,w13 ++ mov d19,v3.d[1] ++ orr w12,w12,w15 ++ eor w11,w11,w7,ror#19 ++ ushr v6.4s,v4.4s,#7 ++ eor w15,w3,w3,ror#11 ++ ushr v5.4s,v4.4s,#3 ++ add w10,w10,w12 ++ add v0.4s,v0.4s,v7.4s ++ ror w11,w11,#6 ++ sli v6.4s,v4.4s,#25 ++ eor w13,w3,w4 ++ eor w15,w15,w3,ror#20 ++ ushr v7.4s,v4.4s,#18 ++ add w10,w10,w11 ++ ldr w12,[sp,#4] ++ and w14,w14,w13 ++ eor v5.16b,v5.16b,v6.16b ++ ror w15,w15,#2 ++ add w6,w6,w10 ++ sli v7.4s,v4.4s,#14 ++ eor w14,w14,w4 ++ ushr v16.4s,v19.4s,#17 ++ add w9,w9,w12 ++ add w10,w10,w15 ++ and w12,w7,w6 ++ eor v5.16b,v5.16b,v7.16b ++ bic w15,w8,w6 ++ eor w11,w6,w6,ror#5 ++ sli v16.4s,v19.4s,#15 ++ add w10,w10,w14 ++ orr w12,w12,w15 ++ ushr v17.4s,v19.4s,#10 ++ eor w11,w11,w6,ror#19 ++ eor w15,w10,w10,ror#11 ++ ushr v7.4s,v19.4s,#19 ++ add w9,w9,w12 ++ ror w11,w11,#6 ++ add v0.4s,v0.4s,v5.4s ++ eor w14,w10,w3 ++ eor w15,w15,w10,ror#20 ++ sli v7.4s,v19.4s,#13 ++ add w9,w9,w11 ++ ldr w12,[sp,#8] ++ and w13,w13,w14 ++ eor v17.16b,v17.16b,v16.16b ++ ror w15,w15,#2 ++ add w5,w5,w9 ++ eor w13,w13,w3 ++ eor v17.16b,v17.16b,v7.16b ++ add w8,w8,w12 ++ add w9,w9,w15 ++ and w12,w6,w5 ++ add v0.4s,v0.4s,v17.4s ++ bic w15,w7,w5 ++ eor w11,w5,w5,ror#5 ++ add w9,w9,w13 ++ ushr v18.4s,v0.4s,#17 ++ orr w12,w12,w15 ++ ushr v19.4s,v0.4s,#10 ++ eor w11,w11,w5,ror#19 ++ eor w15,w9,w9,ror#11 ++ sli v18.4s,v0.4s,#15 ++ add w8,w8,w12 ++ ushr v17.4s,v0.4s,#19 ++ ror w11,w11,#6 ++ eor w13,w9,w10 ++ eor v19.16b,v19.16b,v18.16b ++ eor w15,w15,w9,ror#20 ++ add w8,w8,w11 ++ sli v17.4s,v0.4s,#13 ++ ldr w12,[sp,#12] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ ld1 {v4.4s},[x16], #16 ++ add w4,w4,w8 ++ eor v19.16b,v19.16b,v17.16b ++ eor w14,w14,w10 ++ eor v17.16b,v17.16b,v17.16b ++ add w7,w7,w12 ++ add w8,w8,w15 ++ and w12,w5,w4 ++ mov v17.d[1],v19.d[0] ++ bic w15,w6,w4 ++ eor w11,w4,w4,ror#5 ++ add w8,w8,w14 ++ add v0.4s,v0.4s,v17.4s ++ orr w12,w12,w15 ++ eor w11,w11,w4,ror#19 ++ eor w15,w8,w8,ror#11 ++ add v4.4s,v4.4s,v0.4s ++ add w7,w7,w12 ++ ror w11,w11,#6 ++ eor w14,w8,w9 ++ eor w15,w15,w8,ror#20 ++ add w7,w7,w11 ++ ldr w12,[sp,#16] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w3,w3,w7 ++ eor w13,w13,w9 ++ st1 {v4.4s},[x17], #16 ++ ext v4.16b,v1.16b,v2.16b,#4 ++ add w6,w6,w12 ++ add w7,w7,w15 ++ and w12,w4,w3 ++ bic w15,w5,w3 ++ ext v7.16b,v3.16b,v0.16b,#4 ++ eor w11,w3,w3,ror#5 ++ add w7,w7,w13 ++ mov d19,v0.d[1] ++ orr w12,w12,w15 ++ eor w11,w11,w3,ror#19 ++ ushr v6.4s,v4.4s,#7 ++ eor w15,w7,w7,ror#11 ++ ushr v5.4s,v4.4s,#3 ++ add w6,w6,w12 ++ add v1.4s,v1.4s,v7.4s ++ ror w11,w11,#6 ++ sli v6.4s,v4.4s,#25 ++ eor w13,w7,w8 ++ eor w15,w15,w7,ror#20 ++ ushr v7.4s,v4.4s,#18 ++ add w6,w6,w11 ++ ldr w12,[sp,#20] ++ and w14,w14,w13 ++ eor v5.16b,v5.16b,v6.16b ++ ror w15,w15,#2 ++ add w10,w10,w6 ++ sli v7.4s,v4.4s,#14 ++ eor w14,w14,w8 ++ ushr v16.4s,v19.4s,#17 ++ add w5,w5,w12 ++ add w6,w6,w15 ++ and w12,w3,w10 ++ eor v5.16b,v5.16b,v7.16b ++ bic w15,w4,w10 ++ eor w11,w10,w10,ror#5 ++ sli v16.4s,v19.4s,#15 ++ add w6,w6,w14 ++ orr w12,w12,w15 ++ ushr v17.4s,v19.4s,#10 ++ eor w11,w11,w10,ror#19 ++ eor w15,w6,w6,ror#11 ++ ushr v7.4s,v19.4s,#19 ++ add w5,w5,w12 ++ ror w11,w11,#6 ++ add v1.4s,v1.4s,v5.4s ++ eor w14,w6,w7 ++ eor w15,w15,w6,ror#20 ++ sli v7.4s,v19.4s,#13 ++ add w5,w5,w11 ++ ldr w12,[sp,#24] ++ and w13,w13,w14 ++ eor v17.16b,v17.16b,v16.16b ++ ror w15,w15,#2 ++ add w9,w9,w5 ++ eor w13,w13,w7 ++ eor v17.16b,v17.16b,v7.16b ++ add w4,w4,w12 ++ add w5,w5,w15 ++ and w12,w10,w9 ++ add v1.4s,v1.4s,v17.4s ++ bic w15,w3,w9 ++ eor w11,w9,w9,ror#5 ++ add w5,w5,w13 ++ ushr v18.4s,v1.4s,#17 ++ orr w12,w12,w15 ++ ushr v19.4s,v1.4s,#10 ++ eor w11,w11,w9,ror#19 ++ eor w15,w5,w5,ror#11 ++ sli v18.4s,v1.4s,#15 ++ add w4,w4,w12 ++ ushr v17.4s,v1.4s,#19 ++ ror w11,w11,#6 ++ eor w13,w5,w6 ++ eor v19.16b,v19.16b,v18.16b ++ eor w15,w15,w5,ror#20 ++ add w4,w4,w11 ++ sli v17.4s,v1.4s,#13 ++ ldr w12,[sp,#28] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ ld1 {v4.4s},[x16], #16 ++ add w8,w8,w4 ++ eor v19.16b,v19.16b,v17.16b ++ eor w14,w14,w6 ++ eor v17.16b,v17.16b,v17.16b ++ add w3,w3,w12 ++ add w4,w4,w15 ++ and w12,w9,w8 ++ mov v17.d[1],v19.d[0] ++ bic w15,w10,w8 ++ eor w11,w8,w8,ror#5 ++ add w4,w4,w14 ++ add v1.4s,v1.4s,v17.4s ++ orr w12,w12,w15 ++ eor w11,w11,w8,ror#19 ++ eor w15,w4,w4,ror#11 ++ add v4.4s,v4.4s,v1.4s ++ add w3,w3,w12 ++ ror w11,w11,#6 ++ eor w14,w4,w5 ++ eor w15,w15,w4,ror#20 ++ add w3,w3,w11 ++ ldr w12,[sp,#32] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w7,w7,w3 ++ eor w13,w13,w5 ++ st1 {v4.4s},[x17], #16 ++ ext v4.16b,v2.16b,v3.16b,#4 ++ add w10,w10,w12 ++ add w3,w3,w15 ++ and w12,w8,w7 ++ bic w15,w9,w7 ++ ext v7.16b,v0.16b,v1.16b,#4 ++ eor w11,w7,w7,ror#5 ++ add w3,w3,w13 ++ mov d19,v1.d[1] ++ orr w12,w12,w15 ++ eor w11,w11,w7,ror#19 ++ ushr v6.4s,v4.4s,#7 ++ eor w15,w3,w3,ror#11 ++ ushr v5.4s,v4.4s,#3 ++ add w10,w10,w12 ++ add v2.4s,v2.4s,v7.4s ++ ror w11,w11,#6 ++ sli v6.4s,v4.4s,#25 ++ eor w13,w3,w4 ++ eor w15,w15,w3,ror#20 ++ ushr v7.4s,v4.4s,#18 ++ add w10,w10,w11 ++ ldr w12,[sp,#36] ++ and w14,w14,w13 ++ eor v5.16b,v5.16b,v6.16b ++ ror w15,w15,#2 ++ add w6,w6,w10 ++ sli v7.4s,v4.4s,#14 ++ eor w14,w14,w4 ++ ushr v16.4s,v19.4s,#17 ++ add w9,w9,w12 ++ add w10,w10,w15 ++ and w12,w7,w6 ++ eor v5.16b,v5.16b,v7.16b ++ bic w15,w8,w6 ++ eor w11,w6,w6,ror#5 ++ sli v16.4s,v19.4s,#15 ++ add w10,w10,w14 ++ orr w12,w12,w15 ++ ushr v17.4s,v19.4s,#10 ++ eor w11,w11,w6,ror#19 ++ eor w15,w10,w10,ror#11 ++ ushr v7.4s,v19.4s,#19 ++ add w9,w9,w12 ++ ror w11,w11,#6 ++ add v2.4s,v2.4s,v5.4s ++ eor w14,w10,w3 ++ eor w15,w15,w10,ror#20 ++ sli v7.4s,v19.4s,#13 ++ add w9,w9,w11 ++ ldr w12,[sp,#40] ++ and w13,w13,w14 ++ eor v17.16b,v17.16b,v16.16b ++ ror w15,w15,#2 ++ add w5,w5,w9 ++ eor w13,w13,w3 ++ eor v17.16b,v17.16b,v7.16b ++ add w8,w8,w12 ++ add w9,w9,w15 ++ and w12,w6,w5 ++ add v2.4s,v2.4s,v17.4s ++ bic w15,w7,w5 ++ eor w11,w5,w5,ror#5 ++ add w9,w9,w13 ++ ushr v18.4s,v2.4s,#17 ++ orr w12,w12,w15 ++ ushr v19.4s,v2.4s,#10 ++ eor w11,w11,w5,ror#19 ++ eor w15,w9,w9,ror#11 ++ sli v18.4s,v2.4s,#15 ++ add w8,w8,w12 ++ ushr v17.4s,v2.4s,#19 ++ ror w11,w11,#6 ++ eor w13,w9,w10 ++ eor v19.16b,v19.16b,v18.16b ++ eor w15,w15,w9,ror#20 ++ add w8,w8,w11 ++ sli v17.4s,v2.4s,#13 ++ ldr w12,[sp,#44] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ ld1 {v4.4s},[x16], #16 ++ add w4,w4,w8 ++ eor v19.16b,v19.16b,v17.16b ++ eor w14,w14,w10 ++ eor v17.16b,v17.16b,v17.16b ++ add w7,w7,w12 ++ add w8,w8,w15 ++ and w12,w5,w4 ++ mov v17.d[1],v19.d[0] ++ bic w15,w6,w4 ++ eor w11,w4,w4,ror#5 ++ add w8,w8,w14 ++ add v2.4s,v2.4s,v17.4s ++ orr w12,w12,w15 ++ eor w11,w11,w4,ror#19 ++ eor w15,w8,w8,ror#11 ++ add v4.4s,v4.4s,v2.4s ++ add w7,w7,w12 ++ ror w11,w11,#6 ++ eor w14,w8,w9 ++ eor w15,w15,w8,ror#20 ++ add w7,w7,w11 ++ ldr w12,[sp,#48] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w3,w3,w7 ++ eor w13,w13,w9 ++ st1 {v4.4s},[x17], #16 ++ ext v4.16b,v3.16b,v0.16b,#4 ++ add w6,w6,w12 ++ add w7,w7,w15 ++ and w12,w4,w3 ++ bic w15,w5,w3 ++ ext v7.16b,v1.16b,v2.16b,#4 ++ eor w11,w3,w3,ror#5 ++ add w7,w7,w13 ++ mov d19,v2.d[1] ++ orr w12,w12,w15 ++ eor w11,w11,w3,ror#19 ++ ushr v6.4s,v4.4s,#7 ++ eor w15,w7,w7,ror#11 ++ ushr v5.4s,v4.4s,#3 ++ add w6,w6,w12 ++ add v3.4s,v3.4s,v7.4s ++ ror w11,w11,#6 ++ sli v6.4s,v4.4s,#25 ++ eor w13,w7,w8 ++ eor w15,w15,w7,ror#20 ++ ushr v7.4s,v4.4s,#18 ++ add w6,w6,w11 ++ ldr w12,[sp,#52] ++ and w14,w14,w13 ++ eor v5.16b,v5.16b,v6.16b ++ ror w15,w15,#2 ++ add w10,w10,w6 ++ sli v7.4s,v4.4s,#14 ++ eor w14,w14,w8 ++ ushr v16.4s,v19.4s,#17 ++ add w5,w5,w12 ++ add w6,w6,w15 ++ and w12,w3,w10 ++ eor v5.16b,v5.16b,v7.16b ++ bic w15,w4,w10 ++ eor w11,w10,w10,ror#5 ++ sli v16.4s,v19.4s,#15 ++ add w6,w6,w14 ++ orr w12,w12,w15 ++ ushr v17.4s,v19.4s,#10 ++ eor w11,w11,w10,ror#19 ++ eor w15,w6,w6,ror#11 ++ ushr v7.4s,v19.4s,#19 ++ add w5,w5,w12 ++ ror w11,w11,#6 ++ add v3.4s,v3.4s,v5.4s ++ eor w14,w6,w7 ++ eor w15,w15,w6,ror#20 ++ sli v7.4s,v19.4s,#13 ++ add w5,w5,w11 ++ ldr w12,[sp,#56] ++ and w13,w13,w14 ++ eor v17.16b,v17.16b,v16.16b ++ ror w15,w15,#2 ++ add w9,w9,w5 ++ eor w13,w13,w7 ++ eor v17.16b,v17.16b,v7.16b ++ add w4,w4,w12 ++ add w5,w5,w15 ++ and w12,w10,w9 ++ add v3.4s,v3.4s,v17.4s ++ bic w15,w3,w9 ++ eor w11,w9,w9,ror#5 ++ add w5,w5,w13 ++ ushr v18.4s,v3.4s,#17 ++ orr w12,w12,w15 ++ ushr v19.4s,v3.4s,#10 ++ eor w11,w11,w9,ror#19 ++ eor w15,w5,w5,ror#11 ++ sli v18.4s,v3.4s,#15 ++ add w4,w4,w12 ++ ushr v17.4s,v3.4s,#19 ++ ror w11,w11,#6 ++ eor w13,w5,w6 ++ eor v19.16b,v19.16b,v18.16b ++ eor w15,w15,w5,ror#20 ++ add w4,w4,w11 ++ sli v17.4s,v3.4s,#13 ++ ldr w12,[sp,#60] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ ld1 {v4.4s},[x16], #16 ++ add w8,w8,w4 ++ eor v19.16b,v19.16b,v17.16b ++ eor w14,w14,w6 ++ eor v17.16b,v17.16b,v17.16b ++ add w3,w3,w12 ++ add w4,w4,w15 ++ and w12,w9,w8 ++ mov v17.d[1],v19.d[0] ++ bic w15,w10,w8 ++ eor w11,w8,w8,ror#5 ++ add w4,w4,w14 ++ add v3.4s,v3.4s,v17.4s ++ orr w12,w12,w15 ++ eor w11,w11,w8,ror#19 ++ eor w15,w4,w4,ror#11 ++ add v4.4s,v4.4s,v3.4s ++ add w3,w3,w12 ++ ror w11,w11,#6 ++ eor w14,w4,w5 ++ eor w15,w15,w4,ror#20 ++ add w3,w3,w11 ++ ldr w12,[x16] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w7,w7,w3 ++ eor w13,w13,w5 ++ st1 {v4.4s},[x17], #16 ++ cmp w12,#0 // check for K256 terminator ++ ldr w12,[sp,#0] ++ sub x17,x17,#64 ++ bne .L_00_48 ++ ++ sub x16,x16,#256 // rewind x16 ++ cmp x1,x2 ++ mov x17, #64 ++ csel x17, x17, xzr, eq ++ sub x1,x1,x17 // avoid SEGV ++ mov x17,sp ++ add w10,w10,w12 ++ add w3,w3,w15 ++ and w12,w8,w7 ++ ld1 {v0.16b},[x1],#16 ++ bic w15,w9,w7 ++ eor w11,w7,w7,ror#5 ++ ld1 {v4.4s},[x16],#16 ++ add w3,w3,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w7,ror#19 ++ eor w15,w3,w3,ror#11 ++ rev32 v0.16b,v0.16b ++ add w10,w10,w12 ++ ror w11,w11,#6 ++ eor w13,w3,w4 ++ eor w15,w15,w3,ror#20 ++ add v4.4s,v4.4s,v0.4s ++ add w10,w10,w11 ++ ldr w12,[sp,#4] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w6,w6,w10 ++ eor w14,w14,w4 ++ add w9,w9,w12 ++ add w10,w10,w15 ++ and w12,w7,w6 ++ bic w15,w8,w6 ++ eor w11,w6,w6,ror#5 ++ add w10,w10,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w6,ror#19 ++ eor w15,w10,w10,ror#11 ++ add w9,w9,w12 ++ ror w11,w11,#6 ++ eor w14,w10,w3 ++ eor w15,w15,w10,ror#20 ++ add w9,w9,w11 ++ ldr w12,[sp,#8] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w5,w5,w9 ++ eor w13,w13,w3 ++ add w8,w8,w12 ++ add w9,w9,w15 ++ and w12,w6,w5 ++ bic w15,w7,w5 ++ eor w11,w5,w5,ror#5 ++ add w9,w9,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w5,ror#19 ++ eor w15,w9,w9,ror#11 ++ add w8,w8,w12 ++ ror w11,w11,#6 ++ eor w13,w9,w10 ++ eor w15,w15,w9,ror#20 ++ add w8,w8,w11 ++ ldr w12,[sp,#12] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w4,w4,w8 ++ eor w14,w14,w10 ++ add w7,w7,w12 ++ add w8,w8,w15 ++ and w12,w5,w4 ++ bic w15,w6,w4 ++ eor w11,w4,w4,ror#5 ++ add w8,w8,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w4,ror#19 ++ eor w15,w8,w8,ror#11 ++ add w7,w7,w12 ++ ror w11,w11,#6 ++ eor w14,w8,w9 ++ eor w15,w15,w8,ror#20 ++ add w7,w7,w11 ++ ldr w12,[sp,#16] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w3,w3,w7 ++ eor w13,w13,w9 ++ st1 {v4.4s},[x17], #16 ++ add w6,w6,w12 ++ add w7,w7,w15 ++ and w12,w4,w3 ++ ld1 {v1.16b},[x1],#16 ++ bic w15,w5,w3 ++ eor w11,w3,w3,ror#5 ++ ld1 {v4.4s},[x16],#16 ++ add w7,w7,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w3,ror#19 ++ eor w15,w7,w7,ror#11 ++ rev32 v1.16b,v1.16b ++ add w6,w6,w12 ++ ror w11,w11,#6 ++ eor w13,w7,w8 ++ eor w15,w15,w7,ror#20 ++ add v4.4s,v4.4s,v1.4s ++ add w6,w6,w11 ++ ldr w12,[sp,#20] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w10,w10,w6 ++ eor w14,w14,w8 ++ add w5,w5,w12 ++ add w6,w6,w15 ++ and w12,w3,w10 ++ bic w15,w4,w10 ++ eor w11,w10,w10,ror#5 ++ add w6,w6,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w10,ror#19 ++ eor w15,w6,w6,ror#11 ++ add w5,w5,w12 ++ ror w11,w11,#6 ++ eor w14,w6,w7 ++ eor w15,w15,w6,ror#20 ++ add w5,w5,w11 ++ ldr w12,[sp,#24] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w9,w9,w5 ++ eor w13,w13,w7 ++ add w4,w4,w12 ++ add w5,w5,w15 ++ and w12,w10,w9 ++ bic w15,w3,w9 ++ eor w11,w9,w9,ror#5 ++ add w5,w5,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w9,ror#19 ++ eor w15,w5,w5,ror#11 ++ add w4,w4,w12 ++ ror w11,w11,#6 ++ eor w13,w5,w6 ++ eor w15,w15,w5,ror#20 ++ add w4,w4,w11 ++ ldr w12,[sp,#28] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w8,w8,w4 ++ eor w14,w14,w6 ++ add w3,w3,w12 ++ add w4,w4,w15 ++ and w12,w9,w8 ++ bic w15,w10,w8 ++ eor w11,w8,w8,ror#5 ++ add w4,w4,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w8,ror#19 ++ eor w15,w4,w4,ror#11 ++ add w3,w3,w12 ++ ror w11,w11,#6 ++ eor w14,w4,w5 ++ eor w15,w15,w4,ror#20 ++ add w3,w3,w11 ++ ldr w12,[sp,#32] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w7,w7,w3 ++ eor w13,w13,w5 ++ st1 {v4.4s},[x17], #16 ++ add w10,w10,w12 ++ add w3,w3,w15 ++ and w12,w8,w7 ++ ld1 {v2.16b},[x1],#16 ++ bic w15,w9,w7 ++ eor w11,w7,w7,ror#5 ++ ld1 {v4.4s},[x16],#16 ++ add w3,w3,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w7,ror#19 ++ eor w15,w3,w3,ror#11 ++ rev32 v2.16b,v2.16b ++ add w10,w10,w12 ++ ror w11,w11,#6 ++ eor w13,w3,w4 ++ eor w15,w15,w3,ror#20 ++ add v4.4s,v4.4s,v2.4s ++ add w10,w10,w11 ++ ldr w12,[sp,#36] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w6,w6,w10 ++ eor w14,w14,w4 ++ add w9,w9,w12 ++ add w10,w10,w15 ++ and w12,w7,w6 ++ bic w15,w8,w6 ++ eor w11,w6,w6,ror#5 ++ add w10,w10,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w6,ror#19 ++ eor w15,w10,w10,ror#11 ++ add w9,w9,w12 ++ ror w11,w11,#6 ++ eor w14,w10,w3 ++ eor w15,w15,w10,ror#20 ++ add w9,w9,w11 ++ ldr w12,[sp,#40] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w5,w5,w9 ++ eor w13,w13,w3 ++ add w8,w8,w12 ++ add w9,w9,w15 ++ and w12,w6,w5 ++ bic w15,w7,w5 ++ eor w11,w5,w5,ror#5 ++ add w9,w9,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w5,ror#19 ++ eor w15,w9,w9,ror#11 ++ add w8,w8,w12 ++ ror w11,w11,#6 ++ eor w13,w9,w10 ++ eor w15,w15,w9,ror#20 ++ add w8,w8,w11 ++ ldr w12,[sp,#44] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w4,w4,w8 ++ eor w14,w14,w10 ++ add w7,w7,w12 ++ add w8,w8,w15 ++ and w12,w5,w4 ++ bic w15,w6,w4 ++ eor w11,w4,w4,ror#5 ++ add w8,w8,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w4,ror#19 ++ eor w15,w8,w8,ror#11 ++ add w7,w7,w12 ++ ror w11,w11,#6 ++ eor w14,w8,w9 ++ eor w15,w15,w8,ror#20 ++ add w7,w7,w11 ++ ldr w12,[sp,#48] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w3,w3,w7 ++ eor w13,w13,w9 ++ st1 {v4.4s},[x17], #16 ++ add w6,w6,w12 ++ add w7,w7,w15 ++ and w12,w4,w3 ++ ld1 {v3.16b},[x1],#16 ++ bic w15,w5,w3 ++ eor w11,w3,w3,ror#5 ++ ld1 {v4.4s},[x16],#16 ++ add w7,w7,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w3,ror#19 ++ eor w15,w7,w7,ror#11 ++ rev32 v3.16b,v3.16b ++ add w6,w6,w12 ++ ror w11,w11,#6 ++ eor w13,w7,w8 ++ eor w15,w15,w7,ror#20 ++ add v4.4s,v4.4s,v3.4s ++ add w6,w6,w11 ++ ldr w12,[sp,#52] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w10,w10,w6 ++ eor w14,w14,w8 ++ add w5,w5,w12 ++ add w6,w6,w15 ++ and w12,w3,w10 ++ bic w15,w4,w10 ++ eor w11,w10,w10,ror#5 ++ add w6,w6,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w10,ror#19 ++ eor w15,w6,w6,ror#11 ++ add w5,w5,w12 ++ ror w11,w11,#6 ++ eor w14,w6,w7 ++ eor w15,w15,w6,ror#20 ++ add w5,w5,w11 ++ ldr w12,[sp,#56] ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w9,w9,w5 ++ eor w13,w13,w7 ++ add w4,w4,w12 ++ add w5,w5,w15 ++ and w12,w10,w9 ++ bic w15,w3,w9 ++ eor w11,w9,w9,ror#5 ++ add w5,w5,w13 ++ orr w12,w12,w15 ++ eor w11,w11,w9,ror#19 ++ eor w15,w5,w5,ror#11 ++ add w4,w4,w12 ++ ror w11,w11,#6 ++ eor w13,w5,w6 ++ eor w15,w15,w5,ror#20 ++ add w4,w4,w11 ++ ldr w12,[sp,#60] ++ and w14,w14,w13 ++ ror w15,w15,#2 ++ add w8,w8,w4 ++ eor w14,w14,w6 ++ add w3,w3,w12 ++ add w4,w4,w15 ++ and w12,w9,w8 ++ bic w15,w10,w8 ++ eor w11,w8,w8,ror#5 ++ add w4,w4,w14 ++ orr w12,w12,w15 ++ eor w11,w11,w8,ror#19 ++ eor w15,w4,w4,ror#11 ++ add w3,w3,w12 ++ ror w11,w11,#6 ++ eor w14,w4,w5 ++ eor w15,w15,w4,ror#20 ++ add w3,w3,w11 ++ and w13,w13,w14 ++ ror w15,w15,#2 ++ add w7,w7,w3 ++ eor w13,w13,w5 ++ st1 {v4.4s},[x17], #16 ++ add w3,w3,w15 // h+=Sigma0(a) from the past ++ ldp w11,w12,[x0,#0] ++ add w3,w3,w13 // h+=Maj(a,b,c) from the past ++ ldp w13,w14,[x0,#8] ++ add w3,w3,w11 // accumulate ++ add w4,w4,w12 ++ ldp w11,w12,[x0,#16] ++ add w5,w5,w13 ++ add w6,w6,w14 ++ ldp w13,w14,[x0,#24] ++ add w7,w7,w11 ++ add w8,w8,w12 ++ ldr w12,[sp,#0] ++ stp w3,w4,[x0,#0] ++ add w9,w9,w13 ++ mov w13,wzr ++ stp w5,w6,[x0,#8] ++ add w10,w10,w14 ++ stp w7,w8,[x0,#16] ++ eor w14,w4,w5 ++ stp w9,w10,[x0,#24] ++ mov w15,wzr ++ mov x17,sp ++ b.ne .L_00_48 ++ ++ ldr x29,[x29] ++ add sp,sp,#16*4+16 ++ ret ++.size sha256_block_neon,.-sha256_block_neon ++#ifndef __KERNEL__ ++.comm OPENSSL_armcap_P,4,4 ++#endif +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/defconfig b/defconfig +--- a/defconfig 1970-01-01 08:00:00.000000000 +0800 ++++ b/defconfig 2018-05-10 15:33:01.717312107 +0800 +@@ -0,0 +1,216 @@ ++CONFIG_CROSS_COMPILE="$CROSS_COMPILE" ++CONFIG_SYSVIPC=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=13 ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="${BR_BINARIES_DIR}/rootfs.cpio" ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_BASE_FULL is not set ++# CONFIG_EPOLL is not set ++# CONFIG_SIGNALFD is not set ++# CONFIG_TIMERFD is not set ++# CONFIG_EVENTFD is not set ++# CONFIG_SHMEM is not set ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_ARCH_XGS_IPROC=y ++CONFIG_PCI=y ++CONFIG_NR_CPUS=4 ++CONFIG_PREEMPT=y ++CONFIG_HZ_100=y ++# CONFIG_COMPACTION is not set ++CONFIG_CMA=y ++CONFIG_CMA_DEBUG=y ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=496M" ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++CONFIG_IPV6_TUNNEL=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=y ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_TARGET_CT=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_RPFILTER=y ++CONFIG_IP6_NF_MATCH_RT=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_MTD=y ++CONFIG_MTD_TESTS=m ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_M25P80=y ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_BRCMNAND=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_UBI=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++CONFIG_CHR_DEV_SG=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=y ++CONFIG_TIGON3=y ++# CONFIG_BGMAC_PLATFORM is not set ++CONFIG_APM=y ++CONFIG_MDIO_XGS_IPROC=y ++CONFIG_BROADCOM_PHY=y ++CONFIG_XGS_IPROC_SERDES=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_XGS_IPROC_RNG=y ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_SPI=y ++CONFIG_SPI_PL022=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_WATCHDOG=y ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_XGS_IPROC_DRD=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_BDC_UDC=y ++CONFIG_USB_BDC_XGS_IPROC=y ++CONFIG_USB_G_SERIAL=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++CONFIG_PL330_DMA=y ++# CONFIG_COMMON_CLK_XGENE is not set ++CONFIG_ACPI=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++# CONFIG_DNOTIFY is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=y ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_JFFS2_FS=y ++CONFIG_UBIFS_FS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFSD=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_DEBUG_FS=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM64_CE=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig +--- a/drivers/char/hw_random/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/char/hw_random/Kconfig 2018-05-10 11:31:29.825399854 +0800 +@@ -112,6 +112,18 @@ config HW_RANDOM_IPROC_RNG200 + + If unsure, say Y. + ++config HW_RANDOM_XGS_IPROC_RNG ++ tristate "Broadcom iProc RNG support" ++ depends on (ARCH_XGS_IPROC && HW_RANDOM) ++ ---help--- ++ This driver provides kernel-side support for the RNG ++ hardware found on the Broadcom iProc SoCs. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called iproc-rng ++ ++ If unsure, say Y. ++ + config HW_RANDOM_GEODE + tristate "AMD Geode HW Random Number Generator support" + depends on X86_32 && PCI +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile +--- a/drivers/char/hw_random/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/char/hw_random/Makefile 2018-05-10 11:31:29.825399854 +0800 +@@ -30,6 +30,7 @@ obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng + obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o + obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o + obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o ++obj-$(CONFIG_HW_RANDOM_XGS_IPROC_RNG) += xgs-iproc-rng100.o iproc-rng200.o + obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o + obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o + obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/xgs-iproc-rng100.c b/drivers/char/hw_random/xgs-iproc-rng100.c +--- a/drivers/char/hw_random/xgs-iproc-rng100.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/char/hw_random/xgs-iproc-rng100.c 2018-05-10 11:31:29.829399858 +0800 +@@ -0,0 +1,211 @@ ++/* ++ * Copyright (C) 2017 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++/* Registers for RNG */ ++#define RNG_CTRL_OFFSET 0x00000000 ++#define RNG_CTRL_RESERVED_MASK 0xF00000CC ++#define RNG_CTRL_COMBLK2_OSC_DIS_SHIFT 22 ++#define RNG_CTRL_COMBLK2_OSC_DIS_MASK 0x0FC00000 ++#define RNG_CTRL_COMBLK1_OSC_DIS_SHIFT 16 ++#define RNG_CTRL_COMBLK1_OSC_DIS_MASK 0x003F0000 ++#define RNG_CTRL_JCLK_BYP_DIV_CNT_SHIFT 8 ++#define RNG_CTRL_JCLK_BYP_DIV_CNT_MASK 0x0000FF00 ++#define RNG_CTRL_JCLK_BYP_SRC_SHIFT 5 ++#define RNG_CTRL_JCLK_BYP_SRC_MASK 0x00000020 ++#define RNG_CTRL_JCLK_BYP_SEL_SHIFT 4 ++#define RNG_CTRL_JCLK_BYP_SEL_MASK 0x00000010 ++#define RNG_CTRL_RBG2X_SHIFT 1 ++#define RNG_CTRL_RBG2X_MASK 0x00000002 ++#define RNG_CTRL_RBGEN_SHIFT 0 ++#define RNG_CTRL_RBGEN_MASK 0x00000001 ++ ++#define RNG_STATUS_OFFSET 0x00000004 ++#define RNG_STATUS_RESERVED_MASK 0x00F00000 ++#define RNG_STATUS_RND_VAL_SHIFT 24 ++#define RNG_STATUS_RND_VAL_MASK 0xFF000000 ++#define RNG_STATUS_WARM_CNT_SHIFT 0 ++#define RNG_STATUS_WARM_CNT_MASK 0x000FFFFF ++ ++#define RNG_DATA_OFFSET 0x00000008 ++#define RNG_DATA_RESERVED_MASK 0x00000000 ++#define RNG_DATA_RNG_NUM_SHIFT 0 ++#define RNG_DATA_RNG_NUM_MASK 0xFFFFFFFF ++ ++#define RNG_FF_THRES_OFFSET 0x0000000C ++#define RNG_FF_THRES_RESERVED_MASK 0xFFFFFFE0 ++#define RNG_FF_THRES_RNG_FF_THRESH_SHIFT 0 ++#define RNG_FF_THRES_RNG_FF_THRESH_MASK 0x0000001F ++ ++#define RNG_INT_MASK_OFFSET 0x00000010 ++#define RNG_INT_MASK_RESERVED_MASK 0xFFFFFFFE ++#define RNG_INT_MASK_OFF_SHIFT 0 ++#define RNG_INT_MASK_OFF_MASK 0x00000001 ++ ++static int rng100_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ u32 num_words = 0; ++ u32 num_remaining = max; ++ ++ #define MAX_IDLE_TIME (1 * HZ) ++ unsigned long idle_endtime = jiffies + MAX_IDLE_TIME; ++ ++ /* Retrieve HW RNG registers base address. */ ++ void __iomem *base_addr = (void __iomem *)rng->priv; ++ ++ while ((num_remaining > 0) && time_before(jiffies, idle_endtime)) { ++ /* Are there any random numbers available? */ ++ num_words = (ioread32(base_addr + RNG_STATUS_OFFSET) & ++ RNG_STATUS_RND_VAL_MASK) >> RNG_STATUS_RND_VAL_SHIFT; ++ if (num_words > 0) { ++ if (num_remaining >= sizeof(u32)) { ++ /* Buffer has room to store entire word */ ++ *(u32 *)buf = ioread32(base_addr + ++ RNG_DATA_OFFSET); ++ buf += sizeof(u32); ++ num_remaining -= sizeof(u32); ++ } else { ++ /* Buffer can only store partial word */ ++ u32 rnd_number = ioread32(base_addr + ++ RNG_DATA_OFFSET); ++ memcpy(buf, &rnd_number, num_remaining); ++ buf += num_remaining; ++ num_remaining = 0; ++ } ++ ++ /* Reset the IDLE timeout */ ++ idle_endtime = jiffies + MAX_IDLE_TIME; ++ } else if (!wait) { ++ /* Cannot wait, return immediately */ ++ break; ++ } else { ++ /* Can wait, give others chance to run */ ++ cpu_relax(); ++ } ++ } ++ ++ return max - num_remaining; ++} ++ ++static struct hwrng rng100_ops = { ++ .name = "iproc-rng100", ++ .read = rng100_read, ++}; ++ ++static int iproc_rng100_probe(struct platform_device *pdev) ++{ ++ int error; ++ u32 val; ++ struct device *dev = &pdev->dev; ++ void __iomem *base_addr; ++ struct device_node *node = pdev->dev.of_node; ++ ++ pr_info("Broadcom IPROC RNG100 Driver\n"); ++ /* We only accept one device, and it must have an id of -1 */ ++ if (pdev->id != -1) ++ return -ENODEV; ++ ++ base_addr = of_iomap(node, 0); ++ if (!base_addr) { ++ dev_err(&pdev->dev, "can't iomap base_addr for rng100\n"); ++ return -EIO; ++ } ++ rng100_ops.priv = (unsigned long)base_addr; ++ ++ /* Start RNG block */ ++ val = ioread32(base_addr + RNG_CTRL_OFFSET); ++ val |= RNG_CTRL_RBGEN_MASK; ++ iowrite32(val, base_addr + RNG_CTRL_OFFSET); ++ ++ /* Enable RNG RBG2X */ ++ val = ioread32(base_addr + RNG_CTRL_OFFSET); ++ val |= RNG_CTRL_RBG2X_MASK; ++ iowrite32(val, base_addr + RNG_CTRL_OFFSET); ++ ++ /* Disable RNG INTERRUPT */ ++ val = ioread32(base_addr + RNG_INT_MASK_OFFSET); ++ val |= RNG_INT_MASK_OFF_MASK; ++ iowrite32(val, base_addr + RNG_INT_MASK_OFFSET); ++ ++ /* set warmup cycle 0xfff */ ++ iowrite32(RNG_STATUS_WARM_CNT_MASK - ++ (0xfff & RNG_STATUS_WARM_CNT_MASK), ++ base_addr + RNG_STATUS_OFFSET); ++ while ((ioread32(base_addr + RNG_STATUS_OFFSET) & ++ RNG_STATUS_WARM_CNT_MASK) != RNG_STATUS_WARM_CNT_MASK) ++ cpu_relax(); ++ ++ /* register to the Linux RNG framework */ ++ error = hwrng_register(&rng100_ops); ++ if (error) { ++ dev_err(dev, "hwrng registration failed\n"); ++ iounmap(base_addr); ++ return error; ++ } ++ dev_dbg(dev, "hwrng registered\n"); ++ ++ return 0; ++} ++ ++static int iproc_rng100_remove(struct platform_device *pdev) ++{ ++ u32 val; ++ void __iomem *base_addr = (void __iomem *)rng100_ops.priv; ++ ++ hwrng_unregister(&rng100_ops); ++ ++ if (base_addr) { ++ /* Disable RNG hardware */ ++ val = ioread32(base_addr + RNG_CTRL_OFFSET); ++ val &= ~RNG_CTRL_RBGEN_MASK; ++ iowrite32(val, base_addr + RNG_CTRL_OFFSET); ++ ++ val = ioread32(base_addr + RNG_CTRL_OFFSET); ++ val &= ~RNG_CTRL_RBG2X_MASK; ++ iowrite32(val, base_addr + RNG_CTRL_OFFSET); ++ ++ iounmap(base_addr); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm_iproc_dt_ids[] = { ++ { .compatible = "brcm,iproc-rng100"}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_dt_ids); ++ ++static struct platform_driver iproc_rng100_driver = { ++ .driver = { ++ .name = "iproc-rng100", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_iproc_dt_ids, ++ }, ++ .probe = iproc_rng100_probe, ++ .remove = iproc_rng100_remove, ++}; ++module_platform_driver(iproc_rng100_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("iProc RNG100 Random Number Generator driver"); ++MODULE_LICENSE("GPL v2"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig +--- a/drivers/clk/bcm/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/clk/bcm/Kconfig 2018-05-10 11:31:29.849399879 +0800 +@@ -54,3 +54,11 @@ config CLK_BCM_SR + default ARCH_BCM_IPROC + help + Enable common clock framework support for the Broadcom Stingray SoC ++ ++config CLK_XGS_IPROC ++ bool "BRCM XGS iProc clock support" ++ depends on ARCH_XGS_IPROC || COMPILE_TEST ++ select COMMON_CLK_IPROC ++ default ARCH_XGS_IPROC ++ help ++ Enable clock support for Broadcom XGS iProc SoC +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile +--- a/drivers/clk/bcm/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/clk/bcm/Makefile 2018-05-10 11:31:29.849399879 +0800 +@@ -12,3 +12,4 @@ obj-$(CONFIG_CLK_BCM_CYGNUS) += clk-cygn + obj-$(CONFIG_CLK_BCM_NSP) += clk-nsp.o + obj-$(CONFIG_CLK_BCM_NS2) += clk-ns2.o + obj-$(CONFIG_CLK_BCM_SR) += clk-sr.o ++obj-$(CONFIG_CLK_XGS_IPROC) += clk-xgs-iproc.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/clk-iproc-armpll.c b/drivers/clk/bcm/clk-iproc-armpll.c +--- a/drivers/clk/bcm/clk-iproc-armpll.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/clk/bcm/clk-iproc-armpll.c 2018-05-10 11:31:29.853399884 +0800 +@@ -197,9 +197,9 @@ static unsigned long iproc_arm_pll_recal + { + struct iproc_arm_pll *pll = to_iproc_arm_pll(hw); + u32 val; +- int mdiv; ++ u32 mdiv; + u64 ndiv; +- unsigned int pdiv; ++ u32 pdiv; + + /* in bypass mode, use parent rate */ + val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET); +@@ -226,8 +226,10 @@ static unsigned long iproc_arm_pll_recal + pll->rate = 0; + return 0; + } ++ ++ /* To avoid pll->rate overflow, do divide before multiply */ ++ parent_rate = (parent_rate / pdiv) / mdiv; + pll->rate = (ndiv * parent_rate) >> 20; +- pll->rate = (pll->rate / pdiv) / mdiv; + + pr_debug("%s: ARM PLL rate: %lu. parent rate: %lu\n", __func__, + pll->rate, parent_rate); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/clk-xgs-iproc.c b/drivers/clk/bcm/clk-xgs-iproc.c +--- a/drivers/clk/bcm/clk-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/clk/bcm/clk-xgs-iproc.c 2018-05-10 11:31:29.853399884 +0800 +@@ -0,0 +1,168 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 "clk-iproc.h" ++ ++#define SB2_GEN_PLL_CTRL_1_OFFSET 0x04 ++#define SB2_GEN_PLL_CTRL_3_OFFSET 0x0C ++#define SB2_GEN_PLL_CTRL_5_OFFSET 0x14 ++#define SB2_GEN_PLL_CTRL_1_PDIV_R 27 ++#define SB2_GEN_PLL_CTRL_3_NDIV_INT_R 20 ++#define SB2_GEN_PLL_CTRL_5_CH1_MDIV_R 8 ++#define SB2_GEN_PLL_CTRL_1_PDIV_WIDTH 4 ++#define SB2_GEN_PLL_CTRL_3_NDIV_INT_WIDTH 10 ++#define SB2_GEN_PLL_CTRL_5_CH1_MDIV_WIDTH 8 ++ ++#define GEN_PLL_CTRL1_OFFSET 0x4 ++#define GEN_PLL_CTRL2_OFFSET 0x8 ++#define GEN_PLL_CTRL1_NDIV_INT_R 0 ++#define GEN_PLL_CTRL1_NDIV_INT_WIDTH 10 ++#define GEN_PLL_CTRL1_PDIV_R 10 ++#define GEN_PLL_CTRL2_CH3_MDIV_R 8 ++#define GEN_PLL_CTRL2_CH3_MDIV_WIDTH 8 ++#define GEN_PLL_CTRL1_PDIV_WIDTH_3 3 ++#define GEN_PLL_CTRL1_PDIV_WIDTH_4 4 ++ ++ ++struct iproc_gen_pll { ++ struct clk_hw hw; ++ void __iomem *base; ++ unsigned long rate; ++}; ++ ++#define to_iproc_gen_pll(phw) container_of(phw, struct iproc_gen_pll, hw) ++ ++static u32 genpll_pdiv_width; ++ ++static unsigned long iproc_axi_clk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ uint32_t ndiv, mdiv, pdiv; ++ struct iproc_gen_pll *pll = to_iproc_gen_pll(hw); ++ ++ ndiv = readl(pll->base + GEN_PLL_CTRL1_OFFSET) >> ++ GEN_PLL_CTRL1_NDIV_INT_R; ++ ndiv &= (1 << GEN_PLL_CTRL1_NDIV_INT_WIDTH) - 1; ++ if (ndiv == 0) ++ ndiv = 1 << GEN_PLL_CTRL1_NDIV_INT_WIDTH; ++ ++ pdiv = readl(pll->base + GEN_PLL_CTRL1_OFFSET) >> GEN_PLL_CTRL1_PDIV_R; ++ pdiv &= (1 << genpll_pdiv_width) -1; ++ if (pdiv == 0) ++ pdiv = 1 << genpll_pdiv_width; ++ ++ mdiv = readl(pll->base + GEN_PLL_CTRL2_OFFSET) >> ++ GEN_PLL_CTRL2_CH3_MDIV_R; ++ mdiv &= (1 << GEN_PLL_CTRL2_CH3_MDIV_WIDTH) - 1; ++ if (mdiv == 0) ++ mdiv = 1 << GEN_PLL_CTRL2_CH3_MDIV_WIDTH; ++ ++ pll->rate = parent_rate * ndiv / pdiv / mdiv; ++ return pll->rate; ++} ++ ++static unsigned long iproc_sb2_axi_clk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ uint32_t ndiv, mdiv, pdiv; ++ struct iproc_gen_pll *pll = to_iproc_gen_pll(hw); ++ ++ ndiv = readl(pll->base + SB2_GEN_PLL_CTRL_3_OFFSET) >> ++ SB2_GEN_PLL_CTRL_3_NDIV_INT_R; ++ ndiv &= (1 << SB2_GEN_PLL_CTRL_3_NDIV_INT_WIDTH) - 1; ++ ++ mdiv = readl(pll->base + SB2_GEN_PLL_CTRL_5_OFFSET) >> ++ SB2_GEN_PLL_CTRL_5_CH1_MDIV_R; ++ mdiv &= (1 << SB2_GEN_PLL_CTRL_5_CH1_MDIV_WIDTH) - 1; ++ ++ pdiv = readl(pll->base + SB2_GEN_PLL_CTRL_1_OFFSET) >> ++ SB2_GEN_PLL_CTRL_1_PDIV_R; ++ pdiv &= (1 << SB2_GEN_PLL_CTRL_1_PDIV_WIDTH) - 1; ++ ++ pll->rate = parent_rate * ndiv / pdiv / mdiv; ++ return pll->rate; ++} ++ ++ ++static struct clk_ops iproc_axi_clk_ops = { ++ .recalc_rate = iproc_axi_clk_recalc_rate, ++}; ++ ++void __init xgs_iproc_axi_clk_setup(struct device_node *node) ++{ ++ int ret; ++ struct clk *clk; ++ struct iproc_gen_pll *pll; ++ struct clk_init_data init; ++ const char *parent_name; ++ ++ pll = kzalloc(sizeof(*pll), GFP_KERNEL); ++ if (WARN_ON(!pll)) ++ return; ++ ++ pll->base = of_iomap(node, 0); ++ if (WARN_ON(!pll->base)) ++ goto err_free_pll; ++ ++ init.name = node->name; ++ if (of_device_is_compatible(node, "axi-clk-sb2")) ++ iproc_axi_clk_ops.recalc_rate = iproc_sb2_axi_clk_recalc_rate; ++ if (of_device_is_compatible(node, "axi-clk-hx4") || ++ of_device_is_compatible(node, "axi-clk-hr2")) ++ genpll_pdiv_width = GEN_PLL_CTRL1_PDIV_WIDTH_3; ++ else ++ genpll_pdiv_width = GEN_PLL_CTRL1_PDIV_WIDTH_4; ++ ++ init.ops = &iproc_axi_clk_ops; ++ init.flags = 0; ++ parent_name = of_clk_get_parent_name(node, 0); ++ init.parent_names = (parent_name ? &parent_name : NULL); ++ init.num_parents = (parent_name ? 1 : 0); ++ pll->hw.init = &init; ++ ++ clk = clk_register(NULL, &pll->hw); ++ if (WARN_ON(IS_ERR(clk))) ++ goto err_iounmap; ++ ++ ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ if (WARN_ON(ret)) ++ goto err_clk_unregister; ++ ++ return; ++ ++err_clk_unregister: ++ clk_unregister(clk); ++err_iounmap: ++ iounmap(pll->base); ++err_free_pll: ++ kfree(pll); ++} ++CLK_OF_DECLARE(xgs_iproc_axi_clk, "brcm,xgs-iproc-axi-clk", ++ xgs_iproc_axi_clk_setup); ++ ++ ++static void __init xgs_iproc_armpll_init(struct device_node *node) ++{ ++ iproc_armpll_setup(node); ++} ++CLK_OF_DECLARE(xgs_iproc_armpll, "brcm,xgs-iproc-armpll", ++ xgs_iproc_armpll_init); +\ No newline at end of file +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +--- a/drivers/gpio/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/gpio/Kconfig 2018-05-10 11:31:30.057400102 +0800 +@@ -143,6 +143,15 @@ config GPIO_BRCMSTB + help + Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. + ++config GPIO_XGS_IPROC ++ tristate "BRCM XGS iProc GPIO support" ++ default y if ARCH_XGS_IPROC ++ depends on OF_GPIO && (ARCH_XGS_IPROC || COMPILE_TEST) ++ select GPIO_GENERIC ++ select GPIOLIB_IRQCHIP ++ help ++ Say yes here to enable GPIO support for Broadcom XGS iProc SoCs. ++ + config GPIO_CLPS711X + tristate "CLPS711X GPIO support" + depends on ARCH_CLPS711X || COMPILE_TEST +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/gpio/Makefile b/drivers/gpio/Makefile +--- a/drivers/gpio/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/gpio/Makefile 2018-05-10 11:31:30.057400102 +0800 +@@ -36,6 +36,7 @@ obj-$(CONFIG_GPIO_AXP209) += gpio-axp209 + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o + obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o ++obj-$(CONFIG_GPIO_XGS_IPROC) += gpio-xgs-iproc.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o + obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c +--- a/drivers/gpio/gpio-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/gpio/gpio-xgs-iproc.c 2018-05-10 11:31:30.069400115 +0800 +@@ -0,0 +1,739 @@ ++/* ++ * Copyright (C) 2017 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++ ++#define IPROC_GPIO_CCA_ID 0 ++#define IPROC_GPIO_CCB_ID 1 ++#define IPROC_GPIO_CCG_ID 2 ++ ++#define REGOFFSET_GPIO_DIN 0x0 ++#define REGOFFSET_GPIO_DOUT 0x4 ++#define REGOFFSET_GPIO_OUT_EN 0x8 ++ ++#define CCA_INT_F_GPIOINT 1 ++#define CCA_INT_STS 0x20 ++#define CCA_INT_MASK 0x24 ++#define GPIO_CCA_DIN 0x0 ++#define GPIO_CCA_INT_LEVEL 0x10 ++#define GPIO_CCA_INT_LEVEL_MASK 0x14 ++#define GPIO_CCA_INT_EVENT 0x18 ++#define GPIO_CCA_INT_EVENT_MASK 0x1C ++#define GPIO_CCA_INT_EDGE 0x24 ++ ++#define GPIO_CCB_INT_TYPE 0xC ++#define GPIO_CCB_INT_DE 0x10 ++#define GPIO_CCB_INT_EDGE 0x14 ++#define GPIO_CCB_INT_MSTAT 0x20 ++#define GPIO_CCB_INT_CLR 0x24 ++#define GPIO_CCB_INT_MASK 0x18 ++ ++/* locking wrappers to deal with multiple access to the same gpio bank */ ++#define iproc_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) ++#define iproc_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) ++ ++struct iproc_gpio_irqcfg { ++ unsigned long flags; ++ irqreturn_t (*handler)(int irq, void *dev); ++ void (*ack)(unsigned int irq); ++ void (*unmask)(unsigned int irq); ++ void (*mask)(unsigned int irq); ++ int (*set_type)(unsigned int irq, unsigned int type); ++}; ++ ++struct iproc_gpio_chip { ++ int id; ++ struct gpio_chip chip; ++ struct iproc_gpio_cfg *config; ++ void __iomem *ioaddr; ++ void __iomem *intr_ioaddr; ++ spinlock_t lock; ++ struct irq_domain *irq_domain; ++ struct resource *resource; ++ int irq; ++ struct iproc_gpio_irqcfg *irqcfg; ++ /* GPIO register bit shift */ ++ int pin_reg_bit_shift; ++}; ++ ++static inline struct iproc_gpio_chip *to_iproc_gpio(struct gpio_chip *gpc) ++{ ++ return container_of(gpc, struct iproc_gpio_chip, chip); ++} ++ ++static u32 _iproc_gpio_readl(struct iproc_gpio_chip *chip, int reg) ++{ ++ return readl(chip->ioaddr + reg); ++} ++ ++static void _iproc_gpio_writel(struct iproc_gpio_chip *chip, u32 val, int reg) ++{ ++ writel(val, chip->ioaddr + reg); ++} ++ ++/* ++@ pin : GPIO register bit ++*/ ++static int iproc_gpio_to_irq(struct iproc_gpio_chip *chip, u32 pin) ++{ ++ return irq_linear_revmap(chip->irq_domain, pin - chip->pin_reg_bit_shift); ++} ++ ++/* returns the corresponding gpio register bit */ ++static int iproc_irq_to_gpio(struct iproc_gpio_chip *chip, u32 irq) ++{ ++ struct irq_data *data = irq_domain_get_irq_data(chip->irq_domain, irq); ++ ++ return data->hwirq + chip->pin_reg_bit_shift; ++} ++ ++static void iproc_gpio_irq_ack(struct irq_data *d) ++{ ++ u32 irq = d->irq; ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->ack) ++ irqcfg->ack(irq); ++ } ++} ++ ++static void iproc_gpio_irq_unmask(struct irq_data *d) ++{ ++ u32 irq = d->irq; ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->unmask) ++ irqcfg->unmask(irq); ++ } ++} ++ ++static void iproc_gpio_irq_mask(struct irq_data *d) ++{ ++ u32 irq = d->irq; ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->mask) ++ irqcfg->mask(irq); ++ } ++} ++ ++ ++static int iproc_gpio_irq_set_type(struct irq_data *d, u32 type) ++{ ++ u32 irq = d->irq; ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->set_type) ++ return irqcfg->set_type(irq, type); ++ } ++ ++ return -EINVAL; ++} ++ ++static irqreturn_t iproc_gpio_irq_handler_cca(int irq, void *data) ++{ ++ struct iproc_gpio_chip *iproc_gpio = (struct iproc_gpio_chip *)data; ++ struct gpio_chip gc = iproc_gpio->chip; ++ int bit; ++ unsigned long int_bits = 0; ++ u32 int_status; ++ ++ /* go through the entire GPIOs and handle all interrupts */ ++ int_status = readl(iproc_gpio->intr_ioaddr + CCA_INT_STS); ++ if (int_status & CCA_INT_F_GPIOINT) { ++ u32 event, level; ++ ++ /* Get level and edge interrupts */ ++ event = readl(iproc_gpio->ioaddr + GPIO_CCA_INT_EVENT_MASK); ++ event &= readl(iproc_gpio->ioaddr + GPIO_CCA_INT_EVENT); ++ level = readl(iproc_gpio->ioaddr + GPIO_CCA_DIN); ++ level ^= readl(iproc_gpio->ioaddr + GPIO_CCA_INT_LEVEL); ++ level &= readl(iproc_gpio->ioaddr + GPIO_CCA_INT_LEVEL_MASK); ++ int_bits = level | event; ++ ++ for_each_set_bit(bit, &int_bits, gc.ngpio) ++ generic_handle_irq( ++ irq_linear_revmap(iproc_gpio->irq_domain, bit)); ++ } ++ ++ return int_bits ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++ ++static void iproc_gpio_irq_ack_cca(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 irq_type, event_status = 0; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_get_trigger_type(irq); ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_status |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_status, GPIO_CCA_INT_EVENT); ++ } ++} ++ ++static void iproc_gpio_irq_unmask_cca(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 int_mask, irq_type, event_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_get_trigger_type(irq); ++ event_mask = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, event_mask, GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, int_mask, GPIO_CCA_INT_LEVEL_MASK); ++ } ++} ++ ++static void iproc_gpio_irq_mask_cca(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 irq_type, int_mask, event_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_get_trigger_type(irq); ++ event_mask = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_mask, GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, GPIO_CCA_INT_LEVEL_MASK); ++ } ++} ++ ++static int iproc_gpio_irq_set_type_cca(u32 irq, u32 type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 event_pol, int_pol; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_RISING: ++ event_pol = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_EDGE); ++ event_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ event_pol = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_EDGE); ++ event_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_pol = _iproc_gpio_readl(ourchip, GPIO_CCA_INT_LEVEL); ++ int_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, GPIO_CCA_INT_LEVEL); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_pol = _iproc_gpio_readl(ourchip,GPIO_CCA_INT_LEVEL); ++ int_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, GPIO_CCA_INT_LEVEL); ++ break; ++ default: ++ /* should not come here */ ++ return -EINVAL; ++ } ++ ++ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) ++ irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq); ++ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) ++ irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq); ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg cca_gpio_irqcfg = { ++ /* ++ * Remove IRQF_NO_SUSPEND to be consistent with 8250_core.c setting, ++ * since CCA gpio and uart share the same IRQ. ++ */ ++ .flags = IRQF_SHARED, ++ .handler = iproc_gpio_irq_handler_cca, ++ .ack = iproc_gpio_irq_ack_cca, ++ .mask = iproc_gpio_irq_mask_cca, ++ .unmask = iproc_gpio_irq_unmask_cca, ++ .set_type = iproc_gpio_irq_set_type_cca, ++}; ++ ++static irqreturn_t iproc_gpio_irq_handler_ccb(int irq, void *dev) ++{ ++ struct iproc_gpio_chip *ourchip = dev; ++ int iter, max_pin; ++ u32 val; ++ ++ val = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_MSTAT); ++ if (!val) ++ return IRQ_NONE; ++ ++ /* Max GPIO register bit */ ++ max_pin = ourchip->pin_reg_bit_shift + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_reg_bit_shift; iter < max_pin; iter++) ++ if (val & (1 << iter)) ++ generic_handle_irq(iproc_gpio_to_irq(ourchip, iter)); ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_ccb(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 int_clear = 0; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ int_clear |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_clear, GPIO_CCB_INT_CLR); ++} ++ ++static void iproc_gpio_irq_unmask_ccb(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ int_mask = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_MASK); ++ int_mask |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, GPIO_CCB_INT_MASK); ++} ++ ++static void iproc_gpio_irq_mask_ccb(u32 irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ int_mask = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_MASK); ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask,GPIO_CCB_INT_MASK); ++} ++ ++static int iproc_gpio_irq_set_type_ccb(u32 irq, u32 type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ u32 int_type, int_de, int_edge; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ int_type = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_TYPE); ++ int_edge = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_EDGE); ++ ++ switch (type) { ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type &= ~(1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_DE); ++ int_de |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ int_type &= ~(1 << pin); ++ int_edge |= (1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type &= ~(1 << pin); ++ int_edge &= ~(1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type |= (1 << pin); ++ int_edge |= (1 << pin); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type |= (1 << pin); ++ int_edge &= ~(1 << pin); ++ break; ++ default: ++ /* should not come here */ ++ return -EINVAL; ++ } ++ ++ _iproc_gpio_writel(ourchip, int_type, GPIO_CCB_INT_TYPE); ++ _iproc_gpio_writel(ourchip, int_edge, GPIO_CCB_INT_EDGE); ++ ++ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) ++ irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq); ++ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) ++ irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq); ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg ccb_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND, ++ .handler = iproc_gpio_irq_handler_ccb, ++ .ack = iproc_gpio_irq_ack_ccb, ++ .mask = iproc_gpio_irq_mask_ccb, ++ .unmask = iproc_gpio_irq_unmask_ccb, ++ .set_type = iproc_gpio_irq_set_type_ccb, ++}; ++ ++static struct irq_chip iproc_gpio_irq_chip = { ++ .name = "IPROC-GPIO", ++ .irq_ack = (void *) iproc_gpio_irq_ack, ++ .irq_mask = (void *) iproc_gpio_irq_mask, ++ .irq_unmask = (void *) iproc_gpio_irq_unmask, ++ .irq_set_type = (void *) iproc_gpio_irq_set_type, ++}; ++ ++ ++static int iproc_gpiolib_input(struct gpio_chip *chip, u32 gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ u32 val, nBitMask; ++ int reg_offset; ++ u32 pin_offset = gpio + ourchip->pin_reg_bit_shift; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ nBitMask = 1 << pin_offset; ++ reg_offset = REGOFFSET_GPIO_OUT_EN; ++ ++ val = _iproc_gpio_readl(ourchip, reg_offset); ++ val &= ~nBitMask; ++ _iproc_gpio_writel(ourchip, val, reg_offset); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return 0; ++} ++ ++static int iproc_gpiolib_output(struct gpio_chip *chip, u32 gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags, val; ++ u32 nBitMask; ++ int reg_offset; ++ /* GPIO register bit */ ++ u32 pin_offset = gpio + ourchip->pin_reg_bit_shift; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ nBitMask = 1 << pin_offset; ++ reg_offset = REGOFFSET_GPIO_OUT_EN; ++ ++ val = _iproc_gpio_readl(ourchip, reg_offset); ++ val |= nBitMask; ++ _iproc_gpio_writel(ourchip, val, reg_offset); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return 0; ++} ++ ++static void iproc_gpiolib_set(struct gpio_chip *chip, u32 gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags, val; ++ u32 nBitMask; ++ /* GPIO register bit */ ++ u32 pin_offset = gpio + ourchip->pin_reg_bit_shift; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ nBitMask = 1 << pin_offset; ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_OUT_EN); ++ val &= nBitMask; ++ ++ /* this function only applies to output pin */ ++ if (!val) ++ return; ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ if (value == 0) ++ /* Set the pin to zero */ ++ val &= ~nBitMask; ++ else ++ /* Set the pin to 1 */ ++ val |= nBitMask; ++ ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_DOUT); ++ ++ iproc_gpio_unlock(ourchip, flags); ++} ++ ++static int iproc_gpiolib_get(struct gpio_chip *chip, u32 gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ u32 val, offset, nBitMask; ++ /* GPIO register bit */ ++ u32 pin_offset = gpio + ourchip->pin_reg_bit_shift; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ nBitMask = 1 << pin_offset; ++ ++ /* determine the GPIO pin direction */ ++ offset = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_OUT_EN); ++ offset &= nBitMask; ++ ++ if (offset) ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ else ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DIN); ++ ++ val >>= pin_offset; ++ val &= 1; ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return val; ++} ++ ++/* ++@offset : the gpio pin index number from gpiolib view (minus gpio base only) ++*/ ++static int iproc_gpiolib_to_irq(struct gpio_chip *chip, u32 offset) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ ++ return irq_linear_revmap(ourchip->irq_domain, offset); ++} ++ ++static struct __initconst of_device_id bcm_iproc_gpio_of_match[] = { ++ { .compatible = "brcm,iproc-gpio-cca" }, ++ { .compatible = "brcm,iproc-gpio-ccb" }, ++ { .compatible = "brcm,iproc-gpio-ccg" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_gpio_of_match); ++ ++static int iproc_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *dn = pdev->dev.of_node; ++ struct iproc_gpio_chip *iproc_gpio; ++ u32 num_gpios, count; ++ int ret; ++ ++ iproc_gpio = devm_kzalloc(&pdev->dev, sizeof(*iproc_gpio), GFP_KERNEL); ++ if (!iproc_gpio) { ++ dev_err(&pdev->dev, "Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, iproc_gpio); ++ ++ /* Determine type of gpio controller to allocate */ ++ if (of_device_is_compatible(dn, "brcm,iproc-gpio-cca")) { ++ iproc_gpio->chip.label = "gpio_cca"; ++ iproc_gpio->id = IPROC_GPIO_CCA_ID; ++ iproc_gpio->irqcfg = &cca_gpio_irqcfg; ++ ++ iproc_gpio->intr_ioaddr = of_iomap(dn, 1); ++ if (!iproc_gpio->intr_ioaddr) { ++ dev_err(&pdev->dev, "gpio interrupt base addr fail\n"); ++ return -ENOMEM; ++ } ++ ++ dev_info(&pdev->dev, "%s intr_ioaddr: %p\n", ++ iproc_gpio->chip.label, iproc_gpio->intr_ioaddr); ++ } else if (of_device_is_compatible(dn, "brcm,iproc-gpio-ccb")) { ++ iproc_gpio->chip.label = "gpio_ccb"; ++ iproc_gpio->id = IPROC_GPIO_CCB_ID; ++ iproc_gpio->irqcfg = &ccb_gpio_irqcfg; ++ } else if (of_device_is_compatible(dn, "brcm,iproc-gpio-ccg")) { ++ iproc_gpio->chip.label = "gpio_ccg"; ++ iproc_gpio->id = IPROC_GPIO_CCG_ID; ++ iproc_gpio->irqcfg = &ccb_gpio_irqcfg; ++ } else { ++ dev_err(&pdev->dev, "Error parsing device tree of GPIO\n"); ++ return -ENODEV; ++ } ++ ++ /* Map gpio base ioaddr address */ ++ iproc_gpio->ioaddr = of_iomap(dn, 0); ++ if (!iproc_gpio->ioaddr) { ++ dev_err(&pdev->dev, "can't iomap gpio base address\n"); ++ return -ENOMEM; ++ } ++ dev_info(&pdev->dev, "%s ioaddr: %p\n", iproc_gpio->chip.label, ++ iproc_gpio->ioaddr); ++ ++ /* pin_base: gpio pin base */ ++ if (of_property_read_u32(dn, "pin-base", &iproc_gpio->chip.base)) { ++ dev_err(&pdev->dev, "Missing pin-base property\n"); ++ return -EINVAL; ++ } ++ ++ /* pin_reg_bit_shift: GPIO register bit offset */ ++ if (of_property_read_u32(dn, "pin-reg-bit-shift", ++ &iproc_gpio->pin_reg_bit_shift)) { ++ dev_err(&pdev->dev, "Missing pin-reg-bit-shift property\n"); ++ return -EINVAL; ++ } ++ ++ /* Get number of GPIO pin */ ++ if (of_property_read_u32(dn, "ngpios", &num_gpios)) { ++ dev_err(&pdev->dev, "Missing ngpios property\n"); ++ return -EINVAL; ++ } ++ iproc_gpio->chip.ngpio = num_gpios; ++ ++ iproc_gpio->chip.parent = &pdev->dev; ++ iproc_gpio->chip.of_node = dn; ++ ++ iproc_gpio->chip.direction_input = iproc_gpiolib_input; ++ iproc_gpio->chip.direction_output = iproc_gpiolib_output; ++ iproc_gpio->chip.set = iproc_gpiolib_set; ++ iproc_gpio->chip.get = iproc_gpiolib_get; ++ iproc_gpio->chip.to_irq = iproc_gpiolib_to_irq; ++ ++ ret = gpiochip_add_data(&iproc_gpio->chip, iproc_gpio); ++ if (ret) { ++ dev_err(&pdev->dev, "Could not add gpiochip for %s\n", ++ iproc_gpio->chip.label); ++ return ret; ++ } ++ ++ iproc_gpio->irq = platform_get_irq(pdev, 0); ++ ++ if (iproc_gpio->irq < 0) { ++ dev_warn(&pdev->dev, "No IRQ specified for %s\n", ++ iproc_gpio->chip.label); ++ return 0; ++ } ++ ++ /* Create irq domain */ ++ iproc_gpio->irq_domain = irq_domain_add_linear(dn, num_gpios, ++ &irq_domain_simple_ops, iproc_gpio); ++ ++ if (!iproc_gpio->irq_domain) { ++ dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n"); ++ ret = -ENODEV; ++ goto err_irq_domain; ++ } ++ ++ /* Map each gpio pin to an IRQ and set the handler */ ++ for (count = 0; count < num_gpios; count++) { ++ int irq; ++ ++ irq = irq_create_mapping(iproc_gpio->irq_domain, count); ++ irq_set_chip_and_handler(irq, &iproc_gpio_irq_chip, ++ handle_simple_irq); ++ irq_set_chip_data(irq, iproc_gpio); ++ } ++ ++ /* Enable GPIO interrupts for CCA GPIO */ ++ if (iproc_gpio->id == IPROC_GPIO_CCA_ID) { ++ u32 val; ++ val = readl(iproc_gpio->intr_ioaddr + CCA_INT_MASK); ++ val |= CCA_INT_F_GPIOINT; ++ writel(val, iproc_gpio->intr_ioaddr + CCA_INT_MASK); ++ } ++ ++ /* Install ISR for this GPIO controller */ ++ if (iproc_gpio->irqcfg) { ++ struct iproc_gpio_irqcfg *irqcfg = iproc_gpio->irqcfg; ++ if (irqcfg->handler) { ++ ret = request_irq(iproc_gpio->irq, irqcfg->handler, ++ irqcfg->flags, iproc_gpio->chip.label, ++ iproc_gpio); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to request IRQ%d\n", ++ iproc_gpio->irq); ++ goto err_irq_request; ++ } ++ } else { ++ dev_warn(&pdev->dev, "%s has no isr!\n", ++ iproc_gpio->chip.label); ++ } ++ } ++ ++ return 0; ++ ++err_irq_request: ++ irq_domain_remove(iproc_gpio->irq_domain); ++ iproc_gpio->irq_domain = NULL; ++ ++err_irq_domain: ++ gpiochip_remove(&iproc_gpio->chip); ++ ++ return ret; ++} ++ ++static int __exit iproc_gpio_remove(struct platform_device *pdev) ++{ ++ struct iproc_gpio_chip *iproc_gpio; ++ ++ iproc_gpio = platform_get_drvdata(pdev); ++ if (iproc_gpio == NULL) ++ return -ENODEV; ++ ++ if (iproc_gpio->intr_ioaddr) { ++ /* Disable GPIO interrupts for CCA GPIO */ ++ if (iproc_gpio->id == IPROC_GPIO_CCA_ID) { ++ u32 val; ++ val = readl(iproc_gpio->intr_ioaddr + CCA_INT_MASK); ++ val &= ~(CCA_INT_F_GPIOINT); ++ writel(val, iproc_gpio->intr_ioaddr + CCA_INT_MASK); ++ } ++ } ++ ++ gpiochip_remove(&iproc_gpio->chip); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm_iproc_gpio_driver = { ++ .driver = { ++ .name = "iproc-gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_iproc_gpio_of_match, ++ }, ++ .probe = iproc_gpio_probe, ++ .remove = iproc_gpio_remove, ++}; ++ ++module_platform_driver(bcm_iproc_gpio_driver); ++ ++MODULE_DESCRIPTION("XGS IPROC GPIO driver"); ++MODULE_LICENSE("GPL v2"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +--- a/drivers/i2c/busses/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/i2c/busses/Kconfig 2018-05-10 11:31:30.853400956 +0800 +@@ -418,6 +418,26 @@ config I2C_BCM_IPROC + + If you don't know what to do here, say N. + ++config I2C_XGS_IPROC ++ tristate "Broadcom XGS iProc I2C controller" ++ depends on ARCH_XGS_IPROC ++ default ARCH_XGS_IPROC ++ help ++ If you say yes to this option, support will be included for the ++ Broadcom XGS iProc I2C controller. ++ ++ If you don't know what to do here, say N. ++ ++config SMBUS_XGS_IPROC ++ tristate "Broadcom XGS iProc SMBUS controller" ++ depends on ARCH_XGS_IPROC && !I2C_XGS_IPROC ++ default n ++ help ++ If you say yes to this option, support will be included for the ++ Broadcom XGS iProc SMBUS controller. ++ ++ If you don't know what to do here, say N. ++ + config I2C_BCM_KONA + tristate "BCM Kona I2C adapter" + depends on ARCH_BCM_MOBILE +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +--- a/drivers/i2c/busses/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/i2c/busses/Makefile 2018-05-10 11:31:30.853400956 +0800 +@@ -108,6 +108,8 @@ i2c-octeon-objs := i2c-octeon-core.o i2c + obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o + i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o + obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o ++obj-$(CONFIG_I2C_XGS_IPROC) += i2c-xgs-iproc.o ++obj-$(CONFIG_SMBUS_XGS_IPROC) += xgs_iproc_smbus.o + obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o + obj-$(CONFIG_I2C_XLR) += i2c-xlr.o + obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/i2c-xgs-iproc.c b/drivers/i2c/busses/i2c-xgs-iproc.c +--- a/drivers/i2c/busses/i2c-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/i2c/busses/i2c-xgs-iproc.c 2018-05-10 11:31:30.877400982 +0800 +@@ -0,0 +1,584 @@ ++/* ++ * Copyright (C) 2014 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * This file is based on i2c-bcm-iproc.c with the following changes. ++ * 1. Enable read support with data len >= 64B ++ * 2. Different implementation of write support for data len >= 64B ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CFG_OFFSET 0x00 ++#define CFG_RESET_SHIFT 31 ++#define CFG_EN_SHIFT 30 ++#define CFG_M_RETRY_CNT_SHIFT 16 ++#define CFG_M_RETRY_CNT_MASK 0x0f ++ ++#define TIM_CFG_OFFSET 0x04 ++#define TIM_CFG_MODE_400_SHIFT 31 ++ ++#define M_FIFO_CTRL_OFFSET 0x0c ++#define M_FIFO_RX_FLUSH_SHIFT 31 ++#define M_FIFO_TX_FLUSH_SHIFT 30 ++#define M_FIFO_RX_CNT_SHIFT 16 ++#define M_FIFO_RX_CNT_MASK 0x7f ++#define M_FIFO_RX_THLD_SHIFT 8 ++#define M_FIFO_RX_THLD_MASK 0x3f ++ ++#define M_CMD_OFFSET 0x30 ++#define M_CMD_START_BUSY_SHIFT 31 ++#define M_CMD_STATUS_SHIFT 25 ++#define M_CMD_STATUS_MASK 0x07 ++#define M_CMD_STATUS_SUCCESS 0x0 ++#define M_CMD_STATUS_LOST_ARB 0x1 ++#define M_CMD_STATUS_NACK_ADDR 0x2 ++#define M_CMD_STATUS_NACK_DATA 0x3 ++#define M_CMD_STATUS_TIMEOUT 0x4 ++#define M_CMD_PROTOCOL_SHIFT 9 ++#define M_CMD_PROTOCOL_MASK 0xf ++#define M_CMD_PROTOCOL_BLK_WR 0x7 ++#define M_CMD_PROTOCOL_BLK_RD 0x8 ++#define M_CMD_PEC_SHIFT 8 ++#define M_CMD_RD_CNT_SHIFT 0 ++#define M_CMD_RD_CNT_MASK 0xff ++ ++#define IE_OFFSET 0x38 ++#define IE_M_RX_FIFO_FULL_SHIFT 31 ++#define IE_M_RX_THLD_SHIFT 30 ++#define IE_M_START_BUSY_SHIFT 28 ++ ++#define IS_OFFSET 0x3c ++#define IS_M_RX_FIFO_FULL_SHIFT 31 ++#define IS_M_RX_THLD_SHIFT 30 ++#define IS_M_START_BUSY_SHIFT 28 ++ ++#define M_TX_OFFSET 0x40 ++#define M_TX_WR_STATUS_SHIFT 31 ++#define M_TX_DATA_SHIFT 0 ++#define M_TX_DATA_MASK 0xff ++ ++#define M_RX_OFFSET 0x44 ++#define M_RX_STATUS_SHIFT 30 ++#define M_RX_STATUS_MASK 0x03 ++#define M_RX_PEC_ERR_SHIFT 29 ++#define M_RX_DATA_SHIFT 0 ++#define M_RX_DATA_MASK 0xff ++ ++#define I2C_TIMEOUT_MSEC 100 ++ ++#define M_TX_RX_FIFO_SIZE 64 ++#define I2C_MAX_DATA_LEN (M_TX_RX_FIFO_SIZE - 1) ++ ++/* ++ * Enable support of EEPROM I2C devices with 2-byte addressing mode ++ * (total size > 256B)and page size >= 64B. ++ */ ++#define CONFIG_ENABLE_WRITE_MSG_SPLIT 1 ++ ++ ++enum bus_speed_index { ++ I2C_SPD_100K = 0, ++ I2C_SPD_400K, ++}; ++ ++struct bcm_iproc_i2c_dev { ++ struct device *device; ++ int irq; ++ ++ void __iomem *base; ++ ++ struct i2c_adapter adapter; ++ unsigned int bus_speed; ++ ++ struct completion done; ++ int xfer_is_done; ++}; ++ ++/* ++ * Can be expanded in the future if more interrupt status bits are utilized ++ */ ++#define ISR_MASK (1 << IS_M_START_BUSY_SHIFT) ++ ++static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) ++{ ++ struct bcm_iproc_i2c_dev *iproc_i2c = data; ++ u32 status = readl(iproc_i2c->base + IS_OFFSET); ++ ++ status &= ISR_MASK; ++ ++ if (!status) ++ return IRQ_NONE; ++ ++ writel(status, iproc_i2c->base + IS_OFFSET); ++ iproc_i2c->xfer_is_done = 1; ++ complete(&iproc_i2c->done); ++ ++ return IRQ_HANDLED; ++} ++ ++static int bcm_iproc_i2c_check_status(struct bcm_iproc_i2c_dev *iproc_i2c, ++ struct i2c_msg *msg) ++{ ++ u32 val; ++ ++ val = readl(iproc_i2c->base + M_CMD_OFFSET); ++ val = (val >> M_CMD_STATUS_SHIFT) & M_CMD_STATUS_MASK; ++ ++ switch (val) { ++ case M_CMD_STATUS_SUCCESS: ++ return 0; ++ ++ case M_CMD_STATUS_LOST_ARB: ++ dev_dbg(iproc_i2c->device, "lost bus arbitration\n"); ++ return -EAGAIN; ++ ++ case M_CMD_STATUS_NACK_ADDR: ++ dev_dbg(iproc_i2c->device, "NAK addr:0x%02x\n", msg->addr); ++ return -ENXIO; ++ ++ case M_CMD_STATUS_NACK_DATA: ++ dev_dbg(iproc_i2c->device, "NAK data\n"); ++ return -ENXIO; ++ ++ case M_CMD_STATUS_TIMEOUT: ++ dev_dbg(iproc_i2c->device, "bus timeout\n"); ++ return -ETIMEDOUT; ++ ++ default: ++ dev_dbg(iproc_i2c->device, "unknown error code=%d\n", val); ++ return -EIO; ++ } ++} ++ ++static int bcm_iproc_i2c_xfer_one_msg(struct bcm_iproc_i2c_dev *iproc_i2c, ++ struct i2c_msg *msg) ++{ ++ int ret, i; ++ u8 addr; ++ u32 val; ++ unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MSEC); ++ ++ /* check if bus is busy */ ++ if (!!(readl(iproc_i2c->base + M_CMD_OFFSET) & ++ BIT(M_CMD_START_BUSY_SHIFT))) { ++ dev_warn(iproc_i2c->device, "bus is busy\n"); ++ return -EBUSY; ++ } ++ ++ /* format and load slave address into the TX FIFO */ ++ addr = i2c_8bit_addr_from_msg(msg); ++ writel(addr, iproc_i2c->base + M_TX_OFFSET); ++ ++ /* for a write transaction, load data into the TX FIFO */ ++ if (!(msg->flags & I2C_M_RD)) { ++ for (i = 0; i < msg->len; i++) { ++ val = msg->buf[i]; ++ ++ /* mark the last byte */ ++ if (i == msg->len - 1) ++ val |= 1 << M_TX_WR_STATUS_SHIFT; ++ ++ writel(val, iproc_i2c->base + M_TX_OFFSET); ++ } ++ } ++ ++ /* mark as incomplete before starting the transaction */ ++ reinit_completion(&iproc_i2c->done); ++ iproc_i2c->xfer_is_done = 0; ++ ++ /* ++ * Enable the "start busy" interrupt, which will be triggered after the ++ * transaction is done, i.e., the internal start_busy bit, transitions ++ * from 1 to 0. ++ */ ++ writel(1 << IE_M_START_BUSY_SHIFT, iproc_i2c->base + IE_OFFSET); ++ ++ /* ++ * Now we can activate the transfer. For a read operation, specify the ++ * number of bytes to read ++ */ ++ val = 1 << M_CMD_START_BUSY_SHIFT; ++ if (msg->flags & I2C_M_RD) { ++ val |= (M_CMD_PROTOCOL_BLK_RD << M_CMD_PROTOCOL_SHIFT) | ++ (msg->len << M_CMD_RD_CNT_SHIFT); ++ } else { ++ val |= (M_CMD_PROTOCOL_BLK_WR << M_CMD_PROTOCOL_SHIFT); ++ } ++ writel(val, iproc_i2c->base + M_CMD_OFFSET); ++ ++ time_left = wait_for_completion_timeout(&iproc_i2c->done, time_left); ++ ++ /* disable all interrupts */ ++ writel(0, iproc_i2c->base + IE_OFFSET); ++ /* read it back to flush the write */ ++ readl(iproc_i2c->base + IE_OFFSET); ++ ++ /* make sure the interrupt handler isn't running */ ++ synchronize_irq(iproc_i2c->irq); ++ ++ if (!time_left && !iproc_i2c->xfer_is_done) { ++ dev_err(iproc_i2c->device, "transaction timed out\n"); ++ ++ /* flush FIFOs */ ++ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | ++ (1 << M_FIFO_TX_FLUSH_SHIFT); ++ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); ++ return -ETIMEDOUT; ++ } ++ ++ ret = bcm_iproc_i2c_check_status(iproc_i2c, msg); ++ if (ret) { ++ /* flush both TX/RX FIFOs */ ++ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | ++ (1 << M_FIFO_TX_FLUSH_SHIFT); ++ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); ++ return ret; ++ } ++ ++ /* ++ * For a read operation, we now need to load the data from FIFO ++ * into the memory buffer ++ */ ++ if (msg->flags & I2C_M_RD) { ++ for (i = 0; i < msg->len; i++) { ++ msg->buf[i] = (readl(iproc_i2c->base + M_RX_OFFSET) >> ++ M_RX_DATA_SHIFT) & M_RX_DATA_MASK; ++ } ++ } ++ ++ return 0; ++} ++ ++static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg msgs[], int num) ++{ ++ struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(adapter); ++ int ret, i; ++ int xfer_msg_len; ++ u8 addr_h, addr_l; ++ ++ /* go through all messages */ ++ for (i = 0; i < num; i++) { ++ xfer_msg_len = msgs[i].len; ++ ++ while (xfer_msg_len) { ++ if (xfer_msg_len > I2C_MAX_DATA_LEN) ++ msgs[i].len = I2C_MAX_DATA_LEN; ++ ++ ret = bcm_iproc_i2c_xfer_one_msg(iproc_i2c, &msgs[i]); ++ if (ret) { ++ dev_dbg(iproc_i2c->device, "xfer failed\n"); ++ return ret; ++ } ++ ++ xfer_msg_len -= msgs[i].len; ++ if (xfer_msg_len == 0) ++ break; ++ ++#if defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) ++ /* Keep the addr offset for later use */ ++ addr_h = msgs[i].buf[0]; ++ addr_l = msgs[i].buf[1]; ++#endif ++ ++ msgs[i].len = xfer_msg_len; ++ msgs[i].buf += I2C_MAX_DATA_LEN; ++ ++#if defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ /* ++ * For write transfer with len >= 64B, assuming ++ * 2-byte addressing should be reasonable. ++ */ ++ xfer_msg_len += 2; ++ msgs[i].len = xfer_msg_len; ++ /* ++ * Append a new 2-byte address offset. ++ * The upper byte should be unchanged, and the ++ * lower byte is increased by actually written ++ * bytes: (I2C_MAX_DATA_LEN - 2) ++ */ ++ msgs[i].buf -= 2; ++ msgs[i].buf[0] = addr_h; ++ msgs[i].buf[1] = addr_l + I2C_MAX_DATA_LEN - 2; ++ ++ /* ++ * Wait some time so that EEPROM is ready to ++ * respond after previous partial page write. ++ */ ++ if (!(msgs[i].flags & I2C_M_RD)) ++ mdelay(10); ++ } ++#endif /* CONFIG_ENABLE_WRITE_MSG_SPLIT */ ++ } /* while */ ++ } /* for */ ++ ++ return num; ++} ++ ++ ++static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm bcm_iproc_algo = { ++ .master_xfer = bcm_iproc_i2c_xfer, ++ .functionality = bcm_iproc_i2c_functionality, ++}; ++ ++/* ++ * Don't limit the max write length for Linux I2C core, if support of ++ * write msg split is enabled. ++ * Read msg split is supported, so max_read_len is commented out. ++ */ ++#if !defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) ++static const struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { ++ /* need to reserve one byte in the FIFO for the slave address */ ++ //.max_read_len = M_TX_RX_FIFO_SIZE - 1, ++ .max_write_len = M_TX_RX_FIFO_SIZE - 1, ++}; ++#endif ++ ++static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c) ++{ ++ unsigned int bus_speed; ++ u32 val; ++ int ret = of_property_read_u32(iproc_i2c->device->of_node, ++ "clock-frequency", &bus_speed); ++ if (ret < 0) { ++ dev_info(iproc_i2c->device, ++ "unable to interpret clock-frequency DT property\n"); ++ bus_speed = 100000; ++ } ++ ++ if (bus_speed < 100000) { ++ dev_err(iproc_i2c->device, "%d Hz bus speed not supported\n", ++ bus_speed); ++ dev_err(iproc_i2c->device, ++ "valid speeds are 100khz and 400khz\n"); ++ return -EINVAL; ++ } else if (bus_speed < 400000) { ++ bus_speed = 100000; ++ } else { ++ bus_speed = 400000; ++ } ++ ++ iproc_i2c->bus_speed = bus_speed; ++ val = readl(iproc_i2c->base + TIM_CFG_OFFSET); ++ val &= ~(1 << TIM_CFG_MODE_400_SHIFT); ++ val |= (bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; ++ writel(val, iproc_i2c->base + TIM_CFG_OFFSET); ++ ++ dev_info(iproc_i2c->device, "bus set to %u Hz\n", bus_speed); ++ ++ return 0; ++} ++ ++static int bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) ++{ ++ u32 val; ++ ++ /* put controller in reset */ ++ val = readl(iproc_i2c->base + CFG_OFFSET); ++ val |= 1 << CFG_RESET_SHIFT; ++ val &= ~(1 << CFG_EN_SHIFT); ++ writel(val, iproc_i2c->base + CFG_OFFSET); ++ ++ /* wait 100 usec per spec */ ++ udelay(100); ++ ++ /* bring controller out of reset */ ++ val &= ~(1 << CFG_RESET_SHIFT); ++ writel(val, iproc_i2c->base + CFG_OFFSET); ++ ++ /* flush TX/RX FIFOs and set RX FIFO threshold to zero */ ++ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | (1 << M_FIFO_TX_FLUSH_SHIFT); ++ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); ++ ++ /* disable all interrupts */ ++ writel(0, iproc_i2c->base + IE_OFFSET); ++ ++ /* clear all pending interrupts */ ++ writel(0xffffffff, iproc_i2c->base + IS_OFFSET); ++ ++ return 0; ++} ++ ++static void bcm_iproc_i2c_enable_disable(struct bcm_iproc_i2c_dev *iproc_i2c, ++ bool enable) ++{ ++ u32 val; ++ ++ val = readl(iproc_i2c->base + CFG_OFFSET); ++ if (enable) ++ val |= BIT(CFG_EN_SHIFT); ++ else ++ val &= ~BIT(CFG_EN_SHIFT); ++ writel(val, iproc_i2c->base + CFG_OFFSET); ++} ++ ++static int bcm_iproc_i2c_probe(struct platform_device *pdev) ++{ ++ int irq, ret = 0; ++ struct bcm_iproc_i2c_dev *iproc_i2c; ++ struct i2c_adapter *adap; ++ struct resource *res; ++ ++ iproc_i2c = devm_kzalloc(&pdev->dev, sizeof(*iproc_i2c), ++ GFP_KERNEL); ++ if (!iproc_i2c) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, iproc_i2c); ++ iproc_i2c->device = &pdev->dev; ++ init_completion(&iproc_i2c->done); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ iproc_i2c->base = devm_ioremap_resource(iproc_i2c->device, res); ++ if (IS_ERR(iproc_i2c->base)) ++ return PTR_ERR(iproc_i2c->base); ++ ++ ret = bcm_iproc_i2c_init(iproc_i2c); ++ if (ret) ++ return ret; ++ ++ ret = bcm_iproc_i2c_cfg_speed(iproc_i2c); ++ if (ret) ++ return ret; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(iproc_i2c->device, "no irq resource\n"); ++ return irq; ++ } ++ iproc_i2c->irq = irq; ++ ++ ret = devm_request_irq(iproc_i2c->device, irq, bcm_iproc_i2c_isr, 0, ++ pdev->name, iproc_i2c); ++ if (ret < 0) { ++ dev_err(iproc_i2c->device, "unable to request irq %i\n", irq); ++ return ret; ++ } ++ ++ bcm_iproc_i2c_enable_disable(iproc_i2c, true); ++ ++ adap = &iproc_i2c->adapter; ++ i2c_set_adapdata(adap, iproc_i2c); ++ strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name)); ++ adap->algo = &bcm_iproc_algo; ++#if !defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) ++ adap->quirks = &bcm_iproc_i2c_quirks; ++#endif ++ adap->dev.parent = &pdev->dev; ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ return i2c_add_adapter(adap); ++} ++ ++static int bcm_iproc_i2c_remove(struct platform_device *pdev) ++{ ++ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); ++ ++ /* make sure there's no pending interrupt when we remove the adapter */ ++ writel(0, iproc_i2c->base + IE_OFFSET); ++ readl(iproc_i2c->base + IE_OFFSET); ++ synchronize_irq(iproc_i2c->irq); ++ ++ i2c_del_adapter(&iproc_i2c->adapter); ++ bcm_iproc_i2c_enable_disable(iproc_i2c, false); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++ ++static int bcm_iproc_i2c_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); ++ ++ /* make sure there's no pending interrupt when we go into suspend */ ++ writel(0, iproc_i2c->base + IE_OFFSET); ++ readl(iproc_i2c->base + IE_OFFSET); ++ synchronize_irq(iproc_i2c->irq); ++ ++ /* now disable the controller */ ++ bcm_iproc_i2c_enable_disable(iproc_i2c, false); ++ ++ return 0; ++} ++ ++static int bcm_iproc_i2c_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); ++ int ret; ++ u32 val; ++ ++ /* ++ * Power domain could have been shut off completely in system deep ++ * sleep, so re-initialize the block here ++ */ ++ ret = bcm_iproc_i2c_init(iproc_i2c); ++ if (ret) ++ return ret; ++ ++ /* configure to the desired bus speed */ ++ val = readl(iproc_i2c->base + TIM_CFG_OFFSET); ++ val &= ~(1 << TIM_CFG_MODE_400_SHIFT); ++ val |= (iproc_i2c->bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; ++ writel(val, iproc_i2c->base + TIM_CFG_OFFSET); ++ ++ bcm_iproc_i2c_enable_disable(iproc_i2c, true); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops bcm_iproc_i2c_pm_ops = { ++ .suspend_late = &bcm_iproc_i2c_suspend, ++ .resume_early = &bcm_iproc_i2c_resume ++}; ++ ++#define BCM_IPROC_I2C_PM_OPS (&bcm_iproc_i2c_pm_ops) ++#else ++#define BCM_IPROC_I2C_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static const struct of_device_id bcm_iproc_i2c_of_match[] = { ++ { .compatible = "brcm,iproc-i2c" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_i2c_of_match); ++ ++static struct platform_driver bcm_iproc_i2c_driver = { ++ .driver = { ++ .name = "bcm-iproc-i2c", ++ .of_match_table = bcm_iproc_i2c_of_match, ++ .pm = BCM_IPROC_I2C_PM_OPS, ++ }, ++ .probe = bcm_iproc_i2c_probe, ++ .remove = bcm_iproc_i2c_remove, ++}; ++module_platform_driver(bcm_iproc_i2c_driver); ++ ++MODULE_DESCRIPTION("Broadcom iProc I2C Driver"); ++MODULE_LICENSE("GPL v2"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/iproc_smbus_regs.h b/drivers/i2c/busses/iproc_smbus_regs.h +--- a/drivers/i2c/busses/iproc_smbus_regs.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/i2c/busses/iproc_smbus_regs.h 2018-05-10 11:31:30.877400982 +0800 +@@ -0,0 +1,287 @@ ++/* ++ * Copyright (C) 2013 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __IPROC_SMBUS_REGS_H__ ++#define __IPROC_SMBUS_REGS_H__ ++ ++/* --- */ ++#define CCB_SMB_CFG_REG 0x0 ++ ++#define CCB_SMB_CFG_RST_MASK 0x80000000 ++#define CCB_SMB_CFG_RST_SHIFT 31 ++ ++#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 ++#define CCB_SMB_CFG_SMBEN_SHIFT 30 ++ ++#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 ++#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 ++ ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 ++ ++#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 ++#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 ++ ++#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 ++#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 ++ ++#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 ++#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 ++ ++ ++/* --- */ ++#define CCB_SMB_TIMGCFG_REG 0x4 ++ ++#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 ++#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 ++ ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 ++ ++#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 ++#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 ++ ++#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 ++#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_ADDR_REG 0x8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 ++#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 ++ ++#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 ++#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 ++ ++#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 ++#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 ++ ++#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 ++#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 ++ ++#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 ++#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 ++ ++#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 ++#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 ++#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 ++ ++#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F ++#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_MSTRFIFOCTL_REG 0xC ++ ++#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_SLVFIFOCTL_REG 0x10 ++ ++#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_BITBANGCTL_REG 0x14 ++ ++#define CCB_SMB_SMBCLKIN_MASK 0x80000000 ++#define CCB_SMB_SMBCLKIN_SHIFT 31 ++ ++#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 ++#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 ++ ++#define CCB_SMB_SMBDATAIN_MASK 0x20000000 ++#define CCB_SMB_SMBDATAIN_SHIFT 29 ++ ++#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 ++#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 ++ ++/* --- */ ++#define CCB_SMB_MSTRCMD_REG 0x30 ++ ++#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_MSTRABORT_MASK 0x40000000 ++#define CCB_SMB_MSTRABORT_SHIFT 30 ++ ++#define CCB_SMB_MSTRSTS_MASK 0x0E000000 ++#define CCB_SMB_MSTRSTS_SHIFT 25 ++ ++#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 ++#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 ++ ++#define CCB_SMB_MSTRPEC_MASK 0x00000100 ++#define CCB_SMB_MSTRPEC_SHIFT 8 ++ ++#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF ++#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_SLVCMD_REG 0x34 ++ ++#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_SLVABORT_MASK 0x40000000 ++#define CCB_SMB_SLVABORT_SHIFT 30 ++ ++#define CCB_SMB_SLVSTS_MASK 0x03800000 ++#define CCB_SMB_SLVSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVPEC_MASK 0x00000100 ++#define CCB_SMB_SLVPEC_SHIFT 8 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTEN_REG 0x38 ++ ++#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTEN_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDEN_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTEN_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTSTS_REG 0x3C ++ ++#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATAWR_REG 0x40 ++ ++#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRWRSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATARD_REG 0x44 ++ ++#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 ++#define CCB_SMB_MSTRRDSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 ++#define CCB_SMB_MSTRRDPECERR_SHIFT 29 ++ ++#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRRDDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATAWR_REG 0x48 ++ ++#define CCB_SMB_SLVWRSTS_MASK 0x80000000 ++#define CCB_SMB_SLVWRSTS_SHIFT 31 ++ ++#define CCB_SMB_SLVWRDATA_MASK 0x000000FF ++#define CCB_SMB_SLVWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATARD_REG 0x4C ++ ++#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 ++#define CCB_SMB_SLVRDSTS_SHIFT 30 ++ ++#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 ++#define CCB_SMB_SLVRDERRSTS_SHIFT 28 ++ ++#define CCB_SMB_SLVRDDATA_MASK 0x000000FF ++#define CCB_SMB_SLVRDDATA_SHIFT 0 ++ ++#endif /* __IPROC_SMBUS_REGS_H__ */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/xgs_iproc_smbus.c b/drivers/i2c/busses/xgs_iproc_smbus.c +--- a/drivers/i2c/busses/xgs_iproc_smbus.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/i2c/busses/xgs_iproc_smbus.c 2018-05-10 11:31:30.881400987 +0800 +@@ -0,0 +1,1075 @@ ++/* ++ * Copyright (C) 2013 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++#include ++#include ++#include "iproc_smbus_regs.h" ++ ++/* SMBUS protocol values defined in register 0x30 */ ++#define SMBUS_PROT_QUICK_CMD 0 ++#define SMBUS_PROT_SEND_BYTE 1 ++#define SMBUS_PROT_RECV_BYTE 2 ++#define SMBUS_PROT_WR_BYTE 3 ++#define SMBUS_PROT_RD_BYTE 4 ++#define SMBUS_PROT_WR_WORD 5 ++#define SMBUS_PROT_RD_WORD 6 ++#define SMBUS_PROT_BLK_WR 7 ++#define SMBUS_PROT_BLK_RD 8 ++#define SMBUS_PROT_PROC_CALL 9 ++#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 ++ ++#define MSTR_STS_XACT_SUCCESS 0 ++#define DISABLE_INTR 0 ++#define ENABLE_INTR 1 ++#define SMB_MAX_DATA_SIZE 32 ++#define XACT_TIMEOUT msecs_to_jiffies(100) ++#define init_MUTEX(x) sema_init(x,1) ++#define IPROC_SMB_MAX_RETRIES 35 ++ ++#define GETREGFLDVAL(regval, mask, startbit) (((regval) & (mask)) >> (startbit)) ++ ++#define SETREGFLDVAL(regval, fldval, mask, startbit) regval = \ ++ (regval & ~(mask)) | \ ++ ((fldval) << (startbit)) ++ ++typedef enum iproc_smb_clk_freq { ++ I2C_SPEED_100KHz = 0, ++ I2C_SPEED_400KHz = 1, ++ I2C_SPEED_INVALID = 255 ++} smb_clk_freq_t; ++ ++/* Counters will be used mainly for testing and debugging */ ++struct iproc_smb_counters { ++ unsigned int num_read_requests; ++ unsigned int num_write_requests; ++ unsigned int num_read_errors; ++ unsigned int num_write_errors; ++ unsigned int mstr_rx_evt_cnt; /* ISR counter to check recv event */ ++ unsigned int mstr_start_busy_cnt; /* ISR counter to checking xact sts */ ++ unsigned int mstr_rx_fifo_full_cnt; /* ISR counter to detect rx fifo full */ ++ unsigned int last_int_sts; /* last value of intr status reg */ ++}; ++ ++/* This structure will be used internally by the driver to maintain its ++ * configuration information as well as information programmed into the hardware ++ */ ++struct iproc_smb_drv_int_data { ++ struct device *dev; ++ struct iproc_smb_drv_int_data *next; ++ int irq; ++ unsigned int drv_state_init; /* 1 = Initialized, 0 = not initialized */ ++ unsigned int drv_state_open; /* 1 = Accepting transaction requests, ++ 0 = Not accepting transaction requests */ ++ smb_clk_freq_t clk_speed; ++ void __iomem *base; /* virtual base address for register access */ ++ struct i2c_adapter adapter; ++ unsigned int i2c_slave_addr; ++ struct semaphore xfer_lock; /* Lock for data transfer */ ++ struct completion ses_done; /* To signal the command completion */ ++ volatile int debug; ++ unsigned int master_rx_fifo_thr; /* Master FIFO threshold */ ++ unsigned int slave_rx_fifo_thr; /* Slave FIFO threshold */ ++ unsigned int enable_evts; ++ unsigned int evt_enable_bmap; /* Bit map of events enabled by the driver */ ++ struct iproc_smb_counters smb_counters; /* Statistics maintained by driver */ ++}; ++ ++/* Structure used to pass information to read/write functions. */ ++struct iproc_xact_info { ++ bool cmd_valid; /* true if command field below is valid. Otherwise, false */ ++ unsigned short command; /* Passed by caller to send SMBus command code */ ++ unsigned char *data; /* actual data pased by the caller */ ++ unsigned int size; /* Size of data buffer passed */ ++ unsigned short flags; /* Sent by caller specifying PEC, 10-bit addresses */ ++ unsigned char smb_proto; /* SMBus protocol to use to perform transaction */ ++}; ++ ++static irqreturn_t iproc_smb_isr(int irq, void *devid) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)devid; ++ unsigned int intsts; ++ unsigned int regval; ++ ++ intsts = readl(dev->base + CCB_SMB_EVTSTS_REG); ++ dev->smb_counters.last_int_sts = intsts; ++ ++ if (!intsts) ++ /* Likely received a spurious interrupt */ ++ return IRQ_NONE; ++ ++ /* Clear interrupts */ ++ writel(intsts, dev->base + CCB_SMB_EVTSTS_REG); ++ ++ /* Master read or write complete */ ++ if ((intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) || ++ (intsts & CCB_SMB_MSTRRXEVTSTS_MASK)) { ++ ++ if (intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) ++ dev->smb_counters.mstr_start_busy_cnt++; ++ ++ if (intsts & CCB_SMB_MSTRRXEVTSTS_MASK) ++ dev->smb_counters.mstr_rx_evt_cnt++; ++ ++ complete(&dev->ses_done); ++ } ++ ++ /* If RX FIFO was full we can either read and then flush the FIFO. ++ * Or, only flush the FIFO, and then the client process can restart ++ * the transaction. ++ * For now, we will flush the later action. ++ */ ++ if (intsts & CCB_SMB_MSTRRXFIFOFULLSTS_MASK) { ++ dev->smb_counters.mstr_rx_fifo_full_cnt++; ++ regval = readl(dev->base + CCB_SMB_MSTRFIFOCTL_REG); ++ regval |= CCB_SMB_MSTRRXFIFOFLSH_MASK; ++ writel(regval, dev->base + CCB_SMB_MSTRFIFOCTL_REG); ++ complete(&dev->ses_done); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * This function set clock frequency for SMBus block. As per hardware ++ * engineering, the clock frequency can be changed dynamically. ++ */ ++static int iproc_smb_set_clk_freq(void __iomem *base_addr, ++ smb_clk_freq_t freq) ++{ ++ unsigned int regval; ++ unsigned int val; ++ ++ switch (freq) { ++ case I2C_SPEED_100KHz: ++ val = 0; ++ break; ++ ++ case I2C_SPEED_400KHz: ++ val = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ break; ++ } ++ ++ regval = readl(base_addr + CCB_SMB_TIMGCFG_REG); ++ SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, ++ CCB_SMB_TIMGCFG_MODE400_SHIFT); ++ writel(regval, base_addr + CCB_SMB_TIMGCFG_REG); ++ ++ return 0; ++} ++ ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev) ++{ ++ ++ void __iomem *base_addr = dev->base; ++ unsigned int regval; ++ u32 i2c_clk_freq; ++ struct device_node *dn = dev->dev->of_node; ++ ++ /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. ++ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts ++ */ ++ regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; ++ ++ writel(regval, base_addr + CCB_SMB_MSTRFIFOCTL_REG); ++ ++ /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero ++ * since there will be only one master ++ */ ++ regval = CCB_SMB_CFG_SMBEN_MASK; ++ ++ writel(regval, base_addr + CCB_SMB_CFG_REG); ++ ++ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ ++ udelay(100); ++ ++ /* Set default clock frequency */ ++ if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq)) ++ /*no property available, use default: 100KHz*/ ++ i2c_clk_freq = I2C_SPEED_100KHz; ++ iproc_smb_set_clk_freq(base_addr, i2c_clk_freq); ++ ++ /* Disable intrs */ ++ regval = 0x0; ++ writel(regval, base_addr + CCB_SMB_EVTEN_REG); ++ ++ /* Clear intrs (W1TC) */ ++ regval = readl(base_addr + CCB_SMB_EVTSTS_REG); ++ writel(regval, base_addr + CCB_SMB_EVTSTS_REG); ++ ++ return(0); ++} ++ ++/* ++ * Function to ensure that the previous transaction was completed before ++ * initiating a new transaction. It can also be used in polling mode to ++ * check status of completion of a command ++ */ ++static int iproc_smb_startbusy_wait(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ ++ regval = readl(dev->base + CCB_SMB_MSTRCMD_REG); ++ ++ /* Check if an operation is in progress. During probe it won't be. ++ * But when shutdown/remove was called we want to make sure that ++ * the transaction in progress completed ++ */ ++ if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { ++ unsigned int i = 0; ++ ++ do { ++ msleep(1); ++ i++; ++ regval = readl(dev->base + CCB_SMB_MSTRCMD_REG); ++ /* If start-busy bit cleared, exit the loop */ ++ } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && ++ (i < IPROC_SMB_MAX_RETRIES)); ++ ++ if (i >= IPROC_SMB_MAX_RETRIES) { ++ dev_err(dev->dev, "START_BUSY bit didn't clear\n"); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++static u32 smbus0_sdaRecoveryCnt=0, smbus0_sdaFailedCnt=0, smbus0_startBusyCnt=0; ++static u32 smbus1_sdaRecoveryCnt=0, smbus1_sdaFailedCnt=0, smbus1_startBusyCnt=0; ++ ++/* ++ * Function to recover SMB hangs caused stuck master START_BUSY. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_startbusy_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ int rc = -1; ++ unsigned int recoveryCnt; ++ ++ if (dev->adapter.nr == 0) ++ recoveryCnt = ++smbus0_startBusyCnt; ++ else ++ recoveryCnt = ++smbus1_startBusyCnt; ++ ++ dev_info(dev->dev, "START_BUSY recovery #%d \n", recoveryCnt); ++ ++ /* reset the SMBus block, wait a minimum of 50 uSecs and then re-initialize */ ++ writel(CCB_SMB_CFG_RST_MASK, dev->base + CCB_SMB_CFG_REG); ++ udelay(60); ++ ++ if (iproc_smbus_block_init(dev) == 0) ++ rc = 0; ++ ++ return rc; ++} ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device holding SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++ ++static int iproc_smb_sda_low_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, cfgReg, cfgSave, recoveryCnt, failedCnt, i; ++ int rc = -1; ++ ++ /* enable bit-bang */ ++ cfgSave = readl(dev->base + CCB_SMB_CFG_REG); ++ cfgReg = cfgSave; ++ cfgReg |= CCB_SMB_CFG_BITBANGEN_MASK; ++ writel(cfgReg, dev->base + CCB_SMB_CFG_REG); ++ udelay(50); ++ ++ /* start with clock and SDA set high */ ++ bbReg = readl(dev->base + CCB_SMB_BITBANGCTL_REG); ++ bbReg |= (CCB_SMB_SMBCLKOUTEN_MASK | CCB_SMB_SMBDATAOUTEN_MASK); ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(5); /* should be sufficient for 100 KHz bus */ ++ ++ /* set up to toggle the clock line with SDA out held high for 9 cycles */ ++ for (i = 0; i < 18; i++) { ++ /* toggle CLK out */ ++ if ( (bbReg & CCB_SMB_SMBCLKOUTEN_MASK) == 0 ) ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ else ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(5); ++ } ++ ++ /* check bit 29 -- SMBDAT_IN and make sure SDA not being held low any more */ ++ for (i = 0; i < 10; i++) { ++ bbReg = readl(dev->base + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= CCB_SMB_SMBDATAIN_MASK; ++ if (bbReg) ++ break; ++ udelay(1); ++ } ++ ++ if (bbReg == 0) { ++ /* SDA is still low */ ++ if (dev->adapter.nr == 0) ++ failedCnt = ++smbus0_sdaFailedCnt; ++ else ++ failedCnt = ++smbus1_sdaFailedCnt; ++ ++ dev_info(dev->dev, "SDA release #%d FAILED.\n", failedCnt); ++ } else { ++ if (dev->adapter.nr == 0) ++ recoveryCnt = ++smbus0_sdaRecoveryCnt; ++ else ++ recoveryCnt = ++smbus1_sdaRecoveryCnt; ++ ++ dev_info(dev->dev, "SDA release #%d SUCCESS.\n", recoveryCnt); ++ rc = 0; ++ } ++ ++ /* manually issue a stop by transitioning SDA from low to high with clock held high */ ++ bbReg = readl(dev->base + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(2); ++ ++ bbReg &= ~CCB_SMB_SMBDATAOUTEN_MASK; /* drop SDA low */ ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(2); ++ ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(5); ++ ++ bbReg |= CCB_SMB_SMBDATAOUTEN_MASK; /* pull SDA high */ ++ writel(bbReg, dev->base + CCB_SMB_BITBANGCTL_REG); ++ udelay(2); ++ ++ /* disable bit-bang and then re-enable the SMB with the saved configuration */ ++ cfgReg = readl(dev->base + CCB_SMB_CFG_REG); ++ cfgReg &= ~CCB_SMB_CFG_BITBANGEN_MASK; ++ writel(cfgReg, dev->base + CCB_SMB_CFG_REG); ++ udelay(10); ++ ++ writel(cfgSave, dev->base + CCB_SMB_CFG_REG); ++ ++ return rc; ++} ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device hold SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_timeout_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, mCmdReg; ++ int rc = -1; ++ ++ /* read bit-bang control. If SDA low, attempt SDA release recovery */ ++ bbReg = readl(dev->base + CCB_SMB_BITBANGCTL_REG); ++ ++ if ((bbReg & CCB_SMB_SMBDATAIN_MASK) == 0) ++ if (iproc_smb_sda_low_recovery(dev) == 0) ++ rc = 0; ++ ++ /* regardless of whether there was an SDA hang or not, see if START_BUSY stuck high */ ++ mCmdReg = readl( dev->base + CCB_SMB_MSTRCMD_REG ); ++ if (mCmdReg & CCB_SMB_MSTRSTARTBUSYCMD_MASK) ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) == 0) ++ rc = 0; ++ ++ return rc; ++} ++ ++/* ++ * Copy data to SMBus's Tx FIFO. Valid for write transactions only ++ * ++ * base_addr: Mapped address of this SMBus instance ++ * dev_addr: SMBus device address. Assuming 7-bit addresses initially ++ * info: Data to copy in to Tx FIFO. For read commands, the size should be ++ * set to zero by the caller ++ * ++ */ ++static void iproc_smb_write_trans_data(void __iomem *base_addr, ++ unsigned short dev_addr, ++ struct iproc_xact_info *info) ++{ ++ unsigned int regval; ++ unsigned int i; ++ unsigned int num_data_bytes = 0; ++ ++ /* Write SMBus device address first */ ++ /* We are assuming 7-bit addresses for now. For 10-bit addresses, ++ * we may have one more write to send the upper 3 bits of 10-bit addr ++ */ ++ writel(dev_addr, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ ++ /* If the protocol needs command code, copy it */ ++ if (info->cmd_valid == true) ++ writel(info->command, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ ++ /* ++ * Depending on the SMBus protocol, we need to write additional ++ * transaction data into Tx FIFO. ++ * Refer to section 5.5 of SMBus spec for sequence for a transaction ++ */ ++ switch (info->smb_proto) { ++ case SMBUS_PROT_RECV_BYTE: ++ /* No additional data to be written */ ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_SEND_BYTE: ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_RD_BYTE: ++ case SMBUS_PROT_RD_WORD: ++ case SMBUS_PROT_BLK_RD: ++ /* Write slave address with R/W~ set (bit #0) */ ++ writel(dev_addr | 0x1, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_WR_BYTE: ++ case SMBUS_PROT_WR_WORD: ++ /* No additional bytes to be written */ ++ /* Data portion is written in the 'for' loop below */ ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_BLK_WR: ++ /* 3rd byte is byte count */ ++ writel(info->size, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: ++ /* Write byte count */ ++ writel(info->size, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ num_data_bytes = info->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Copy actual data from caller */ ++ for (i = 0; num_data_bytes; --num_data_bytes, i++) { ++ /* For the last byte, set MASTER_WR_STATUS bit. For block rd/wr process ++ * call, we need to program slave addr after copying data byte(s), so ++ * master status bit is set later, after the loop ++ */ ++ if ((num_data_bytes == 1) && ++ (info->smb_proto != SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) ++ regval = info->data[i] | CCB_SMB_MSTRWRSTS_MASK; ++ else ++ regval = info->data[i]; ++ ++ writel(regval, base_addr + CCB_SMB_MSTRDATAWR_REG); ++ } ++ ++ if (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL) ++ /* Write device address needed during repeat start condition */ ++ writel(CCB_SMB_MSTRWRSTS_MASK | dev_addr | 0x1, ++ base_addr + CCB_SMB_MSTRDATAWR_REG); ++ ++ return; ++} ++ ++static int iproc_smb_data_send(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ if (rc < 0) { ++ dev_err(dev->dev, "Send: bus is busy, attempt recovery \n"); ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) ++ return rc; ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ /* Enable start_busy interrupt */ ++ regval = readl(dev->base + CCB_SMB_EVTEN_REG); ++ regval |= CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ writel(regval, dev->base + CCB_SMB_EVTEN_REG); ++ /* Mark as incomplete before sending the data */ ++ reinit_completion(&dev->ses_done); ++ } ++ ++ /* Write transaction bytes to Tx FIFO */ ++ iproc_smb_write_trans_data(dev->base, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and ++ * set start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK; ++ writel(regval, dev->base + CCB_SMB_MSTRCMD_REG); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ /* ++ * Block waiting for the transaction to finish. When finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, ++ XACT_TIMEOUT); ++ /* Disable start_busy interrupt */ ++ regval = readl(dev->base + CCB_SMB_EVTEN_REG); ++ regval &= ~CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ writel(regval, dev->base + CCB_SMB_EVTEN_REG); ++ ++ if (time_left == 0) { ++ dev_info(dev->dev, "Send: timeout accessing device"); ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if (rc != 0) ++ return -ETIMEDOUT; ++ else ++ return -ECOMM; ++ } ++ } ++ ++ regval = readl(dev->base + CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++ /* We can flush Tx FIFO here */ ++ dev_err(dev->dev, "Send: Error in transaction\n"); ++ return -EREMOTEIO; ++ } ++ } ++ ++ return 0; ++} ++ ++static int iproc_smb_data_recv(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info, ++ unsigned int *num_bytes_read) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ dev_err(dev->dev, "Receive: bus is busy, attempt recovery \n"); ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) ++ return rc; ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ /* Enable start_busy interrupt */ ++ regval = readl(dev->base + CCB_SMB_EVTEN_REG); ++ ++ /* Set Rx_event_en bit for notification of reception event */ ++ regval |= (CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ writel(regval, dev->base + CCB_SMB_EVTEN_REG); ++ ++ /* Mark as incomplete before sending the data */ ++ reinit_completion(&dev->ses_done); ++ } ++ ++ /* Program all transaction bytes into master Tx FIFO */ ++ iproc_smb_write_trans_data(dev->base, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; ++ writel(regval, dev->base + CCB_SMB_MSTRCMD_REG); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ /* ++ * Block waiting for the transaction to finish. When finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, ++ XACT_TIMEOUT); ++ ++ /* Disable start_busy and rx_event interrupts */ ++ regval = readl(dev->base + CCB_SMB_EVTEN_REG); ++ regval &= ~(CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ writel(regval, dev->base + CCB_SMB_EVTEN_REG); ++ ++ if (time_left == 0) { ++ dev_err(dev->dev, "Receive: timeout accessing device\n"); ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if (rc != 0) ++ return -ETIMEDOUT; ++ else ++ return -ECOMM; ++ } ++ } ++ ++ regval = readl(dev->base + CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++ /* We can flush Tx FIFO here */ ++ dev_info(dev->dev, "Error in transaction\n"); ++ return -EREMOTEIO; ++ } ++ } ++ ++ /* In the isr we will read the received byte, and also deal with ++ * rx fifo full event. The above check is for timeout error. If needed ++ * we may move it to rx isr ++ */ ++ ++ /* For block read, protocol (hw) returns byte count, as the first byte */ ++ if ((info->smb_proto == SMBUS_PROT_BLK_RD) || ++ (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ int i, adj; ++ ++ /* Read received byte(s) */ ++ regval = readl(dev->base + CCB_SMB_MSTRDATARD_REG); ++ *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ adj = 0; ++ ++ /* SMBUS spec ver. 3 (2015) extends max block transfer byte count from 32 to 256 */ ++ /* Use SMB_MAX_DATA_SIZE (according to HW FIFO) instead of I2C_SMBUS_BLOCK_MAX (defined in Linux)*/ ++ /* ++ * Current SMBUS HW FIFO length is 64B. For block write xfer, ++ * the first three FIFO entries are for slave adress, register ofFset, ++ * and length count. ++ */ ++ for (i = 0; (i < *num_bytes_read) && (i < (SMB_MAX_DATA_SIZE - adj)); i++) { ++ /* Read Rx FIFO for data bytes */ ++ regval = readl(dev->base + CCB_SMB_MSTRDATARD_REG); ++ info->data[i + adj] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ } ++ ++ *num_bytes_read = i + adj; ++ } ++ else { ++ regval = readl(dev->base + CCB_SMB_MSTRDATARD_REG); ++ *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; ++ *num_bytes_read = 1; ++ if (info->smb_proto == SMBUS_PROT_RD_WORD) { ++ /* Read Rx FIFO for data bytes */ ++ regval = readl(dev->base + CCB_SMB_MSTRDATARD_REG); ++ info->data[1] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ *num_bytes_read = 2; ++ } ++ } ++ ++ return 0; ++} ++ ++static int iproc_smb_xfer(struct i2c_adapter *i2c_adap, u16 addr, ++ unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data *data) ++{ ++ int rc = 0; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(i2c_adap); ++ struct iproc_xact_info info; ++ unsigned int num_bytes_read = 0; ++ int smb_xfer_size; ++ ++ down(&dev->xfer_lock); ++ ++ addr <<= 1; ++ ++ switch (size /* protocol */) { ++ case I2C_SMBUS_BYTE: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ if (read_write == I2C_SMBUS_WRITE) ++ info.data = &command; ++ else ++ info.data = &data->byte; ++ info.size = 1; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ addr |= 0x1; /* Read operation */ ++ info.smb_proto = SMBUS_PROT_RECV_BYTE; ++ info.data = &data->byte; ++ } ++ else { ++ info.smb_proto = SMBUS_PROT_SEND_BYTE; ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->byte; ++ info.size = 1; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) ++ info.smb_proto = SMBUS_PROT_RD_BYTE; ++ else ++ info.smb_proto = SMBUS_PROT_WR_BYTE; ++ break; ++ ++ case I2C_SMBUS_WORD_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = (unsigned char *)(&data->word); ++ info.size = 2; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) ++ info.smb_proto = SMBUS_PROT_RD_WORD; ++ else ++ info.smb_proto = SMBUS_PROT_WR_WORD; ++ break; ++ ++ case I2C_SMBUS_BLOCK_DATA: ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ info.smb_proto = SMBUS_PROT_BLK_RD; ++ /* Refer to RD_BYTE_COUNT in reg 0x30 about 'block read' ++ * If '0', protocol(hw) returns data byte count as part of ++ * response. ++ */ ++ info.size = 0; ++ } ++ else { ++ info.smb_proto = SMBUS_PROT_BLK_WR; ++ /* i2c-core passes the length in this field */ ++ info.size = data->block[0]; ++ } ++ break; ++ ++ case I2C_SMBUS_BLOCK_PROC_CALL: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ info.size = data->block[0]; ++ info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; ++ break; ++ ++ default: ++ dev_err(dev->dev, "Unsupported transaction\n"); ++ up(&dev->xfer_lock); ++ return -EINVAL; ++ } ++ ++ /* Handle large packet by spliting into SMB_MAX_DATA_SIZE packet */ ++ smb_xfer_size = (int)info.size; ++ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || ++ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) ++ data->block[0] = 0; ++ ++ while (smb_xfer_size) { ++ if (info.size >= SMB_MAX_DATA_SIZE) ++ info.size = SMB_MAX_DATA_SIZE; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ /* Refer to i2c_smbus_read_byte for params passed. */ ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, ++ &num_bytes_read); ++ /* if failed due to bus hang, but recovered, retry once */ ++ if (rc == -ECOMM) ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, ++ &num_bytes_read); ++ /* pass the actual amount of data sent by slave */ ++ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || ++ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) ++ if (rc == 0) ++ data->block[0] += num_bytes_read; ++ } else { ++ /* Refer to i2c_smbus_write_byte params passed. */ ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ /* if failed due to bus hang, but recovered, retry */ ++ if (rc == -ECOMM) ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ } ++ ++ if (rc < 0) { ++ dev_info(dev->dev, "%s error accessing\n", ++ (read_write == I2C_SMBUS_READ) ? "Read" : "Write"); ++ up(&dev->xfer_lock); ++ return -EREMOTEIO; ++ } ++ if (info.size == SMB_MAX_DATA_SIZE) { ++ smb_xfer_size -= SMB_MAX_DATA_SIZE; ++ info.size = smb_xfer_size; ++ info.data += SMB_MAX_DATA_SIZE; ++ /* Adjust I2c device register offset */ ++ info.command += SMB_MAX_DATA_SIZE; ++ } else { ++ break; ++ } ++ } ++ ++ msleep(1); ++ up(&dev->xfer_lock); ++ ++ return (rc); ++} ++ ++static int iproc_intr_enable(struct iproc_smb_drv_int_data *dev, u32 bmap) ++{ ++ void __iomem *base_addr = dev->base; ++ unsigned int regval; ++ ++ regval = readl(base_addr + CCB_SMB_EVTEN_REG); ++ regval |= bmap; ++ writel(regval, base_addr + CCB_SMB_EVTEN_REG); ++ ++ /* ++ * Store all interrupts enabled so far. Note bmap can have only ++ * 'incremental' set of events ++ */ ++ dev->evt_enable_bmap = regval; ++ ++ return 0; ++} ++ ++static int iproc_intr_disable(struct iproc_smb_drv_int_data *dev, u32 bmap) ++{ ++ void __iomem *base_addr = dev->base; ++ unsigned int regval; ++ ++ regval = readl(base_addr + CCB_SMB_EVTEN_REG); ++ regval &= ~bmap; ++ writel(regval, base_addr + CCB_SMB_EVTEN_REG); ++ ++ dev->evt_enable_bmap = regval; ++ ++ return 0; ++} ++ ++/* Verify this sequence with hw engg */ ++static int iproc_smbus_block_deinit(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ int rc; ++ ++ /* Disable all interrupts */ ++ regval = 0x0; ++ ++ writel(regval, dev->base + CCB_SMB_EVTEN_REG); ++ ++ /* Check if a transaction is in progress */ ++ rc = iproc_smb_startbusy_wait(dev); ++ if (rc < 0) { ++ dev_err(dev->dev, "A transaction is still in progress"); ++ /* Wait for some time */ ++ udelay(100); ++ } ++ ++ /* Disable SMBus block */ ++ regval = readl(dev->base + CCB_SMB_CFG_REG); ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ writel(regval, dev->base + CCB_SMB_CFG_REG); ++ ++ /* Wait for some time */ ++ udelay(100); ++ ++ /* Put the block under reset. Note the RESET bit in reg 0x0 is ++ * self clearing ++ */ ++ regval = CCB_SMB_CFG_RST_MASK; ++ writel(regval, dev->base + CCB_SMB_CFG_REG); ++ ++ return 0; ++} ++ ++static u32 iproc_smb_funcs(struct i2c_adapter *adapter) ++{ ++ /* I2C_FUNC_SMBUS_I2C_BLOCK */ ++ return (I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA); ++} ++ ++static struct i2c_algorithm iproc_smb_algorithm = { ++ /*.name = "iproc-smb", */ ++ .smbus_xfer = iproc_smb_xfer, ++ .master_xfer = NULL, ++ .functionality = iproc_smb_funcs, ++}; ++ ++static int iproc_smb_probe(struct platform_device *pdev) ++{ ++ int rc=0, irq; ++ struct iproc_smb_drv_int_data *dev; ++ struct i2c_adapter *adap; ++ struct resource *res; ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->dev = &pdev->dev; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ dev->base = devm_ioremap_resource(dev->dev, res); ++ if (IS_ERR(dev->base)) ++ return PTR_ERR(dev->base); ++ ++ /* Get the interrupt number */ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev->dev, "no irq resource\n"); ++ return irq; ++ } ++ ++ init_MUTEX(&dev->xfer_lock); ++ init_completion(&dev->ses_done); ++ dev->irq = irq; ++ ++ /* Default value, can be changed after initial testing */ ++ dev->enable_evts = ENABLE_INTR; ++ ++ platform_set_drvdata(pdev, dev); ++ ++ /* ++ * Init internal regs, disable intrs (and then clear intrs), set fifo ++ * thresholds, etc. ++ */ ++ iproc_smbus_block_init(dev); ++ ++ /* Register ISR handler */ ++ rc = devm_request_irq(dev->dev, dev->irq, iproc_smb_isr, 0, ++ pdev->name, dev); ++ if (rc) { ++ dev_err(dev->dev, "unable to request irq %i\n", irq); ++ goto err_smb_deinit; ++ } ++ ++ adap = &dev->adapter; ++ i2c_set_adapdata(adap, dev); ++ adap->owner = THIS_MODULE; ++ adap->class = UINT_MAX; ++ adap->algo = &iproc_smb_algorithm; ++ adap->dev.parent = &pdev->dev; ++ adap->nr = pdev->id; ++ adap->dev.of_node = pdev->dev.of_node; ++ strlcpy(adap->name, "iproc-smbus", sizeof(adap->name)); ++ ++ rc = i2c_add_numbered_adapter(adap); ++ if (rc) ++ goto err_free_irq; ++ ++ /* Turn on default set of interrupts */ ++ /* ++ * For Rx, enable RX fifo full, threshold hit interrupts. Other rx ++ * interrupts will be set in the read/recv transactions, as required ++ * For Tx, enable fifo under run intr. Other intrs will be set in send ++ * write access functions ++ */ ++ iproc_intr_enable(dev, CCB_SMB_MSTRRXFIFOFULLEN_MASK); ++ ++ return 0; ++ ++err_free_irq: ++ free_irq(dev->irq, dev); ++ ++err_smb_deinit: ++ iproc_smbus_block_deinit(dev); ++ platform_set_drvdata(pdev, NULL); ++ ++ dev_err(dev->dev, "probe failed, error=%d", rc); ++ return (rc); ++} ++ ++static int iproc_smb_remove(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ unsigned int regval; ++ ++ /* Disable interrupts. */ ++ /* Verify: Should we wait for any in-progress xact to complete? */ ++ synchronize_irq(dev->irq); ++ iproc_intr_disable(dev, ~0); ++ free_irq(dev->irq, dev); ++ ++ /* Disable SMbus block */ ++ regval = readl(dev->base + CCB_SMB_CFG_REG); ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ writel(regval, dev->base + CCB_SMB_CFG_REG); ++ ++ i2c_del_adapter(&dev->adapter); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ iproc_smbus_block_deinit(dev); ++ ++ devm_iounmap(&pdev->dev, dev->base); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm_iproc_smb_of_match[] = { ++ { .compatible = "brcm,iproc-i2c" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_smb_of_match); ++ ++static struct platform_driver bcm_iproc_smbus_driver = { ++ .driver = { ++ .name = "bcm-iproc-smbus", ++ .of_match_table = bcm_iproc_smb_of_match, ++ }, ++ .probe = iproc_smb_probe, ++ .remove = iproc_smb_remove, ++}; ++module_platform_driver(bcm_iproc_smbus_driver); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("IPROC SMBus Bus Driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +--- a/drivers/mmc/host/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/mmc/host/Kconfig 2018-05-10 11:31:31.593401757 +0800 +@@ -892,6 +892,16 @@ config MMC_SDHCI_BRCMSTB + + If unsure, say Y. + ++config MMC_SDHCI_XGS_IPROC ++ tristate "Broadcom XGS iProc SD/MMC Card Interface support" ++ depends on ARCH_XGS_IPROC ++ depends on MMC_SDHCI_PLTFM ++ select MMC_SDHCI_IO_ACCESSORS ++ default n ++ help ++ This selects the platform Secure Digital Host Controller Interface. ++ If unsure, say N. ++ + config MMC_SDHCI_XENON + tristate "Marvell Xenon eMMC/SD/SDIO SDHCI driver" + depends on MMC_SDHCI_PLTFM +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +--- a/drivers/mmc/host/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/mmc/host/Makefile 2018-05-10 11:31:31.593401757 +0800 +@@ -90,6 +90,7 @@ obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-ms + obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o + obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o + obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o ++obj-$(CONFIG_MMC_SDHCI_XGS_IPROC) += sdhci-bcm-hr3.o + + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/sdhci-bcm-hr3.c b/drivers/mmc/host/sdhci-bcm-hr3.c +--- a/drivers/mmc/host/sdhci-bcm-hr3.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/mmc/host/sdhci-bcm-hr3.c 2018-05-10 11:31:31.609401775 +0800 +@@ -0,0 +1,458 @@ ++/* ++ * drivers/mmc/host/sdhci-bcm-hr3 - Broadcom HR3 SDHCI Platform driver ++ * ++ * Copyright (C) 2014-2016, Broadcom Corporation. All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 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. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sdhci-pltfm.h" ++ ++struct xgs_iproc_sdhci_host { ++ struct device_node *dn; ++ void __iomem *wrap_base; ++ void __iomem *idm_base; ++ u32 shadow_cmd; ++ u32 shadow_blk; ++}; ++ ++static int iproc_top_sdio_config(void); ++ ++static void iproc_sdhci_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ /* WAR for SDIO/GPIO setting might be reset by SDK for HR3. */ ++ struct xgs_iproc_sdhci_host *iproc_host = ++ sdhci_pltfm_priv(sdhci_priv(host)); ++ if (of_device_is_compatible(iproc_host->dn, "brcm,iproc-hr3-sdio")) { ++ if (reg == SDHCI_INT_STATUS) { ++ iproc_top_sdio_config(); ++ } ++ } ++ ++ writel(val, host->ioaddr + reg); ++} ++ ++static inline u32 iproc_sdhci_readl(struct sdhci_host *host, int reg) ++{ ++ return readl(host->ioaddr + reg); ++} ++ ++static void iproc_sdhci_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ struct xgs_iproc_sdhci_host *iproc_host = ++ sdhci_pltfm_priv(sdhci_priv(host)); ++ u32 oldval, newval; ++ u32 word_num = (reg >> 1) & 1; ++ u32 word_shift = word_num * 16; ++ u32 mask = 0xffff << word_shift; ++ ++ if (reg == SDHCI_COMMAND) { ++ if (iproc_host->shadow_blk != 0) { ++ iproc_sdhci_writel(host, iproc_host->shadow_blk, SDHCI_BLOCK_SIZE); ++ iproc_host->shadow_blk = 0; ++ } ++ oldval = iproc_host->shadow_cmd; ++ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { ++ oldval = iproc_host->shadow_blk; ++ } else { ++ oldval = iproc_sdhci_readl(host, reg & ~3); ++ } ++ newval = (oldval & ~mask) | (val << word_shift); ++ ++ if (reg == SDHCI_TRANSFER_MODE) ++ /* Save the transfer mode until the command is issued */ ++ iproc_host->shadow_cmd = newval; ++ else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) ++ /* Save the block info until the command is issued */ ++ iproc_host->shadow_blk = newval; ++ else ++ /* Command or other regular 32-bit write */ ++ iproc_sdhci_writel(host, newval, reg & ~3); ++} ++ ++static u16 iproc_sdhci_readw(struct sdhci_host *host, int reg) ++{ ++ u32 val, word; ++ u32 word_num = (reg >> 1) & 1; ++ u32 word_shift = word_num * 16; ++ ++ val = iproc_sdhci_readl(host, (reg & ~3)); ++ word = (val >> word_shift) & 0xffff; ++ ++ return word; ++} ++ ++static void iproc_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ u32 oldval, newval; ++ u32 byte_num = reg & 3; ++ u32 byte_shift = byte_num * 8; ++ u32 mask = 0xff << byte_shift; ++ ++ oldval = iproc_sdhci_readl(host, reg & ~3); ++ newval = (oldval & ~mask) | (val << byte_shift); ++ ++ iproc_sdhci_writel(host, newval, reg & ~3); ++} ++ ++static u8 iproc_sdhci_readb(struct sdhci_host *host, int reg) ++{ ++ u32 val, byte; ++ u32 byte_num = reg & 3; ++ u32 byte_shift = byte_num * 8; ++ ++ val = iproc_sdhci_readl(host, (reg & ~3)); ++ byte = (val >> byte_shift) & 0xff; ++ ++ return byte; ++} ++ ++static u32 iproc_sdhci_get_max_clock(struct sdhci_host *host) ++{ ++ unsigned long max_clock; ++ ++ max_clock = (host->caps & SDHCI_CLOCK_V3_BASE_MASK) ++ >> SDHCI_CLOCK_BASE_SHIFT; ++ max_clock *= 1000000; ++ ++ return max_clock; ++} ++ ++static u32 iproc_sdhci_get_min_clock(struct sdhci_host *host) ++{ ++ return (host->max_clk / SDHCI_MAX_DIV_SPEC_300); ++} ++ ++static int iproc_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ /* ++ * Tuning is unnecessary for SDR50 and DDR50; moreover, the IPROC platform ++ * doesn't support SDR104, HS200 and HS400 cards. So, we needn't do anything ++ * for tuning. ++ */ ++ return 0; ++} ++ ++static void iproc_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) ++{ ++ /* ++ * WAR that IPROC SD/MMC host need to set the driver strength ++ * to TYPE_A in 3.3v DS/HS mode even if the driver strength is ++ * meaningless for 3.3V signaling. ++ */ ++ if ((host->timing == MMC_TIMING_LEGACY) || ++ (host->timing == MMC_TIMING_MMC_HS) || ++ (host->timing == MMC_TIMING_SD_HS)) ++ host->mmc->ios.drv_type = MMC_SET_DRIVER_TYPE_A; ++ ++ sdhci_set_clock(host, clock); ++} ++ ++static struct sdhci_ops sdhci_iproc_ops = { ++#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS ++ .write_l = iproc_sdhci_writel, ++ .write_w = iproc_sdhci_writew, ++ .write_b = iproc_sdhci_writeb, ++ .read_l = iproc_sdhci_readl, ++ .read_w = iproc_sdhci_readw, ++ .read_b = iproc_sdhci_readb, ++#else ++#error The iproc SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set ++#endif ++ .reset = sdhci_reset, ++ .set_bus_width = sdhci_set_bus_width, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++ .set_clock = iproc_sdhci_set_clock, ++ .get_max_clock = iproc_sdhci_get_max_clock, ++ .get_min_clock = iproc_sdhci_get_min_clock, ++ .platform_execute_tuning = iproc_sdhci_execute_tuning, ++}; ++ ++/* TOP registers */ ++#define TOP_SDIO_MISC_CONTROL 0x0207e500 ++#define TOP_SDIO_MISC_CONTROL__TOP_SDIO_8B_INF 4 ++#define TOP_SDIO_MISC_CONTROL__TOP_SDIO_GPIO_INF_SEL_R 0 ++ ++/* SDIO IDM registers */ ++#define SDIO_IDM0_IO_CONTROL_DIRECT(base) (base + 0x0) ++#define SDIO_IDM0_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE 22 ++#define SDIO_IDM0_IO_CONTROL_DIRECT__FEEDBACK_CLK_EN 21 ++#define SDIO_IDM0_IO_CONTROL_DIRECT__clk_enable 0 ++#define SDIO_IDM0_IDM_RESET_CONTROL(base) (base + 0x3F8) ++ ++/* IPROC WRAP registers */ ++#define IPROC_WRAP_SDIO_CONTROL(base) (base + 0xb0) ++#define IPROC_WRAP_SDIO_CONTROL1(base) (base + 0xb4) ++#define IPROC_WRAP_SDIO_CONTROL2(base) (base + 0xb8) ++#define IPROC_WRAP_SDIO_CONTROL3(base) (base + 0xbc) ++#define IPROC_WRAP_SDIO_CONTROL4(base) (base + 0xc0) ++#define IPROC_WRAP_SDIO_CONTROL5(base) (base + 0xc4) ++#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(base) (base + 0xc8) ++#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_VDDO_18V_FAIL_SOVW 1 ++#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_UHS1_18V_VREG_FAIL 0 ++ ++/* ++ * SDIO_CAPS_L ++ * ++ * Field Bit(s) ++ * =========================== ++ * DDR50 31 ++ * SDR104 30 ++ * SDR50 29 ++ * SLOTTYPE 28:27 ++ * ASYNCHIRQ 26 ++ * SYSBUS64 25 ++ * V18 24 ++ * V3 23 ++ * V33 22 ++ * SUPRSM 21 ++ * SDMA 20 ++ * HSPEED 19 ++ * ADMA2 18 ++ * EXTBUSMED 17 ++ * MAXBLK 16:15 ++ * BCLK 14:7 ++ * TOUT 6 ++ * TOUTFREQ 5:0 ++ */ ++#define SDIO_CAPS_L 0xA17f6470 ++ ++/* ++ * SDIO_CAPS_H ++ * ++ * Field Bit(s) ++ * =========================== ++ * reserved 31:20 ++ * SPIBLOCKMODE 19 ++ * SPIMODE_CAP 18 ++ * CLOCKMULT 17:10 ++ * RETUNE_MODE 9:8 ++ * USETUNE_SDR50 7 ++ * TMRCNT_RETUNE 6:3 ++ * DRVR_TYPED 2 ++ * DRVR_TYPEC 1 ++ * DRVR_TYPEA 0 ++ */ ++#define SDIO_CAPS_H 0x000C000f ++ ++/* ++ * Preset value ++ * ++ * Field Bit(s) ++ * =========================== ++ * Driver Strength 12:11 ++ * Clock Generator 10 ++ * SDCLK Frequeency 9:0 ++ */ ++ ++/* ++ * SDIO_PRESETVAL1 ++ * ++ * Field Bit(s) Description ++ * ============================================================ ++ * DDR50_PRESET 25:13 Preset Value for DDR50 ++ * DEFAULT_PRESET 12:0 Preset Value for Default Speed ++ */ ++#define SDIO_PRESETVAL1 0x01004004 ++ ++/* ++ * SDIO_PRESETVAL2 ++ * ++ * Field Bit(s) Description ++ * ============================================================ ++ * HIGH_SPEED_PRESET 25:13 Preset Value for High Speed ++ * INIT_PRESET 12:0 Preset Value for Initialization ++ */ ++#define SDIO_PRESETVAL2 0x01004100 ++ ++/* ++ * SDIO_PRESETVAL3 ++ * ++ * Field Bit(s) Description ++ * ============================================================ ++ * SDR104_PRESET 25:13 Preset Value for SDR104 ++ * SDR12_PRESET 12:0 Preset Value for SDR12 ++ */ ++#define SDIO_PRESETVAL3 0x00000004 ++ ++/* ++ * SDIO_PRESETVAL4 ++ * ++ * Field Bit(s) Description ++ * ============================================================ ++ * SDR25_PRESET 25:13 Preset Value for SDR25 ++ * SDR50_PRESET 12:0 Preset Value for SDR50 ++ */ ++#define SDIO_PRESETVAL4 0x01005001 ++ ++static int iproc_top_sdio_config(void) ++{ ++ u32 val; ++ ++ val = iproc_cmic_schan_reg32_read(CMIC_BLOCK_TYPE_TOP, TOP_SDIO_MISC_CONTROL); ++ if ((val & 0x1f) != 0x1f) { ++ val |= (0x1 << TOP_SDIO_MISC_CONTROL__TOP_SDIO_8B_INF); ++ val |= (0xf << TOP_SDIO_MISC_CONTROL__TOP_SDIO_GPIO_INF_SEL_R); ++ iproc_cmic_schan_reg32_write(CMIC_BLOCK_TYPE_TOP, TOP_SDIO_MISC_CONTROL, val); ++ } ++ ++ return 0; ++} ++ ++static int iproc_sdio_init(struct xgs_iproc_sdhci_host *iproc_host) ++{ ++ int ret = 0; ++ u32 val; ++ ++ /* Enable SDIO for SDIO/GPIO selection */ ++ ret = iproc_top_sdio_config(); ++ if (ret < 0) ++ return ret; ++ ++ /* Release reset */ ++ writel(0x1, SDIO_IDM0_IDM_RESET_CONTROL(iproc_host->idm_base)); ++ udelay(1000); ++ writel(0x0, SDIO_IDM0_IDM_RESET_CONTROL(iproc_host->idm_base)); ++ ++ /* Enable the SDIO clock */ ++ val = readl(SDIO_IDM0_IO_CONTROL_DIRECT(iproc_host->idm_base)); ++ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE); ++ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__FEEDBACK_CLK_EN); ++ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__clk_enable); ++ writel(val, SDIO_IDM0_IO_CONTROL_DIRECT(iproc_host->idm_base)); ++ ++ /* Set the 1.8v fail control for HR3. ++ * This setting will not impact the uboot SD/MMC driver, since uboot doesn't ++ * support 1.8v. The 1.8v SDIO will be supportted in Kernel. ++ */ ++ val = readl(IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(iproc_host->wrap_base)); ++ val |= (1 << IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_VDDO_18V_FAIL_SOVW); ++ val &= ~(1 << IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_UHS1_18V_VREG_FAIL); ++ writel(val, IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(iproc_host->wrap_base)); ++ ++ /* ++ * Configure SDIO host controller capabilities ++ * (common setting for all SDIO controllers) ++ */ ++ writel(SDIO_CAPS_H, IPROC_WRAP_SDIO_CONTROL(iproc_host->wrap_base)); ++ writel(SDIO_CAPS_L, IPROC_WRAP_SDIO_CONTROL1(iproc_host->wrap_base)); ++ ++ /* ++ * Configure SDIO host controller preset values ++ * (common setting for all SDIO controllers) ++ */ ++ writel(SDIO_PRESETVAL1, IPROC_WRAP_SDIO_CONTROL2(iproc_host->wrap_base)); ++ writel(SDIO_PRESETVAL2, IPROC_WRAP_SDIO_CONTROL3(iproc_host->wrap_base)); ++ writel(SDIO_PRESETVAL3, IPROC_WRAP_SDIO_CONTROL4(iproc_host->wrap_base)); ++ writel(SDIO_PRESETVAL4, IPROC_WRAP_SDIO_CONTROL5(iproc_host->wrap_base)); ++ ++ return 0; ++} ++ ++static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = { ++ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ++ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, ++ /*.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,*/ ++ .ops = &sdhci_iproc_ops, ++}; ++ ++static const struct of_device_id sdhci_xgs_iproc_of_match[] = { ++ { .compatible = "brcm,iproc-hr3-sdio", .data = &sdhci_iproc_pltfm_data }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sdhci_xgs_iproc_of_match); ++ ++static int sdhci_xgs_iproc_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct xgs_iproc_sdhci_host *iproc_host; ++ struct sdhci_host *host; ++ const struct sdhci_pltfm_data *pltfm_data; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct resource *res; ++ int ret = 0; ++ ++ match = of_match_device(sdhci_xgs_iproc_of_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ++ pltfm_data = match->data; ++ host = sdhci_pltfm_init(pdev, pltfm_data, sizeof(*iproc_host)); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ pltfm_host = sdhci_priv(host); ++ iproc_host = sdhci_pltfm_priv(pltfm_host); ++ ++ iproc_host->dn = pdev->dev.of_node; ++ ++ mmc_of_parse(host->mmc); ++ sdhci_get_of_property(pdev); ++ ++ host->hw_name = "XGS-IPROC-SDIO"; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ iproc_host->idm_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(iproc_host->idm_base)) { ++ dev_err(&pdev->dev, "SDIO IDM base ioremap fail\n"); ++ ret = PTR_ERR(iproc_host->idm_base); ++ goto err1; ++ } ++ ++ iproc_host->wrap_base = get_iproc_wrap_ctrl_base(); ++ if (!iproc_host->wrap_base) { ++ dev_err(&pdev->dev, "SDIO wrap ctrl base ioremap fail\n"); ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ ret = iproc_sdio_init(iproc_host); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "SDIO%d init failed\n", pdev->id); ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ ret = sdhci_add_host(host); ++ if (ret) { ++ dev_err(&pdev->dev, "SDIO add host fail\n"); ++ goto err1; ++ } ++ ++err1: ++ sdhci_pltfm_free(pdev); ++ return ret; ++} ++ ++static struct platform_driver sdhci_xgs_iproc_driver = { ++ .probe = sdhci_xgs_iproc_probe, ++ .remove = sdhci_pltfm_unregister, ++ .driver = { ++ .name = "iproc-hr3-sdio", ++ .pm = &sdhci_pltfm_pmops, ++ .of_match_table = sdhci_xgs_iproc_of_match, ++ }, ++}; ++ ++module_platform_driver(sdhci_xgs_iproc_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("SDHCI XGS HR3 driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig +--- a/drivers/mtd/maps/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/mtd/maps/Kconfig 2018-05-10 11:31:31.625401792 +0800 +@@ -419,4 +419,13 @@ config MTD_LATCH_ADDR + + If compiled as a module, it will be called latch-addr-flash. + ++config MTD_NOR_XGS_IPROC ++ bool "Broadcom XGS iProc CFI NOR support" ++ depends on (ARCH_XGS_IPROC || COMPILE_TEST) && MTD_CFI ++ default n ++ help ++ This selects a driver for the iProc NOR support. ++ ++ If unsure, say N. ++ + endmenu +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile +--- a/drivers/mtd/maps/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/mtd/maps/Makefile 2018-05-10 11:31:31.625401792 +0800 +@@ -48,3 +48,4 @@ obj-$(CONFIG_MTD_VMU) += vmu-flash.o + obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o + obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o + obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o ++obj-$(CONFIG_MTD_NOR_XGS_IPROC) += xgs-iproc-flash.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/xgs-iproc-flash.c b/drivers/mtd/maps/xgs-iproc-flash.c +--- a/drivers/mtd/maps/xgs-iproc-flash.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/mtd/maps/xgs-iproc-flash.c 2018-05-10 11:31:31.629401796 +0800 +@@ -0,0 +1,184 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 ++ ++extern void __iomem *get_iproc_dmu_pcu_base(void); ++ ++#define PNOR_DIRECT_CMD_OFFSET 0x10 ++#define PNOR_SET_OPMODE_OFFSET 0X18 ++ ++#define IPROC_STRAP_BOOT_DEV_NAND 1 ++#define IPROC_STRAP_BOOT_DEV_PNOR 4 ++#define ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R 0 ++#define PNOR_set_opmode__set_mw_R 0 ++#define PNOR_direct_cmd__cmd_type_R 21 ++#define IPROC_DMU_STRAPS_OFFSET 0x28 ++#define IPROC_BOOT_STRAP_MASK 0x7 ++ ++struct iproc_nor_mtd { ++ void __iomem *reg_base; ++ void __iomem *reg_strap; ++ struct map_info map; ++ struct mtd_info *mtd; ++}; ++ ++static int xgs_iproc_nor_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ struct iproc_nor_mtd *iproc_data = NULL; ++ struct resource *res; ++ u32 straps, val; ++ u32 strap_boot_dev_shift; ++ void __iomem *reg_base; ++ ++ dev_info(dev, "XGS iProc pnor interface driver\n"); ++ ++ iproc_data = devm_kzalloc(dev, sizeof(*iproc_data), GFP_KERNEL); ++ if (!iproc_data) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, iproc_data); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ iproc_data->reg_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(iproc_data->reg_base)) { ++ dev_err(dev, "can't ioremap pnor base addr\n"); ++ return PTR_ERR(iproc_data->reg_base); ++ } ++ ++ /* Check boot device */ ++ if (of_machine_is_compatible("brcm,hurricane2") || ++ of_machine_is_compatible("brcm,greyhound")) ++ strap_boot_dev_shift = 9; ++ else ++ strap_boot_dev_shift = 10; ++ ++ straps = readl(get_iproc_dmu_pcu_base() + IPROC_DMU_STRAPS_OFFSET); ++ straps = (straps >> strap_boot_dev_shift) & IPROC_BOOT_STRAP_MASK; ++ ++ if (straps == IPROC_STRAP_BOOT_DEV_NAND) { ++ /* If booting from NAND, PNOR cannot be used */ ++ return -ENODEV; ++ } else if (straps != IPROC_STRAP_BOOT_DEV_PNOR) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ iproc_data->reg_strap = devm_ioremap_resource(dev, res); ++ ++ if (!IS_ERR(iproc_data->reg_strap)) { ++ /* Configure controller memory width based on strap */ ++ reg_base = iproc_data->reg_base; ++ straps = readl(iproc_data->reg_strap) & ++ (1 << ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R); ++ ++ if (straps) { ++ /* 16-bit */ ++ val = readl(reg_base + PNOR_SET_OPMODE_OFFSET); ++ val |= (1 << PNOR_set_opmode__set_mw_R); ++ writel(val, reg_base + PNOR_SET_OPMODE_OFFSET); ++ } else { ++ /* 8-bit */ ++ val = readl(reg_base + PNOR_SET_OPMODE_OFFSET); ++ val &= ~(1 << PNOR_set_opmode__set_mw_R); ++ writel(val, reg_base + PNOR_SET_OPMODE_OFFSET); ++ } ++ ++ val = readl(reg_base + PNOR_DIRECT_CMD_OFFSET); ++ val |= (2 << PNOR_direct_cmd__cmd_type_R); ++ writel(val, reg_base + PNOR_DIRECT_CMD_OFFSET); ++ } ++ } ++ ++ mdelay(1); ++ ++ iproc_data->map.bankwidth = 2; ++ iproc_data->map.name = "XGS-IPROC-PNOR-FLASH"; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ iproc_data->map.phys = res->start; ++ iproc_data->map.size = resource_size(res); ++ iproc_data->map.virt = devm_ioremap_resource(dev, res); ++ ++ if (IS_ERR(iproc_data->map.virt)) { ++ dev_err(dev, "can't ioremap pnor flash addr space\n"); ++ return PTR_ERR(iproc_data->map.virt); ++ } ++ ++ simple_map_init(&iproc_data->map); ++ ++ dev_info(dev, "MTD probing 16 bit PNOR FLASH\n"); ++ iproc_data->mtd = do_map_probe("cfi_probe", &iproc_data->map); ++ if (!iproc_data->mtd) { ++ /* Probe for bankwidth 1 */ ++ dev_info(dev, "MTD probing 8 bit PNOR FLASH\n"); ++ iproc_data->map.bankwidth = 1; ++ iproc_data->mtd = do_map_probe("cfi_probe", &iproc_data->map); ++ } ++ ++ if (iproc_data->mtd) { ++ iproc_data->mtd->owner = THIS_MODULE; ++ iproc_data->mtd->dev.parent = dev; ++ mtd_set_of_node(iproc_data->mtd, np); ++ mtd_device_parse_register(iproc_data->mtd, NULL, NULL, NULL, 0); ++ dev_info(dev, "PNOR MTD partitions parsed!\n"); ++ return 0; ++ } ++ ++ dev_warn(dev, "NO PNOR FLASH found!\n"); ++ ++ return -ENXIO; ++} ++ ++static int xgs_iproc_nor_remove(struct platform_device *pdev) ++{ ++ struct iproc_nor_mtd *iproc_data = platform_get_drvdata(pdev); ++ ++ if (!iproc_data) ++ return 0; ++ ++ if (iproc_data->mtd) { ++ mtd_device_unregister(iproc_data->mtd); ++ map_destroy(iproc_data->mtd); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id xgs_iproc_nor_dt_ids[] = { ++ { .compatible = "brcm,iproc-nor", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, xgs_iproc_nor_dt_ids); ++ ++static struct platform_driver xgs_iproc_nor_driver = ++{ ++ .driver = { ++ .name = "xgs-iproc-nor", ++ .owner = THIS_MODULE, ++ .of_match_table = xgs_iproc_nor_dt_ids, ++ }, ++ .probe = xgs_iproc_nor_probe, ++ .remove = xgs_iproc_nor_remove, ++}; ++ ++module_platform_driver(xgs_iproc_nor_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("MTD map driver for XGS iProc PNOR controller"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c +--- a/drivers/mtd/nand/brcmnand/brcmnand.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/mtd/nand/brcmnand/brcmnand.c 2018-05-30 15:50:51.028753148 +0800 +@@ -1220,6 +1220,8 @@ static void brcmnand_send_cmd(struct brc + ctrl->cmd_pending = cmd; + + ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0); ++ /* mark out this warning for XGS iProc */ ++ if (!IS_ENABLED(CONFIG_ARCH_XGS_IPROC)) + WARN_ON(ret); + + mb(); /* flush previous writes */ +@@ -1698,7 +1700,9 @@ static int brcmstb_nand_verify_erased_pa + ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size, + oob, sas, NULL, 0, + chip->ecc.strength); ++ buf += chip->ecc.size; ++ + if (ret < 0) + return ret; + + +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig +--- a/drivers/net/ethernet/broadcom/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/Kconfig 2018-05-10 11:31:31.725401901 +0800 +@@ -171,16 +171,26 @@ config BGMAC_BCMA + config BGMAC_PLATFORM + tristate "Broadcom iProc GBit platform support" + depends on HAS_DMA +- depends on ARCH_BCM_IPROC || COMPILE_TEST ++ depends on ARCH_BCM_IPROC || ARCH_XGS_IPROC || COMPILE_TEST + depends on OF + select BGMAC + select PHYLIB + select FIXED_PHY +- default ARCH_BCM_IPROC ++ default ARCH_BCM_IPROC || ARCH_XGS_IPROC + ---help--- + Say Y here if you want to use the Broadcom iProc Gigabit Ethernet + controller through the generic platform interface + ++config APM ++ tristate "Broadcom iProc AXI Port Macro (APM) support" ++ depends on HAS_DMA ++ depends on ARCH_XGS_IPROC || COMPILE_TEST ++ depends on OF ++ ---help--- ++ This driver supports AXI Port Macro (APM) module. ++ The APM provides a bridge function between a standard Port Macro (PM 4X10) ++ interface and the AXI interconnect (128 bits data bus) for data transfer. ++ + config SYSTEMPORT + tristate "Broadcom SYSTEMPORT internal MAC support" + depends on OF +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile +--- a/drivers/net/ethernet/broadcom/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/Makefile 2018-05-10 11:31:31.725401901 +0800 +@@ -16,3 +16,4 @@ obj-$(CONFIG_BGMAC_BCMA) += bgmac-bcma.o + obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o + obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o + obj-$(CONFIG_BNXT) += bnxt/ ++obj-$(CONFIG_APM) += apm.o apm_ethtool.o pm4x10.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/apm.c b/drivers/net/ethernet/broadcom/apm.c +--- a/drivers/net/ethernet/broadcom/apm.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/apm.c 2018-05-31 15:24:26.196724803 +0800 +@@ -0,0 +1,1414 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 "pm.h" ++#include "apm.h" ++ ++static bool apm_clk_enabled(struct apm *apm); ++ ++static u32 apm_read(struct apm *apm, u16 offset) ++{ ++ return readl(apm->plat.base + offset); ++} ++ ++static void apm_write(struct apm *apm, u16 offset, u32 value) ++{ ++ writel(value, apm->plat.base + offset); ++} ++ ++static u32 apm_idm_read(struct apm *apm, u16 offset) ++{ ++ return readl(apm->plat.idm_base + offset); ++} ++ ++static void apm_idm_write(struct apm *apm, u16 offset, u32 value) ++{ ++ return writel(value, apm->plat.idm_base + offset); ++} ++ ++static bool apm_wait_value(struct apm *apm, u16 reg, u32 mask, ++ u32 value, int timeout) ++{ ++ u32 val; ++ int i; ++ ++ for (i = 0; i < timeout / 10; i++) { ++ val = apm_read(apm, reg); ++ if ((val & mask) == value) ++ return true; ++ udelay(10); ++ } ++ dev_err(apm->dev, "Timeout waiting for reg 0x%X\n", reg); ++ return false; ++} ++ ++/************************************************** ++ * DMA ++ **************************************************/ ++static void apm_dma_tx_reset(struct apm *apm, struct apm_dma_ring *tx_ring) ++{ ++ u32 val; ++ int i; ++ ++ if (!tx_ring->mmio_base) ++ return; ++ ++ /* Suspend DMA TX ring first. ++ * apm_wait_value doesn't support waiting for any of few values, so ++ * implement whole loop here. ++ */ ++ val = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_CTL); ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_CTL, ++ (val | APM_DMA_TX_SUSPEND)); ++ for (i = 0; i < 10000 / 10; i++) { ++ val = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_STATUS); ++ val &= APM_DMA_TX_STAT; ++ if (val == APM_DMA_TX_STAT_DISABLED || ++ val == APM_DMA_TX_STAT_IDLEWAIT || ++ val == APM_DMA_TX_STAT_STOPPED) { ++ i = 0; ++ break; ++ } ++ udelay(10); ++ } ++ if (i) { ++ dev_err(apm->dev, "Timeout suspending DMA TX ring 0x%X (APM_DMA_TX_STAT: 0x%08X)\n", ++ tx_ring->mmio_base, val); ++ } ++ ++ /* Disable the transmit channel */ ++ val = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_CTL); ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_CTL, ++ (val & ~APM_DMA_TX_SUSPEND)); ++ if (!apm_wait_value(apm, tx_ring->mmio_base + APM_DMA_TX_STATUS, ++ APM_DMA_TX_STAT, APM_DMA_TX_STAT_DISABLED, 10000)) { ++ dev_warn(apm->dev, "DMA TX ring 0x%X wasn't disabled on time, waiting additional 300us\n", ++ tx_ring->mmio_base); ++ udelay(300); ++ ++ val = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_STATUS); ++ if ((val & APM_DMA_TX_STAT) != APM_DMA_TX_STAT_DISABLED) ++ dev_err(apm->dev, "Reset of DMA TX ring 0x%X failed\n", ++ tx_ring->mmio_base); ++ } ++} ++ ++static void apm_dma_tx_enable(struct apm *apm, ++ struct apm_dma_ring *tx_ring) ++{ ++ u32 ctl; ++ ++ ctl = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_CTL); ++ if (apm->feature_flags & APM_FEAT_TX_MASK_SETUP) { ++ ctl &= ~APM_DMA_TX_BL_MASK; ++ ctl |= APM_DMA_TX_BL_128 << APM_DMA_TX_BL_SHIFT; ++ ++// ctl &= ~APM_DMA_TX_MR_MASK; ++// ctl |= APM_DMA_TX_MR_2 << APM_DMA_TX_MR_SHIFT; ++ ++ ctl &= ~APM_DMA_TX_PC_MASK; ++ ctl |= APM_DMA_TX_PC_16 << APM_DMA_TX_PC_SHIFT; ++ ++ ctl &= ~APM_DMA_TX_PT_MASK; ++ ctl |= APM_DMA_TX_PT_8 << APM_DMA_TX_PT_SHIFT; ++ } ++ ctl |= APM_DMA_TX_ENABLE; ++// ctl |= APM_DMA_TX_PARITY_DISABLE; ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_CTL, ctl); ++} ++ ++static void ++apm_dma_tx_add_buf(struct apm *apm, struct apm_dma_ring *tx_ring, ++ int i, int len, u32 ctl0) ++{ ++ struct apm_slot_info *slot; ++ struct apm_dma_desc *dma_desc; ++ u32 ctl1; ++ ++ if (i == tx_ring->desc_num - 1) ++ ctl0 |= APM_DESC_CTL0_EOT; ++ ++ ctl1 = len & APM_DESC_CTL1_LEN; ++ ++ slot = &tx_ring->slots[i]; ++ dma_desc = &tx_ring->desc_base[i]; ++ dma_desc->addr_low = cpu_to_le32(lower_32_bits(slot->dma_addr)); ++ dma_desc->addr_high = cpu_to_le32(upper_32_bits(slot->dma_addr)); ++ dma_desc->ctl0 = cpu_to_le32(ctl0); ++ dma_desc->ctl1 = cpu_to_le32(ctl1); ++} ++ ++static netdev_tx_t apm_dma_tx_add(struct apm *apm, ++ struct apm_dma_ring *tx_ring, struct sk_buff *skb) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ struct net_device *net_dev = apm->net_dev; ++ int index = tx_ring->end % tx_ring->desc_num; ++ struct apm_slot_info *slot = &tx_ring->slots[index]; ++ int nr_frags; ++ u32 flags; ++ int i; ++ ++ if (skb->len > APM_DESC_CTL1_LEN) { ++ netdev_err(apm->net_dev, "Too long skb (%d)\n", skb->len); ++ goto err_drop; ++ } ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ skb_checksum_help(skb); ++ ++ nr_frags = skb_shinfo(skb)->nr_frags; ++ ++ /* ring->end - ring->start will return the number of valid slots, ++ * even when tx_ring->end overflows ++ */ ++ if (tx_ring->end - tx_ring->start + nr_frags + 1 >= tx_ring->desc_num) { ++ netdev_err(apm->net_dev, "TX ring is full, queue should be stopped!\n"); ++ netif_stop_queue(net_dev); ++ return NETDEV_TX_BUSY; ++ } ++ ++ slot->dma_addr = dma_map_single(dma_dev, skb->data, skb_headlen(skb), ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dma_dev, slot->dma_addr))) ++ goto err_dma_head; ++ ++ flags = APM_DESC_CTL0_SOF; ++ if (!nr_frags) ++ flags |= APM_DESC_CTL0_EOF | APM_DESC_CTL0_IOC; ++ ++ apm_dma_tx_add_buf(apm, tx_ring, index, skb->len + 4, flags); ++ flags = 0; ++ ++ for (i = 0; i < nr_frags; i++) { ++ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; ++ int len = skb_frag_size(frag); ++ ++ index = (index + 1) % tx_ring->desc_num; ++ slot = &tx_ring->slots[index]; ++ slot->dma_addr = skb_frag_dma_map(dma_dev, frag, 0, ++ len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dma_dev, slot->dma_addr))) ++ goto err_dma; ++ ++ if (i == nr_frags - 1) ++ flags |= APM_DESC_CTL0_EOF | APM_DESC_CTL0_IOC; ++ ++ apm_dma_tx_add_buf(apm, tx_ring, index, len, flags); ++ } ++ ++ slot->skb = skb; ++ tx_ring->end += nr_frags + 1; ++ netdev_sent_queue(net_dev, skb->len); ++ ++ wmb(); ++ ++ /* Increase tx_ring->end to point empty slot. We tell hardware the first ++ * slot it should *not* read. ++ */ ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_INDEX, ++ tx_ring->index_base + ++ (tx_ring->end % tx_ring->desc_num) * ++ sizeof(struct apm_dma_desc)); ++ ++ if (tx_ring->end - tx_ring->start >= tx_ring->desc_num - 8) ++ netif_stop_queue(net_dev); ++ ++ return NETDEV_TX_OK; ++ ++err_dma: ++ dma_unmap_single(dma_dev, slot->dma_addr, skb_headlen(skb), ++ DMA_TO_DEVICE); ++ ++ while (i-- > 0) { ++ int index = (tx_ring->end + i) % tx_ring->desc_num; ++ struct apm_slot_info *slot = &tx_ring->slots[index]; ++ u32 ctl1 = le32_to_cpu(tx_ring->desc_base[index].ctl1); ++ int len = ctl1 & APM_DESC_CTL1_LEN; ++ ++ dma_unmap_page(dma_dev, slot->dma_addr, len, DMA_TO_DEVICE); ++ } ++ ++err_dma_head: ++ netdev_err(apm->net_dev, "Mapping error of skb on TX ring 0x%X\n", ++ tx_ring->mmio_base); ++ ++err_drop: ++ dev_kfree_skb(skb); ++ net_dev->stats.tx_dropped++; ++ net_dev->stats.tx_errors++; ++ return NETDEV_TX_OK; ++} ++ ++/* Free transmitted packets */ ++static void apm_dma_tx_free(struct apm *apm, struct apm_dma_ring *tx_ring) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ int empty_slot; ++ bool freed = false; ++ unsigned bytes_compl = 0, pkts_compl = 0; ++ ++ /* The last slot that hardware didn't consume yet */ ++ empty_slot = apm_read(apm, tx_ring->mmio_base + APM_DMA_TX_STATUS); ++ empty_slot &= APM_DMA_TX_STATDPTR; ++ empty_slot -= tx_ring->index_base; ++ empty_slot &= APM_DMA_TX_STATDPTR; ++ empty_slot /= sizeof(struct apm_dma_desc); ++ ++ while (tx_ring->start != tx_ring->end) { ++ int index = tx_ring->start % tx_ring->desc_num; ++ struct apm_slot_info *slot = &tx_ring->slots[index]; ++ u32 ctl0, ctl1; ++ int len; ++ ++ if (index == empty_slot) ++ break; ++ ++ ctl0 = le32_to_cpu(tx_ring->desc_base[index].ctl0); ++ ctl1 = le32_to_cpu(tx_ring->desc_base[index].ctl1); ++ len = ctl1 & APM_DESC_CTL1_LEN; ++ if (ctl0 & APM_DESC_CTL0_SOF) ++ /* Unmap no longer used buffer */ ++ dma_unmap_single(dma_dev, slot->dma_addr, len, ++ DMA_TO_DEVICE); ++ else ++ dma_unmap_page(dma_dev, slot->dma_addr, len, ++ DMA_TO_DEVICE); ++ ++ if (slot->skb) { ++ apm->net_dev->stats.tx_bytes += slot->skb->len; ++ apm->net_dev->stats.tx_packets++; ++ bytes_compl += slot->skb->len; ++ pkts_compl++; ++ ++ /* Free memory! :) */ ++ dev_kfree_skb(slot->skb); ++ slot->skb = NULL; ++ } ++ ++ slot->dma_addr = 0; ++ tx_ring->start++; ++ freed = true; ++ } ++ ++ if (!pkts_compl) ++ return; ++ ++ netdev_completed_queue(apm->net_dev, pkts_compl, bytes_compl); ++ ++ if (netif_queue_stopped(apm->net_dev)) ++ netif_wake_queue(apm->net_dev); ++} ++ ++static void apm_dma_rx_reset(struct apm *apm, struct apm_dma_ring *rx_ring) ++{ ++ if (!rx_ring->mmio_base) ++ return; ++ ++ apm_write(apm, rx_ring->mmio_base + APM_DMA_RX_CTL, 0); ++ if (!apm_wait_value(apm, ++ rx_ring->mmio_base + APM_DMA_RX_STATUS, ++ APM_DMA_RX_STAT, APM_DMA_RX_STAT_DISABLED, ++ 10000)) ++ dev_err(apm->dev, "Reset of RX ring 0x%X RX failed\n", ++ rx_ring->mmio_base); ++} ++ ++static void apm_dma_rx_enable(struct apm *apm, ++ struct apm_dma_ring *rx_ring) ++{ ++ u32 ctl; ++ ++ ctl = apm_read(apm, rx_ring->mmio_base + APM_DMA_RX_CTL); ++ ++// /* preserve ONLY bits 16-17 from current hardware value */ ++// ctl &= APM_DMA_RX_ADDREXT_MASK; ++ ++ if (apm->feature_flags & APM_FEAT_RX_MASK_SETUP) { ++ ctl &= ~APM_DMA_RX_BL_MASK; ++ ctl |= APM_DMA_RX_BL_128 << APM_DMA_RX_BL_SHIFT; ++ ++ ctl &= ~APM_DMA_RX_PC_MASK; ++ ctl |= APM_DMA_RX_PC_8 << APM_DMA_RX_PC_SHIFT; ++ ++ ctl &= ~APM_DMA_RX_PT_MASK; ++ ctl |= APM_DMA_RX_PT_1 << APM_DMA_RX_PT_SHIFT; ++ } ++ ctl |= APM_DMA_RX_ENABLE; ++// ctl |= APM_DMA_RX_PARITY_DISABLE; ++ ctl |= APM_DMA_RX_OVERFLOW_CONT; ++ ctl |= APM_RX_FRAME_OFFSET << APM_DMA_RX_FRAME_OFFSET_SHIFT; ++ apm_write(apm, rx_ring->mmio_base + APM_DMA_RX_CTL, ctl); ++} ++ ++static int apm_dma_rx_skb_for_slot(struct apm *apm, ++ struct apm_slot_info *slot) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ dma_addr_t dma_addr; ++ struct apm_rx_header *rx; ++ void *buf; ++ ++ /* Alloc skb */ ++ buf = netdev_alloc_frag(APM_RX_ALLOC_SIZE); ++ if (!buf) ++ return -ENOMEM; ++ ++ /* Poison - if everything goes fine, hardware will overwrite it */ ++ rx = buf + APM_RX_BUF_OFFSET; ++ rx->len = cpu_to_le16(0xdead); ++ rx->flags = cpu_to_le16(0xbeef); ++ ++ /* Map skb for the DMA */ ++ dma_addr = dma_map_single(dma_dev, buf + APM_RX_BUF_OFFSET, ++ APM_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ if (dma_mapping_error(dma_dev, dma_addr)) { ++ netdev_err(apm->net_dev, "DMA mapping error\n"); ++ put_page(virt_to_head_page(buf)); ++ return -ENOMEM; ++ } ++ ++ /* Update the slot */ ++ slot->buf = buf; ++ slot->dma_addr = dma_addr; ++ ++ return 0; ++} ++ ++static void apm_dma_rx_update_index(struct apm *apm, ++ struct apm_dma_ring *rx_ring) ++{ ++ dma_wmb(); ++ ++ apm_write(apm, rx_ring->mmio_base + APM_DMA_RX_INDEX, ++ rx_ring->index_base + ++ rx_ring->end * sizeof(struct apm_dma_desc)); ++} ++ ++static void apm_dma_rx_setup_desc(struct apm *apm, ++ struct apm_dma_ring *rx_ring, int index) ++{ ++ struct apm_dma_desc *dma_desc = rx_ring->desc_base + index; ++ u32 ctl0 = 0, ctl1 = 0; ++ ++ if (index == rx_ring->desc_num - 1) ++ ctl0 |= APM_DESC_CTL0_EOT; ++ ctl1 |= APM_RX_BUF_SIZE & APM_DESC_CTL1_LEN; ++ /* Is there any APM device that requires extension? */ ++ /* ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT) & ++ * B43_DMA64_DCTL1_ADDREXT_MASK; ++ */ ++ ++ dma_desc->addr_low = cpu_to_le32(lower_32_bits(rx_ring->slots[index].dma_addr)); ++ dma_desc->addr_high = cpu_to_le32(upper_32_bits(rx_ring->slots[index].dma_addr)); ++ dma_desc->ctl0 = cpu_to_le32(ctl0); ++ dma_desc->ctl1 = cpu_to_le32(ctl1); ++ ++ rx_ring->end = index; ++} ++ ++static void apm_dma_rx_poison_buf(struct device *dma_dev, ++ struct apm_slot_info *slot) ++{ ++ struct apm_rx_header *rx = slot->buf + APM_RX_BUF_OFFSET; ++ ++ dma_sync_single_for_cpu(dma_dev, slot->dma_addr, APM_RX_BUF_SIZE, ++ DMA_FROM_DEVICE); ++ rx->len = cpu_to_le16(0xdead); ++ rx->flags = cpu_to_le16(0xbeef); ++ dma_sync_single_for_device(dma_dev, slot->dma_addr, APM_RX_BUF_SIZE, ++ DMA_FROM_DEVICE); ++} ++ ++static int apm_dma_rx_read(struct apm *apm, struct apm_dma_ring *rx_ring, ++ int weight) ++{ ++ u32 end_slot; ++ int handled = 0; ++ ++ end_slot = apm_read(apm, rx_ring->mmio_base + APM_DMA_RX_STATUS); ++ end_slot &= APM_DMA_RX_STATDPTR; ++ end_slot -= rx_ring->index_base; ++ end_slot &= APM_DMA_RX_STATDPTR; ++ end_slot /= sizeof(struct apm_dma_desc); ++ ++ while (rx_ring->start != end_slot) { ++ struct device *dma_dev = apm->dma_dev; ++ struct apm_slot_info *slot = &rx_ring->slots[rx_ring->start]; ++ struct apm_rx_header *rx = slot->buf + APM_RX_BUF_OFFSET; ++ struct sk_buff *skb; ++ void *buf = slot->buf; ++ dma_addr_t dma_addr = slot->dma_addr; ++ u16 len, flags; ++ ++ do { ++ /* Prepare new skb as replacement */ ++ if (apm_dma_rx_skb_for_slot(apm, slot)) { ++ apm_dma_rx_poison_buf(dma_dev, slot); ++ break; ++ } ++ ++ /* Unmap buffer to make it accessible to the CPU */ ++ dma_unmap_single(dma_dev, dma_addr, ++ APM_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ ++ /* Get info from the header */ ++ len = le16_to_cpu(rx->len); ++ flags = le16_to_cpu(rx->flags); ++ ++ /* Check for poison and drop or pass the packet */ ++ if (len == 0xdead && flags == 0xbeef) { ++ netdev_err(apm->net_dev, "Found poisoned packet at slot %d, DMA issue!\n", ++ rx_ring->start); ++ put_page(virt_to_head_page(buf)); ++ apm->net_dev->stats.rx_errors++; ++ break; ++ } ++ ++ if (len > APM_RX_ALLOC_SIZE) { ++ netdev_err(apm->net_dev, "Found oversized packet at slot %d, DMA issue!\n", ++ rx_ring->start); ++ put_page(virt_to_head_page(buf)); ++ apm->net_dev->stats.rx_length_errors++; ++ apm->net_dev->stats.rx_errors++; ++ break; ++ } ++ ++ /* Omit CRC. */ ++ len -= ETH_FCS_LEN; ++ ++ skb = build_skb(buf, APM_RX_ALLOC_SIZE); ++ if (unlikely(!skb)) { ++ netdev_err(apm->net_dev, "build_skb failed\n"); ++ put_page(virt_to_head_page(buf)); ++ apm->net_dev->stats.rx_errors++; ++ break; ++ } ++ skb_put(skb, APM_RX_FRAME_OFFSET + ++ APM_RX_BUF_OFFSET + len); ++ skb_pull(skb, APM_RX_FRAME_OFFSET + ++ APM_RX_BUF_OFFSET); ++ ++ skb_checksum_none_assert(skb); ++ skb->protocol = eth_type_trans(skb, apm->net_dev); ++ apm->net_dev->stats.rx_bytes += len; ++ apm->net_dev->stats.rx_packets++; ++ napi_gro_receive(&apm->napi, skb); ++ handled++; ++ } while (0); ++ ++ apm_dma_rx_setup_desc(apm, rx_ring, rx_ring->start); ++ ++ if (++rx_ring->start >= rx_ring->desc_num) ++ rx_ring->start = 0; ++ ++ if (handled >= weight) /* Should never be greater */ ++ break; ++ } ++ ++ apm_dma_rx_update_index(apm, rx_ring); ++ ++ return handled; ++} ++ ++/* Does ring support unaligned addressing? */ ++static bool apm_dma_unaligned(struct apm *apm, ++ struct apm_dma_ring *ring, ++ enum apm_dma_ring_type ring_type) ++{ ++ switch (ring_type) { ++ case APM_DMA_RING_TYPE_TX: ++ apm_write(apm, ring->mmio_base + APM_DMA_TX_RINGLO, 0xff0); ++ if (apm_read(apm, ring->mmio_base + APM_DMA_TX_RINGLO)) ++ return true; ++ break; ++ case APM_DMA_RING_TYPE_RX: ++ apm_write(apm, ring->mmio_base + APM_DMA_RX_RINGLO, 0xff0); ++ if (apm_read(apm, ring->mmio_base + APM_DMA_RX_RINGLO)) ++ return true; ++ break; ++ default: ++ return false; ++ } ++ return false; ++} ++ ++static void apm_dma_tx_ring_free(struct apm *apm, ++ struct apm_dma_ring *tx_ring) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ struct apm_dma_desc *dma_desc = tx_ring->desc_base; ++ struct apm_slot_info *slot; ++ int i; ++ ++ for (i = 0; i < tx_ring->desc_num; i++) { ++ int len = dma_desc[i].ctl1 & APM_DESC_CTL1_LEN; ++ ++ slot = &tx_ring->slots[i]; ++ dev_kfree_skb(slot->skb); ++ if (!slot->dma_addr) ++ continue; ++ ++ if (slot->skb) ++ dma_unmap_single(dma_dev, slot->dma_addr, ++ len, DMA_TO_DEVICE); ++ else ++ dma_unmap_page(dma_dev, slot->dma_addr, ++ len, DMA_TO_DEVICE); ++ } ++} ++ ++static void apm_dma_rx_ring_free(struct apm *apm, ++ struct apm_dma_ring *rx_ring) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ struct apm_slot_info *slot; ++ int i; ++ ++ for (i = 0; i < rx_ring->desc_num; i++) { ++ slot = &rx_ring->slots[i]; ++ if (!slot->dma_addr) ++ continue; ++ ++ dma_unmap_single(dma_dev, slot->dma_addr, ++ APM_RX_BUF_SIZE, ++ DMA_FROM_DEVICE); ++ put_page(virt_to_head_page(slot->buf)); ++ slot->dma_addr = 0; ++ } ++} ++ ++static void apm_dma_cleanup(struct apm *apm) ++{ ++ int i; ++ ++ for (i = 0; i < apm->tx_channel; i++) { ++ apm_dma_tx_ring_free(apm, &apm->tx_ring[i]); ++ } ++ ++ apm_dma_rx_ring_free(apm, &apm->rx_ring[0]); ++} ++ ++static void apm_dma_free(struct apm *apm) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ int size; ++ ++ if (apm->desc_buf) { ++ size = (APM_TX_MAX_DESCS + APM_RX_MAX_DESCS) * ++ sizeof(struct apm_dma_desc); ++ dma_free_coherent(dma_dev, size, apm->desc_buf, apm->dma_addr); ++ } ++ ++ if (apm->slot_buf) { ++ kfree(apm->slot_buf); ++ } ++} ++ ++static int apm_dma_alloc(struct apm *apm) ++{ ++ struct device *dma_dev = apm->dma_dev; ++ int size; ++ ++ size = (APM_TX_MAX_DESCS + APM_RX_MAX_DESCS) * ++ sizeof(struct apm_dma_desc); ++ apm->desc_buf = dma_zalloc_coherent(dma_dev, size, ++ &apm->dma_addr, GFP_KERNEL); ++ if (!apm->desc_buf) { ++ dev_err(apm->dev, "Descriptor buffer allocation failed\n"); ++ goto err_dma_free; ++ } ++ memset(apm->desc_buf, 0, size); ++ ++ size = (APM_TX_MAX_DESCS + APM_RX_MAX_DESCS) * ++ sizeof(struct apm_slot_info); ++ apm->slot_buf = kmalloc(size, GFP_KERNEL); ++ if (!apm->slot_buf) { ++ dev_err(apm->dev, "Data buffer allocation failed\n"); ++ goto err_dma_free; ++ } ++ memset(apm->slot_buf, 0, size); ++ return 0; ++ ++err_dma_free: ++ apm_dma_free(apm); ++ return -ENOMEM; ++} ++ ++static int apm_tx_dma_init(struct apm *apm, ++ struct apm_dma_ring *tx_ring, int channel) ++{ ++ const u16 ring_base[] = { APM_DMA_BASE0, APM_DMA_BASE1, ++ APM_DMA_BASE2, APM_DMA_BASE3,}; ++ int desc_num = APM_TX_MAX_DESCS / apm->tx_channel; ++ int offset = channel * desc_num; ++ ++ BUILD_BUG_ON(APM_MAX_TX_RINGS > ARRAY_SIZE(ring_base)); ++ ++ tx_ring->mmio_base = ring_base[channel]; ++ if ((apm->tx_channel == 2) && (channel == 1)) { ++ tx_ring->mmio_base = ring_base[2]; ++ } ++ ++ tx_ring->desc_num = desc_num; ++ tx_ring->desc_base = apm->desc_buf + offset; ++ tx_ring->dma_base = (dma_addr_t)((u32)apm->dma_addr + ++ offset * sizeof(struct apm_dma_desc)); ++ tx_ring->slots = apm->slot_buf + offset; ++ ++ tx_ring->index_base = 0; ++ tx_ring->unaligned = apm_dma_unaligned(apm, ++ tx_ring, APM_DMA_RING_TYPE_TX); ++ if (tx_ring->unaligned) { ++ tx_ring->index_base = lower_32_bits(tx_ring->dma_base); ++ } ++ ++ tx_ring->start = 0; ++ tx_ring->end = 0; /* Points the slot that should *not* be read */ ++ ++ return 0; ++} ++ ++static int apm_rx_dma_init(struct apm *apm, struct apm_dma_ring *rx_ring) ++{ ++ int offset = APM_TX_MAX_DESCS; ++ ++ rx_ring->desc_num = APM_RX_MAX_DESCS; ++ rx_ring->mmio_base = APM_DMA_BASE0; ++ rx_ring->desc_base = apm->desc_buf + offset; ++ rx_ring->dma_base = (dma_addr_t)((u32)apm->dma_addr + ++ offset * sizeof(struct apm_dma_desc)); ++ rx_ring->slots = apm->slot_buf + offset; ++ ++ rx_ring->index_base = 0; ++ rx_ring->unaligned = apm_dma_unaligned(apm, ++ rx_ring, APM_DMA_RING_TYPE_RX); ++ if (rx_ring->unaligned) { ++ rx_ring->index_base = lower_32_bits(rx_ring->dma_base); ++ } ++ ++ rx_ring->start = 0; ++ rx_ring->end = 0; /* Points the slot that should *not* be read */ ++ ++ return 0; ++} ++ ++static int apm_dma_init(struct apm *apm) ++{ ++ struct apm_dma_ring *tx_ring, *rx_ring; ++ int i, err; ++ ++ /* TX DMA init */ ++ for (i = 0; i < apm->tx_channel; i++) { ++ tx_ring = &apm->tx_ring[i]; ++ apm_tx_dma_init(apm, tx_ring, i); ++ ++ if (!tx_ring->unaligned) { ++ apm_dma_tx_enable(apm, tx_ring); ++ } ++ ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_RINGLO, ++ lower_32_bits(tx_ring->dma_base)); ++ apm_write(apm, tx_ring->mmio_base + APM_DMA_TX_RINGHI, ++ upper_32_bits(tx_ring->dma_base)); ++ ++ if (tx_ring->unaligned) { ++ apm_dma_tx_enable(apm, tx_ring); ++ } ++ } ++ ++ /* RX DMA init */ ++ rx_ring = &apm->rx_ring[0]; ++ apm_rx_dma_init(apm, rx_ring); ++ ++ if (!rx_ring->unaligned) { ++ apm_dma_rx_enable(apm, rx_ring); ++ } ++ ++ apm_write(apm, rx_ring->mmio_base + APM_DMA_RX_RINGLO, ++ lower_32_bits(rx_ring->dma_base)); ++ apm_write(apm, rx_ring->mmio_base + APM_DMA_RX_RINGHI, ++ upper_32_bits(rx_ring->dma_base)); ++ ++ if (rx_ring->unaligned) { ++ apm_dma_rx_enable(apm, rx_ring); ++ } ++ ++ for (i = 0; i < rx_ring->desc_num; i++) { ++ err = apm_dma_rx_skb_for_slot(apm, &rx_ring->slots[i]); ++ if (err) { ++ goto error; ++ } ++ apm_dma_rx_setup_desc(apm, rx_ring, i); ++ } ++ apm_dma_rx_update_index(apm, rx_ring); ++ ++ return 0; ++ ++error: ++ apm_dma_cleanup(apm); ++ return err; ++} ++ ++ ++/************************************************** ++ * Chip ops ++ **************************************************/ ++ ++/* TODO: can we just drop @force? Can we don't reset MAC at all if there is ++ * nothing to change? Try if after stabilizng driver. ++ */ ++//static void apm_cmdcfg_maskset(struct apm *apm, u32 mask, u32 set, ++// bool force) ++//{ ++// u32 cmdcfg = apm_read(apm, APM_CMDCFG); ++// u32 new_val = (cmdcfg & mask) | set; ++// u32 cmdcfg_sr; ++// ++// apm_set(apm, APM_CMDCFG, cmdcfg_sr); ++// udelay(2); ++// ++// if (new_val != cmdcfg || force) ++// apm_write(apm, APM_CMDCFG, new_val); ++// ++// apm_mask(apm, APM_CMDCFG, ~cmdcfg_sr); ++// udelay(2); ++//} ++ ++//static void apm_set_rx_mode(struct net_device *net_dev) ++//{ ++// struct apm *apm = netdev_priv(net_dev); ++// ++// if (net_dev->flags & IFF_PROMISC) ++// apm_cmdcfg_maskset(apm, ~0, APM_CMDCFG_PROM, true); ++// else ++// apm_cmdcfg_maskset(apm, ~APM_CMDCFG_PROM, 0, true); ++//} ++ ++static int apm_port_loopback(struct apm *apm, int lb_type) ++{ ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ ++ if (!pm_ops) { ++ dev_err(apm->dev, "(%s) PM does not exist\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (lb_type == APM_LOOPBACK_TYPE_NONE) { ++ pm_ops->port_loopback(apm->land_idx, pmLoopbackMac, 0); ++ pm_ops->port_loopback(apm->land_idx, pmLoopbackPhy, 0); ++ } else if (lb_type == APM_LOOPBACK_TYPE_MAC) { ++ pm_ops->port_loopback(apm->land_idx, pmLoopbackMac, 1); ++ } else if (lb_type == APM_LOOPBACK_TYPE_PHY) { ++ pm_ops->port_loopback(apm->land_idx, pmLoopbackPhy, 1); ++ } ++ return 0; ++} ++ ++static int apm_port_mac_address_set(struct apm *apm, u8 *addr) ++{ ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ ++ if (!pm_ops) { ++ dev_err(apm->dev, "(%s) PM does not exist\n", __func__); ++ return -EINVAL; ++ } ++ ++ return pm_ops->port_mac_addr(apm->land_idx, addr); ++} ++ ++static int apm_port_speed(struct apm *apm) ++{ ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ ++ if (!pm_ops) { ++ dev_err(apm->dev, "(%s) PM does not exist\n", __func__); ++ return -EINVAL; ++ } ++ ++ switch (apm->mac_speed) { ++ case SPEED_10: ++ case SPEED_100: ++ case SPEED_1000: ++ return pm_ops->port_speed(apm->land_idx, apm->mac_speed); ++ default: ++ dev_err(apm->dev, "Unsupported speed: %d\n", apm->mac_speed); ++ } ++ ++ return -EINVAL; ++} ++ ++static int apm_port_enable(struct apm *apm, int enable) ++{ ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ ++ if (!pm_ops) { ++ dev_err(apm->dev, "(%s) PM does not exist\n", __func__); ++ return -EINVAL; ++ } ++ ++ return pm_ops->port_enable(apm->land_idx, enable); ++} ++ ++static int apm_port_stats_clear(struct apm *apm) ++{ ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ ++ if (!pm_ops) { ++ dev_err(apm->dev, "(%s) PM does not exist\n", __func__); ++ return -EINVAL; ++ } ++ ++ return pm_ops->port_stats_clear(apm->land_idx); ++} ++ ++static void apm_chip_init(struct apm *apm) ++{ ++ u32 dev_ctl; ++// u32 cmdcfg; ++ ++ /* 1 interrupt per received frame */ ++ apm_write(apm, APM_INT_RECV_LAZY, 1 << APM_IRL_FC_SHIFT); ++ ++ /* TX QoS mode */ ++ dev_ctl = apm_read(apm, APM_DEV_CTL); ++ if (apm->strict_mode) { ++ dev_ctl |= APM_DC_TSM; ++ } else { ++ dev_ctl &= ~APM_DC_TSM; ++ } ++ apm_write(apm, APM_DEV_CTL, dev_ctl); ++ ++// /* Enable 802.3x tx flow control (honor received PAUSE frames) */ ++// apm_cmdcfg_maskset(apm, ~APM_CMDCFG_RPI, 0, true); ++// ++// /* Activate apm tx & rx */ ++// cmdcfg = apm_read(apm, APM_CMDCFG); ++// cmdcfg |= APM_CMDCFG_TE | APM_CMDCFG_RE; ++// apm_write(apm, APM_CMDCFG, cmdcfg); ++ ++ apm_port_mac_address_set(apm, apm->net_dev->dev_addr); ++ ++ /* Enable the pm port */ ++ apm_port_enable(apm, 1); ++} ++ ++static void apm_chip_reset(struct apm *apm) ++{ ++ int i; ++ ++ if (apm_clk_enabled(apm)) { ++ for (i = 0; i < apm->tx_channel; i++) { ++ apm_dma_tx_reset(apm, &apm->tx_ring[i]); ++ } ++ ++ apm_port_loopback (apm, APM_LOOPBACK_TYPE_NONE); ++ udelay(1); ++ ++ apm_dma_rx_reset(apm, &apm->rx_ring[0]); ++ ++ /* TODO: Clear software multicast filter list */ ++ } ++ ++ /* Disable the pm port */ ++ apm_port_enable(apm, 0); ++ ++ /* Clear the MIB */ ++ apm_port_stats_clear(apm); ++ ++ apm->mac_speed = SPEED_1000; ++ apm->mac_duplex = DUPLEX_FULL; ++ apm_port_speed(apm); ++ ++ if (apm->mii_bus) { ++ apm->mii_bus->reset(apm->mii_bus); ++ } ++ ++ netdev_reset_queue(apm->net_dev); ++} ++ ++ ++static void apm_intrs_on(struct apm *apm) ++{ ++ apm_write(apm, APM_INT_MASK, apm->int_mask); ++} ++ ++static void apm_intrs_off(struct apm *apm) ++{ ++ apm_write(apm, APM_INT_MASK, 0); ++ apm_read(apm, APM_INT_MASK); ++} ++ ++static bool apm_clk_enabled(struct apm *apm) ++{ ++ if ((apm_idm_read(apm, BCMA_IOCTL) & ++ (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) != BCMA_IOCTL_CLK) ++ return false; ++ if (apm_idm_read(apm, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) ++ return false; ++ return true; ++} ++ ++static void apm_clk_enable(struct apm *apm, u32 flags) ++{ ++ apm_idm_write(apm, BCMA_IOCTL, ++ (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags)); ++ apm_idm_read(apm, BCMA_IOCTL); ++ ++ apm_idm_write(apm, BCMA_RESET_CTL, 0); ++ apm_idm_read(apm, BCMA_RESET_CTL); ++ udelay(1); ++ ++ apm_idm_write(apm, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); ++ apm_idm_read(apm, BCMA_IOCTL); ++ udelay(1); ++} ++ ++static irqreturn_t apm_interrupt(int irq, void *dev_id) ++{ ++ struct apm *apm = netdev_priv(dev_id); ++ u32 int_status = apm_read(apm, APM_INT_STATUS); ++ int_status &= apm->int_mask; ++ ++ if (!int_status) ++ return IRQ_NONE; ++ ++ int_status &= ~(APM_IS_TX0 | APM_IS_RX); ++ if (int_status) ++ dev_err(apm->dev, "Unknown IRQs: 0x%08X\n", int_status); ++ ++ /* Disable new interrupts until handling existing ones */ ++ apm_intrs_off(apm); ++ ++ napi_schedule(&apm->napi); ++ ++ return IRQ_HANDLED; ++} ++ ++static int apm_poll(struct napi_struct *napi, int weight) ++{ ++ struct apm *apm = container_of(napi, struct apm, napi); ++ int handled = 0; ++ ++ /* Ack */ ++ apm_write(apm, APM_INT_STATUS, ~0); ++ ++ apm_dma_tx_free(apm, &apm->tx_ring[0]); ++ handled += apm_dma_rx_read(apm, &apm->rx_ring[0], weight); ++ ++ /* Poll again if more events arrived in the meantime */ ++ if (apm_read(apm, APM_INT_STATUS) & (APM_IS_TX0 | APM_IS_RX)) ++ return weight; ++ ++ if (handled < weight) { ++ napi_complete(napi); ++ apm_intrs_on(apm); ++ } ++ ++ return handled; ++} ++ ++/************************************************** ++ * net_device_ops ++ **************************************************/ ++static int apm_open(struct net_device *net_dev) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ int err = 0; ++ ++ apm_chip_reset(apm); ++ ++ err = apm_dma_init(apm); ++ if (err) ++ return err; ++ ++ /* Specs say about reclaiming rings here, but we do that in DMA init */ ++ apm_chip_init(apm); ++ ++ ++ err = request_irq(apm->irq0, apm_interrupt, IRQF_SHARED, ++ KBUILD_MODNAME, net_dev); ++ if (err < 0) { ++ dev_err(apm->dev, "IRQ 0 request error: %d!\n", err); ++ apm_dma_cleanup(apm); ++ return err; ++ } ++ err = request_irq(apm->irq1, apm_interrupt, IRQF_SHARED, ++ KBUILD_MODNAME, net_dev); ++ if (err < 0) { ++ dev_err(apm->dev, "IRQ 1 request error: %d!\n", err); ++ apm_dma_cleanup(apm); ++ return err; ++ } ++ err = request_irq(apm->irq2, apm_interrupt, IRQF_SHARED, ++ KBUILD_MODNAME, net_dev); ++ if (err < 0) { ++ dev_err(apm->dev, "IRQ 2 request error: %d!\n", err); ++ apm_dma_cleanup(apm); ++ return err; ++ } ++ napi_enable(&apm->napi); ++ ++ phy_start(net_dev->phydev); ++ ++ netif_start_queue(net_dev); ++ ++ apm_intrs_on(apm); ++ ++ return 0; ++} ++ ++static int apm_stop(struct net_device *net_dev) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ ++ netif_carrier_off(net_dev); ++ ++ phy_stop(net_dev->phydev); ++ ++ napi_disable(&apm->napi); ++ apm_intrs_off(apm); ++ ++ free_irq(apm->irq0, net_dev); ++ free_irq(apm->irq1, net_dev); ++ free_irq(apm->irq2, net_dev); ++ ++ apm_chip_reset(apm); ++ apm_dma_cleanup(apm); ++ ++ return 0; ++} ++ ++static netdev_tx_t apm_start_xmit(struct sk_buff *skb, ++ struct net_device *net_dev) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ struct apm_dma_ring *tx_ring; ++ u32 channel; ++ ++ /* Remap the priority to 8 priorities first and transmit the packet ++ * to corresponding tx channel. ++ */ ++ channel = (skb->priority % 8) / (8 / apm->tx_channel); ++ channel = 0; // FIXME, GH2 doesn't support multiple channel ++ ++ tx_ring = &apm->tx_ring[channel]; ++ return apm_dma_tx_add(apm, tx_ring, skb); ++} ++ ++static int apm_set_mac_address(struct net_device *net_dev, void *addr) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ int ret; ++ ++ ret = eth_prepare_mac_addr_change(net_dev, addr); ++ if (ret < 0) ++ return ret; ++ apm_port_mac_address_set(apm, (u8 *)addr); ++ eth_commit_mac_addr_change(net_dev, addr); ++ ++ return 0; ++} ++ ++static int apm_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) ++{ ++ if (!netif_running(net_dev)) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(net_dev->phydev, ifr, cmd); ++} ++ ++static const struct net_device_ops apm_netdev_ops = { ++ .ndo_open = apm_open, ++ .ndo_stop = apm_stop, ++ .ndo_start_xmit = apm_start_xmit, ++// .ndo_set_rx_mode = apm_set_rx_mode, ++ .ndo_set_mac_address = apm_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_do_ioctl = apm_ioctl, ++}; ++ ++/************************************************** ++ * MII ++ **************************************************/ ++static void apm_adjust_link(struct net_device *net_dev) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ struct phy_device *phy_dev = net_dev->phydev; ++ bool update = false; ++ ++ if (phy_dev->link) { ++ if (phy_dev->speed != apm->mac_speed) { ++ apm->mac_speed = phy_dev->speed; ++ update = true; ++ } ++ ++ if (phy_dev->duplex != apm->mac_duplex) { ++ apm->mac_duplex = phy_dev->duplex; ++ update = true; ++ } ++ } ++ ++ if (update) { ++ apm_port_speed(apm); ++ phy_print_status(phy_dev); ++ } ++} ++ ++static int apm_enet_probe(struct apm *info) ++{ ++ struct net_device *net_dev; ++ struct apm *apm; ++ struct phy_device *phy_dev; ++ int err; ++ ++ /* Allocation and references */ ++ net_dev = alloc_etherdev(sizeof(*apm)); ++ if (!net_dev) ++ return -ENOMEM; ++ ++ net_dev->netdev_ops = &apm_netdev_ops; ++ ++ apm = netdev_priv(net_dev); ++ memcpy(apm, info, sizeof(*apm)); ++ apm->net_dev = net_dev; ++ net_dev->irq = apm->irq0; /* irq1, irq2 ?? */ ++ SET_NETDEV_DEV(net_dev, apm->dev); ++ ++ if (!is_valid_ether_addr(apm->mac_addr)) { ++ dev_err(apm->dev, "Invalid MAC addr: %pM\n", apm->mac_addr); ++ eth_random_addr(apm->mac_addr); ++ dev_warn(apm->dev, "Using random MAC: %pM\n", apm->mac_addr); ++ } ++ ether_addr_copy(net_dev->dev_addr, apm->mac_addr); ++ ++ /* This (reset &) enable is not preset in specs or reference driver but ++ * Broadcom does it in arch PCI code when enabling fake PCI device. ++ */ ++ apm_clk_enable(apm, 0); ++ ++ apm_chip_reset(apm); ++ ++ err = apm_ethtool_init(net_dev); ++ if (err) { ++ dev_err(apm->dev, "Init ethtool failed\n"); ++ goto err_netdev_free; ++ } ++ ++ err = apm_dma_alloc(apm); ++ if (err) { ++ dev_err(apm->dev, "Unable to alloc memory for DMA\n"); ++ goto err_netdev_free; ++ } ++ ++ apm->int_mask = APM_IS_ERRMASK | APM_IS_RX | APM_IS_TX_MASK; ++ ++ netif_napi_add(net_dev, &apm->napi, apm_poll, APM_WEIGHT); ++ ++ /* phy init; serdes init is already done in pm.c */ ++ phy_dev = of_phy_get_and_connect(apm->net_dev, apm->dev->of_node, ++ &apm_adjust_link); ++ if (!phy_dev) { ++ dev_warn(apm->dev, "No phy available in DT"); ++ } ++ ++ net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ net_dev->hw_features = net_dev->features; ++ net_dev->vlan_features = net_dev->features; ++ ++ err = register_netdev(apm->net_dev); ++ if (err) { ++ dev_err(apm->dev, "Cannot register net device\n"); ++ goto err_phy_disconnect; ++ } ++ ++ netif_carrier_off(net_dev); ++ ++ return 0; ++ ++err_phy_disconnect: ++ phy_disconnect(net_dev->phydev); ++err_netdev_free: ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static void apm_enet_remove(struct apm *apm) ++{ ++ unregister_netdev(apm->net_dev); ++ phy_disconnect(apm->net_dev->phydev); ++ netif_napi_del(&apm->napi); ++ apm_dma_free(apm); ++ free_netdev(apm->net_dev); ++} ++ ++/************************************************** ++ * Platform related code ++ **************************************************/ ++static int apm_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct apm *apm; ++ struct resource *regs; ++ const u8 *mac_addr; ++ const char *pm_type; ++ u32 value; ++ ++ apm = devm_kzalloc(&pdev->dev, sizeof(*apm), GFP_KERNEL); ++ if (!apm) { ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, apm); ++ ++ /* Set the features */ ++ apm->feature_flags |= APM_FEAT_TX_MASK_SETUP; ++ apm->feature_flags |= APM_FEAT_RX_MASK_SETUP; ++ ++ apm->dev = &pdev->dev; ++ apm->dma_dev = &pdev->dev; ++ ++ mac_addr = of_get_mac_address(np); ++ if (mac_addr) ++ ether_addr_copy(apm->mac_addr, mac_addr); ++ else ++ dev_warn(&pdev->dev, "MAC address not present in device tree\n"); ++ ++ apm->irq0 = platform_get_irq(pdev, 0); ++ if (apm->irq0 < 0) { ++ dev_err(&pdev->dev, "Unable to obtain IRQ 0\n"); ++ return apm->irq0; ++ } ++ apm->irq1 = platform_get_irq(pdev, 1); ++ if (apm->irq1 < 0) { ++ dev_err(&pdev->dev, "Unable to obtain IRQ 1\n"); ++ return apm->irq1; ++ } ++ apm->irq2 = platform_get_irq(pdev, 2); ++ if (apm->irq2 < 0) { ++ dev_err(&pdev->dev, "Unable to obtain IRQ 2\n"); ++ return apm->irq2; ++ } ++ ++ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apm_base"); ++ if (!regs) { ++ dev_err(&pdev->dev, "Unable to obtain base resource\n"); ++ return -EINVAL; ++ } ++ ++ apm->plat.base = devm_ioremap_resource(&pdev->dev, regs); ++ if (IS_ERR(apm->plat.base)) ++ return PTR_ERR(apm->plat.base); ++ ++ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base"); ++ if (!regs) { ++ dev_err(&pdev->dev, "Unable to obtain idm resource\n"); ++ return -EINVAL; ++ } ++ ++ apm->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs); ++ if (IS_ERR(apm->plat.idm_base)) { ++ return PTR_ERR(apm->plat.idm_base); ++ } ++ ++ /* Get TX queue number and QoS mode from DTS file */ ++ if (of_property_read_u32(np, "tx-channels", &value)) { ++ /* Set the default TX channel number */ ++ apm->tx_channel = 1; ++ } else { ++ apm->tx_channel = value; ++ if (value == 0) { ++ apm->tx_channel = 1; ++ } else if (value > APM_MAX_TX_RINGS) { ++ apm->tx_channel = APM_MAX_TX_RINGS; ++ } ++ } ++ ++ if (of_property_read_u32(np, "strict-mode", &value)) { ++ /* Set the default strict mode */ ++ apm->strict_mode = true; ++ } else { ++ apm->strict_mode = true; ++ if (value == 0) { ++ apm->strict_mode = false; ++ } ++ } ++ ++ /* Get lane index in PM */ ++ if (of_property_read_u32(np, "land-idx", &value)) { ++ dev_err(&pdev->dev, "Unable to get the PM land index\n"); ++ return -EINVAL; ++ } ++ apm->land_idx = value; ++ ++ /* Get the PM type */ ++ if (of_property_read_string(np, "pm-type", &pm_type)) { ++ dev_err(&pdev->dev, "Unable to get the PM type\n"); ++ return -EINVAL; ++ } ++ ++ if (!strcmp(pm_type, "pm4x10")) { ++ //pm4x10_pm_init(apm->pm_ops); ++ apm->pm_ops = kmalloc(sizeof(struct iproc_pm_ops), GFP_KERNEL); ++ apm->pm_ops->port_enable= pm4x10_pm_xlport_port_config; ++ apm->pm_ops->port_speed = pm4x10_xlport_speed_set; ++ apm->pm_ops->port_loopback = pm4x10_xlport_loopback_set; ++ apm->pm_ops->port_mac_addr = pm4x10_xlport_mac_addr_set; ++ apm->pm_ops->port_stats = pm4x10_xlport_stats_get; ++ apm->pm_ops->port_stats_clear = pm4x10_xlport_mib_reset; ++ pm4x10_pm_init(apm->pm_ops, apm->land_idx); ++ ++ } else { ++ dev_err(&pdev->dev, "Unknown the PM type - %s\n", pm_type); ++ return -EINVAL; ++ } ++ ++ return apm_enet_probe(apm); ++} ++ ++static int apm_remove(struct platform_device *pdev) ++{ ++ struct apm *apm = platform_get_drvdata(pdev); ++ ++ //pm4x10_pm_deinit(apm->pm_ops); ++ kfree(apm->pm_ops); ++ apm->pm_ops = NULL; ++ pm4x10_pm_deinit(apm->pm_ops); ++ apm_enet_remove(apm); ++ ++ return 0; ++} ++ ++static const struct of_device_id apm_of_enet_match[] = { ++ {.compatible = "brcm,xgs-iproc-apm",}, ++ {.compatible = "brcm,xgs-iproc-apm,hx5",}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, apm_of_enet_match); ++ ++static struct platform_driver apm_enet_driver = { ++ .driver = { ++ .name = "apm-enet", ++ .of_match_table = apm_of_enet_match, ++ }, ++ .probe = apm_probe, ++ .remove = apm_remove, ++}; ++ ++module_platform_driver(apm_enet_driver); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/apm.h b/drivers/net/ethernet/broadcom/apm.h +--- a/drivers/net/ethernet/broadcom/apm.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/apm.h 2018-05-30 15:50:51.028753148 +0800 +@@ -0,0 +1,617 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef _APM_H ++#define _APM_H ++ ++#include ++ ++#define APM_DEV_CTL 0x000 ++//#define APM_DC_TSM 0x00000002 ++#define APM_DC_TSM 0x00000001 ++#define APM_DC_ROCS 0x00000002 ++#define APM_DC_CFCO 0x00000004 ++//#define APM_DC_MROR 0x00000010 ++//#define APM_DC_RLSS   0x00000008 ++#define APM_DC_FCM_MASK 0x00000060 ++#define APM_DC_FCM_SHIFT 5 ++//#define APM_DC_NAE 0x00000080 ++//#define APM_DC_TF 0x00000100 ++//#define APM_DC_RDS_MASK 0x00030000 ++//#define APM_DC_RDS_SHIFT 16 ++//#define APM_DC_TDS_MASK 0x000c0000 ++//#define APM_DC_TDS_SHIFT 18 ++ ++#define APM_DEV_STATUS 0x004 /* Configuration of the interface */ ++#define APM_DS_RBF 0x00000001 ++#define APM_DS_RDF 0x00000002 ++#define APM_DS_RIF 0x00000004 ++//#define APM_DS_TBF 0x00000008 ++#define APM_DS_TDF 0x00000010 ++//#define APM_DS_TIF 0x00000020 ++#define APM_DS_PO 0x00000040 ++//#define APM_DS_MM_MASK 0x00000300 /* Mode of the interface */ ++//#define APM_DS_MM_SHIFT 8 ++#define APM_DS_RQS_MASK 0x000f0000 ++#define APM_DS_RQS_SHIFT 16 ++#define APM_DS_TQS_MASK 0x00f00000 ++#define APM_DS_TQS_SHIFT 20 ++#define APM_DS_TOC_MASK 0x3f000000 ++#define APM_DS_TOC_SHIFT 24 ++ ++//#define APM_BIST_STATUS 0x00c ++ ++#define APM_DATA_SWAP_CTL 0x010 ++#define APM_DSC_TBSWD 0x00000001 ++#define APM_DSC_TDS 0x00000002 ++#define APM_DSC_RBSWD 0x00000004 ++#define APM_DSC_RDS 0x00000008 ++ ++#define APM_ERROR_STATIS 0x014 ++#define APM_ES_DESC_READ_ERR_TC0 0x00000001 ++#define APM_ES_DESC_READ_ERR_TC1 0x00000002 ++#define APM_ES_DESC_READ_ERR_TC2 0x00000004 ++#define APM_ES_DESC_READ_ERR_TC3 0x00000008 ++#define APM_ES_DESC_READ_ERR_RC0 0x00000010 ++#define APM_ES_DATA_ERR_TC0 0x00000100 ++#define APM_ES_DATA_ERR_TC1 0x00000200 ++#define APM_ES_DATA_ERR_TC2 0x00000400 ++#define APM_ES_DATA_ERR_TC3 0x00000800 ++#define APM_ES_DATA_ERR_RC0 0x00001000 ++#define APM_ES_DESC_PROT_ERR_TC0 0x00010000 ++#define APM_ES_DESC_PROT_ERR_TC1 0x00020000 ++#define APM_ES_DESC_PROT_ERR_TC2 0x00040000 ++#define APM_ES_DESC_PROT_ERR_TC3 0x00080000 ++#define APM_ES_DESC_PROT_ERR_RC0 0x00100000 ++ ++#define APM_INT_STATUS 0x020 /* Interrupt status */ ++//#define APM_IS_MRO 0x00000001 ++//#define APM_IS_MTO 0x00000002 ++//#define APM_IS_TFD 0x00000004 ++//#define APM_IS_LS 0x00000008 ++//#define APM_IS_MDIO 0x00000010 ++//#define APM_IS_MR 0x00000020 ++//#define APM_IS_MT 0x00000040 ++#define APM_IS_TO 0x00000080 /* Timeout */ ++#define APM_IS_SL_SC 0x00000100 /* Software link status change */ ++#define APM_IS_PM_LS 0x00000200 /* Port Macro link status */ ++#define APM_IS_DESC_ERR 0x00000400 /* Descriptor error */ ++#define APM_IS_DATA_ERR 0x00000800 /* Data error */ ++#define APM_IS_DESC_PROT_ERR 0x00001000 /* Descriptor protocol error */ ++#define APM_IS_RX_DESC_UNDERF 0x00002000 /* Receive descriptor underflow */ ++#define APM_IS_RX_F_OVERF 0x00004000 /* Receive FIFO overflow */ ++//#define APM_IS_TX_F_UNDERF 0x00008000 /* Transmit FIFO underflow */ ++#define APM_IS_RX 0x00010000 /* Interrupt for RX queue 0 */ ++#define APM_IS_RX_INFO_ECC_CORR 0x00100000 /* RXQ info memory corrected error */ ++#define APM_IS_RX_INFO_ECC_UNCORR 0x00200000 /* RXQ info memory uncorrected error */ ++#define APM_IS_AXI_SHARED_ECC_CORR 0x00400000 /* AXI share memory corrected error */ ++#define APM_IS_AXI_SHARED_ECC_UNCORR 0x00800000 /* AXI share memory uncorrected error */ ++#define APM_IS_TX0 0x01000000 /* Interrupt for TX queue 0 */ ++#define APM_IS_TX1 0x02000000 /* Interrupt for TX queue 1 */ ++#define APM_IS_TX2 0x04000000 /* Interrupt for TX queue 2 */ ++#define APM_IS_TX3 0x08000000 /* Interrupt for TX queue 3 */ ++#define APM_IS_ECC_MASK 0x00f00000 ++#define APM_IS_TX_MASK 0x0f000000 ++//#define APM_IS_INTMASK 0x0f01fcff ++#define APM_IS_INTMASK 0x0ff17f80 ++//#define APM_IS_ERRMASK 0x0000fc00 ++#define APM_IS_ERRMASK 0x00007c00 ++ ++#define APM_INT_MASK 0x024 /* Interrupt mask */ ++#define APM_GP_TIMER 0x028 ++ ++#define APM_TXQ_COMMON_CTL 0x040 ++#define APM_TCCTL_FLUSH_CREDIT 0x00000001 ++#define APM_TCCTL_FUNC_MODE_MASK 0x00000006 ++#define APM_TCCTL_FUNC_MODE_SHIFT 1 ++#define APM_FUNC_MODE_SINGLE 0 ++#define APM_FUNC_MODE_DUAL 1 ++#define APM_FUNC_MODE_QUAD 2 ++#define APM_TCCTL_WR_FUNC_MODE 0x00000008 ++#define APM_TCCTL_INTERRUPT_SEL 0x00000010 ++ ++#define APM_TXQ_DATA_TXREQ_CTL0 0x044 ++#define APM_TXQ_DATA_TXREQ_CTL1 0x048 ++#define APM_TXQ_SHARED_BUF_DEPTH0 0x050 ++#define APM_TXQ_SHARED_BUF_DEPTH1 0x054 ++#define APM_RXQ_BUF_DEPTH 0x058 ++#define APM_DMA_TOTAL_OUTSTD_TRANS_LIMIT 0x080 ++#define APM_DMA_RD_PER_ID_OUTSTD_TRANS_LIMIT 0x084 ++#define APM_PKT_DMA_RD_AXI_MAP_CTRL 0x088 ++#define APM_RX_PKT_DMA_WR_AXI_MAP_CTRL 0x08c ++#define APM_TX_PKT_DMA_RD_ARB_CTRL 0x090 ++#define APM_RX_PKT_DMA_RD_ARB_CTRL 0x094 ++#define APM_RX_PKT_DMA_WR_ARB_CTRL 0x098 ++#define APM_RCBUF_MAX_FLIST_ENTRIES 0x09c ++#define APM_STAT_COUNTER_CTL 0x0a0 ++#define APM_STAT_RXQ_TRANSFERRED_PKT_CNT 0x0b0 ++#define APM_STAT_RXQ_COMPLETE_PKT_DROP_CNT 0x0b4 ++#define APM_STAT_RXQ_PARTIAL_PKT_DROP_CNT 0x0b8 ++#define APM_STAT_RXQ_TRUNCATED_PKT_CNT 0x0bc ++#define APM_STAT_TXQ_CH0_GOOD_PKT_CNT 0x0c0 ++#define APM_STAT_TXQ_CH0_ERR_PKT_CNT 0x0c4 ++#define APM_STAT_TXQ_CH1_GOOD_PKT_CNT 0x0c8 ++#define APM_STAT_TXQ_CH1_ERR_PKT_CNT 0x0cc ++#define APM_STAT_TXQ_CH2_GOOD_PKT_CNT 0x0d0 ++#define APM_STAT_TXQ_CH2_ERR_PKT_CNT 0x0d4 ++#define APM_STAT_TXQ_CH3_GOOD_PKT_CNT 0x0d8 ++#define APM_STAT_TXQ_CH3_ERR_PKT_CNT 0x0dc ++#define APM_DBG_TXQ_CH0_STM 0x0e0 ++#define APM_DBG_TXQ_CH1_STM 0x0e4 ++#define APM_DBG_TXQ_CH2_STM 0x0e8 ++#define APM_DBG_TXQ_CH3_STM 0x0ec ++#define APM_DBG_RXQ_STM 0x0f0 ++#define APM_DBG_DMA_HOSTRD_STM 0x0f8 ++#define APM_DBG_DMA_HOSTWR_STM 0x0fc ++ ++#define APM_INT_RECV_LAZY 0x100 ++#define APM_IRL_TO_MASK 0x00ffffff ++#define APM_IRL_TO_SHIFT 0 ++#define APM_IRL_FC_MASK 0xff000000 ++#define APM_IRL_FC_SHIFT 24 /* Shift the number of interrupts triggered per received frame */ ++#define APM_FLOW_CTL_THRESH 0x104 /* Flow control thresholds */ ++#define APM_WRRTHRESH 0x108 ++//#define APM_GMAC_IDLE_CNT_THRESH 0x10c ++//#define APM_PHY_ACCESS 0x180 /* PHY access address */ ++//#define APM_PA_DATA_MASK 0x0000ffff ++//#define APM_PA_ADDR_MASK 0x001f0000 ++//#define APM_PA_ADDR_SHIFT 16 ++//#define APM_PA_REG_MASK 0x1f000000 ++//#define APM_PA_REG_SHIFT 24 ++//#define APM_PA_WRITE 0x20000000 ++//#define APM_PA_START 0x40000000 ++//#define APM_PHY_CNTL 0x188 /* PHY control address */ ++//#define APM_PC_EPA_MASK 0x0000001f ++//#define APM_PC_MCT_MASK 0x007f0000 ++//#define APM_PC_MCT_SHIFT 16 ++//#define APM_PC_MTE 0x00800000 ++//#define APM_TXQ_CTL 0x18c ++//#define APM_TXQ_CTL_DBT_MASK 0x00000fff ++//#define APM_TXQ_CTL_DBT_SHIFT 0 ++#define APM_RXQ_CTL 0x190 ++//#define APM_RXQ_CTL_DBT_MASK 0x00000fff ++#define APM_RXQ_CTL_DBT_MASK 0x00000f7ff ++#define APM_RXQ_CTL_DBT_SHIFT 0 ++//#define APM_RXQ_CTL_PTE 0x00001000 ++//#define APM_RXQ_CTL_MDP_MASK 0x3f000000 ++//#define APM_RXQ_CTL_MDP_SHIFT 24 ++#define APM_RXQ_CTL_RPT_EN 0x40000000 ++ ++//#define APM_GPIO_SELECT 0x194 ++//#define APM_GPIO_OUTPUT_EN 0x198 ++ ++///* For 0x1e0 see BCMA_CLKCTLST. Below are APM specific bits */ ++//#define APM_BCMA_CLKCTLST_MISC_PLL_REQ 0x00000100 ++//#define APM_BCMA_CLKCTLST_MISC_PLL_ST 0x01000000 ++ ++//#define APM_HW_WAR 0x1e4 ++//#define APM_PWR_CTL 0x1e8 ++ ++#define APM_MEM_ECC_CTL 0x1F0 ++#define APM_MEM_ECC_STAT 0x1F4 ++ ++#define APM_DMA_BASE0 0x200 /* Tx and Rx controller */ ++#define APM_DMA_BASE1 0x240 /* Tx controller only */ ++#define APM_DMA_BASE2 0x280 /* Tx controller only */ ++#define APM_DMA_BASE3 0x2C0 /* Tx controller only */ ++ ++//#define APM_TX_GOOD_OCTETS 0x300 ++//#define APM_TX_GOOD_OCTETS_HIGH 0x304 ++//#define APM_TX_GOOD_PKTS 0x308 ++//#define APM_TX_OCTETS 0x30c ++//#define APM_TX_OCTETS_HIGH 0x310 ++//#define APM_TX_PKTS 0x314 ++//#define APM_TX_BROADCAST_PKTS 0x318 ++//#define APM_TX_MULTICAST_PKTS 0x31c ++//#define APM_TX_LEN_64 0x320 ++//#define APM_TX_LEN_65_TO_127 0x324 ++//#define APM_TX_LEN_128_TO_255 0x328 ++//#define APM_TX_LEN_256_TO_511 0x32c ++//#define APM_TX_LEN_512_TO_1023 0x330 ++//#define APM_TX_LEN_1024_TO_1522 0x334 ++//#define APM_TX_LEN_1523_TO_2047 0x338 ++//#define APM_TX_LEN_2048_TO_4095 0x33c ++//#define APM_TX_LEN_4096_TO_8191 0x340 ++//#define APM_TX_LEN_8192_TO_MAX 0x344 ++//#define APM_TX_JABBER_PKTS 0x348 /* Error */ ++//#define APM_TX_OVERSIZE_PKTS 0x34c /* Error */ ++//#define APM_TX_FRAGMENT_PKTS 0x350 ++//#define APM_TX_UNDERRUNS 0x354 /* Error */ ++//#define APM_TX_TOTAL_COLS 0x358 ++//#define APM_TX_SINGLE_COLS 0x35c ++//#define APM_TX_MULTIPLE_COLS 0x360 ++//#define APM_TX_EXCESSIVE_COLS 0x364 /* Error */ ++//#define APM_TX_LATE_COLS 0x368 /* Error */ ++//#define APM_TX_DEFERED 0x36c ++//#define APM_TX_CARRIER_LOST 0x370 ++//#define APM_TX_PAUSE_PKTS 0x374 ++//#define APM_TX_UNI_PKTS 0x378 ++//#define APM_TX_Q0_PKTS 0x37c ++//#define APM_TX_Q0_OCTETS 0x380 ++//#define APM_TX_Q0_OCTETS_HIGH 0x384 ++//#define APM_TX_Q1_PKTS 0x388 ++//#define APM_TX_Q1_OCTETS 0x38c ++//#define APM_TX_Q1_OCTETS_HIGH 0x390 ++//#define APM_TX_Q2_PKTS 0x394 ++//#define APM_TX_Q2_OCTETS 0x398 ++//#define APM_TX_Q2_OCTETS_HIGH 0x39c ++//#define APM_TX_Q3_PKTS 0x3a0 ++//#define APM_TX_Q3_OCTETS 0x3a4 ++//#define APM_TX_Q3_OCTETS_HIGH 0x3a8 ++//#define APM_RX_GOOD_OCTETS 0x3b0 ++//#define APM_RX_GOOD_OCTETS_HIGH 0x3b4 ++//#define APM_RX_GOOD_PKTS 0x3b8 ++//#define APM_RX_OCTETS 0x3bc ++//#define APM_RX_OCTETS_HIGH 0x3c0 ++//#define APM_RX_PKTS 0x3c4 ++//#define APM_RX_BROADCAST_PKTS 0x3c8 ++//#define APM_RX_MULTICAST_PKTS 0x3cc ++//#define APM_RX_LEN_64 0x3d0 ++//#define APM_RX_LEN_65_TO_127 0x3d4 ++//#define APM_RX_LEN_128_TO_255 0x3d8 ++//#define APM_RX_LEN_256_TO_511 0x3dc ++//#define APM_RX_LEN_512_TO_1023 0x3e0 ++//#define APM_RX_LEN_1024_TO_1522 0x3e4 ++//#define APM_RX_LEN_1523_TO_2047 0x3e8 ++//#define APM_RX_LEN_2048_TO_4095 0x3ec ++//#define APM_RX_LEN_4096_TO_8191 0x3f0 ++//#define APM_RX_LEN_8192_TO_MAX 0x3f4 ++//#define APM_RX_JABBER_PKTS 0x3f8 /* Error */ ++//#define APM_RX_OVERSIZE_PKTS 0x3fc /* Error */ ++//#define APM_RX_FRAGMENT_PKTS 0x400 ++//#define APM_RX_MISSED_PKTS 0x404 /* Error */ ++//#define APM_RX_CRC_ALIGN_ERRS 0x408 /* Error */ ++//#define APM_RX_UNDERSIZE 0x40c /* Error */ ++//#define APM_RX_CRC_ERRS 0x410 /* Error */ ++//#define APM_RX_ALIGN_ERRS 0x414 /* Error */ ++//#define APM_RX_SYMBOL_ERRS 0x418 /* Error */ ++//#define APM_RX_PAUSE_PKTS 0x41c ++//#define APM_RX_NONPAUSE_PKTS 0x420 ++//#define APM_RX_SACHANGES 0x424 ++//#define APM_RX_UNI_PKTS 0x428 ++//#define APM_UNIMAC_VERSION 0x800 ++//#define APM_HDBKP_CTL 0x804 ++//#define APM_CMDCFG 0x808 /* Configuration */ ++//#define APM_CMDCFG_TE 0x00000001 /* Set to activate TX */ ++//#define APM_CMDCFG_RE 0x00000002 /* Set to activate RX */ ++//#define APM_CMDCFG_ES_MASK 0x0000000c /* Ethernet speed see gmac_speed */ ++//#define APM_CMDCFG_ES_10 0x00000000 ++//#define APM_CMDCFG_ES_100 0x00000004 ++//#define APM_CMDCFG_ES_1000 0x00000008 ++//#define APM_CMDCFG_ES_2500 0x0000000C ++//#define APM_CMDCFG_PROM 0x00000010 /* Set to activate promiscuous mode */ ++//#define APM_CMDCFG_PAD_EN 0x00000020 ++//#define APM_CMDCFG_CF 0x00000040 ++//#define APM_CMDCFG_PF 0x00000080 ++//#define APM_CMDCFG_RPI 0x00000100 /* Unset to enable 802.3x tx flow control */ ++//#define APM_CMDCFG_TAI 0x00000200 ++//#define APM_CMDCFG_HD 0x00000400 /* Set if in half duplex mode */ ++//#define APM_CMDCFG_HD_SHIFT 10 ++//#define APM_CMDCFG_SR_REV0 0x00000800 /* Set to reset mode, for core rev 0-3 */ ++//#define APM_CMDCFG_SR_REV4 0x00002000 /* Set to reset mode, for core rev >= 4 */ ++//#define APM_CMDCFG_ML 0x00008000 /* Set to activate mac loopback mode */ ++//#define APM_CMDCFG_AE 0x00400000 ++//#define APM_CMDCFG_CFE 0x00800000 ++//#define APM_CMDCFG_NLC 0x01000000 ++//#define APM_CMDCFG_RL 0x02000000 ++//#define APM_CMDCFG_RED 0x04000000 ++//#define APM_CMDCFG_PE 0x08000000 ++//#define APM_CMDCFG_TPI 0x10000000 ++//#define APM_CMDCFG_AT 0x20000000 ++//#define APM_MACADDR_HIGH 0x80c /* High 4 octets of own mac address */ ++//#define APM_MACADDR_LOW 0x810 /* Low 2 octets of own mac address */ ++//#define APM_RXMAX_LENGTH 0x814 /* Max receive frame length with vlan tag */ ++//#define APM_PAUSEQUANTA 0x818 ++//#define APM_MAC_MODE 0x844 ++//#define APM_OUTERTAG 0x848 ++//#define APM_INNERTAG 0x84c ++//#define APM_TXIPG 0x85c ++//#define APM_PAUSE_CTL 0xb30 ++//#define APM_TX_FLUSH 0xb34 ++//#define APM_RX_STATUS 0xb38 ++//#define APM_TX_STATUS 0xb3c ++// ++///* BCMA GMAC core specific IO Control (BCMA_IOCTL) flags */ ++//#define APM_BCMA_IOCTL_SW_CLKEN 0x00000004 /* PHY Clock Enable */ ++//#define APM_BCMA_IOCTL_SW_RESET 0x00000008 /* PHY Reset */ ++// ++///* BCMA GMAC core specific IO status (BCMA_IOST) flags */ ++//#define APM_BCMA_IOST_ATTACHED 0x00000800 ++// ++//#define APM_NUM_MIB_TX_REGS (((APM_TX_Q3_OCTETS_HIGH - APM_TX_GOOD_OCTETS) / 4) + 1) ++//#define APM_NUM_MIB_RX_REGS (((APM_RX_UNI_PKTS - APM_RX_GOOD_OCTETS) / 4) + 1) ++ ++#define APM_DMA_TX_CTL 0x00 ++#define APM_DMA_TX_ENABLE 0x00000001 ++#define APM_DMA_TX_SUSPEND 0x00000002 ++//#define APM_DMA_TX_LOOPBACK 0x00000004 ++//#define APM_DMA_TX_FLUSH 0x00000010 ++//#define APM_DMA_TX_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++//#define APM_DMA_TX_MR_SHIFT 6 ++//#define APM_DMA_TX_MR_1 0 ++//#define APM_DMA_TX_MR_2 1 ++//#define APM_DMA_TX_PARITY_DISABLE 0x00000800 ++#define APM_DMA_TX_SBAI 0x00002000 ++//#define APM_DMA_TX_ADDREXT_MASK 0x00030000 ++//#define APM_DMA_TX_ADDREXT_SHIFT 16 ++#define APM_DMA_TX_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define APM_DMA_TX_BL_SHIFT 18 ++#define APM_DMA_TX_BL_16 0 ++#define APM_DMA_TX_BL_32 1 ++#define APM_DMA_TX_BL_64 2 ++#define APM_DMA_TX_BL_128 3 ++//#define APM_DMA_TX_BL_256 4 ++//#define APM_DMA_TX_BL_512 5 ++//#define APM_DMA_TX_BL_1024 6 ++#define APM_DMA_TX_PC_MASK 0x00E00000 /* Prefetch control */ ++#define APM_DMA_TX_PC_SHIFT 21 ++#define APM_DMA_TX_PC_0 0 ++#define APM_DMA_TX_PC_4 1 ++#define APM_DMA_TX_PC_8 2 ++#define APM_DMA_TX_PC_16 3 ++#define APM_DMA_TX_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define APM_DMA_TX_PT_SHIFT 24 ++#define APM_DMA_TX_PT_1 0 ++#define APM_DMA_TX_PT_2 1 ++#define APM_DMA_TX_PT_4 2 ++#define APM_DMA_TX_PT_8 3 ++ ++#define APM_DMA_TX_INDEX 0x04 ++#define APM_DMA_TX_RINGLO 0x08 ++#define APM_DMA_TX_RINGHI 0x0C ++#define APM_DMA_TX_STATUS 0x10 ++#define APM_DMA_TX_STATDPTR 0x00001FFF ++#define APM_DMA_TX_STAT 0xF0000000 ++#define APM_DMA_TX_STAT_DISABLED 0x00000000 ++#define APM_DMA_TX_STAT_ACTIVE 0x10000000 ++#define APM_DMA_TX_STAT_IDLEWAIT 0x20000000 ++#define APM_DMA_TX_STAT_STOPPED 0x30000000 ++#define APM_DMA_TX_STAT_SUSP 0x40000000 ++#define APM_DMA_TX_ERROR 0x14 ++#define APM_DMA_TX_ERRDPTR 0x0001FFFF ++#define APM_DMA_TX_ERR 0xF0000000 ++#define APM_DMA_TX_ERR_NOERR 0x00000000 ++#define APM_DMA_TX_ERR_PROT 0x10000000 ++//#define APM_DMA_TX_ERR_UNDERRUN 0x20000000 ++#define APM_DMA_TX_ERR_TRANSFER 0x30000000 ++#define APM_DMA_TX_ERR_DESCREAD 0x40000000 ++#define APM_DMA_TX_ERR_CORE 0x50000000 ++ ++#define APM_DMA_RX_CTL 0x20 ++#define APM_DMA_RX_ENABLE 0x00000001 ++#define APM_DMA_RX_FRAME_OFFSET_MASK 0x000000FE ++#define APM_DMA_RX_FRAME_OFFSET_SHIFT 1 ++//#define APM_DMA_RX_DIRECT_FIFO 0x00000100 ++#define APM_DMA_RX_OVERFLOW_CONT 0x00000400 ++//#define APM_DMA_RX_PARITY_DISABLE 0x00000800 ++//#define APM_DMA_RX_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++//#define APM_DMA_RX_MR_SHIFT 6 ++//#define APM_DMA_TX_MR_1 0 ++//#define APM_DMA_TX_MR_2 1 ++//#define APM_DMA_RX_ADDREXT_MASK 0x00030000 ++//#define APM_DMA_RX_ADDREXT_SHIFT 16 ++#define APM_DMA_RX_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define APM_DMA_RX_BL_SHIFT 18 ++#define APM_DMA_RX_BL_16 0 ++#define APM_DMA_RX_BL_32 1 ++#define APM_DMA_RX_BL_64 2 ++#define APM_DMA_RX_BL_128 3 ++//#define APM_DMA_RX_BL_256 4 ++//#define APM_DMA_RX_BL_512 5 ++//#define APM_DMA_RX_BL_1024 6 ++#define APM_DMA_RX_PC_MASK 0x00E00000 /* Prefetch control */ ++#define APM_DMA_RX_PC_SHIFT 21 ++#define APM_DMA_RX_PC_0 0 ++#define APM_DMA_RX_PC_4 1 ++#define APM_DMA_RX_PC_8 2 ++#define APM_DMA_RX_PC_16 3 ++#define APM_DMA_RX_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define APM_DMA_RX_PT_SHIFT 24 ++#define APM_DMA_RX_PT_1 0 ++#define APM_DMA_RX_PT_2 1 ++#define APM_DMA_RX_PT_4 2 ++#define APM_DMA_RX_PT_8 3 ++#define APM_DMA_RX_INDEX 0x24 ++#define APM_DMA_RX_RINGLO 0x28 ++#define APM_DMA_RX_RINGHI 0x2C ++#define APM_DMA_RX_STATUS 0x30 ++#define APM_DMA_RX_STATDPTR 0x00001FFF ++#define APM_DMA_RX_STAT 0xF0000000 ++#define APM_DMA_RX_STAT_DISABLED 0x00000000 ++#define APM_DMA_RX_STAT_ACTIVE 0x10000000 ++#define APM_DMA_RX_STAT_IDLEWAIT 0x20000000 ++#define APM_DMA_RX_STAT_STOPPED 0x30000000 ++//#define APM_DMA_RX_STAT_SUSP 0x40000000 ++#define APM_DMA_RX_ERROR 0x34 ++#define APM_DMA_RX_ERRDPTR 0x0001FFFF ++#define APM_DMA_RX_ERR 0xF0000000 ++#define APM_DMA_RX_ERR_NOERR 0x00000000 ++#define APM_DMA_RX_ERR_PROT 0x10000000 ++#define APM_DMA_RX_ERR_UNDERRUN 0x20000000 ++#define APM_DMA_RX_ERR_TRANSFER 0x30000000 ++#define APM_DMA_RX_ERR_DESCREAD 0x40000000 ++#define APM_DMA_RX_ERR_CORE 0x50000000 ++ ++ ++ ++ ++ ++ ++#define APM_DESC_CTL0_CRC 0x00300000 /* CRC mode */ ++#define APM_DESC_CRC_APPEND 0x00000000 /* CRC append mode */ ++#define APM_DESC_CRC_OVERWRITE 0x00100000 /* CRC overwrite mode */ ++#define APM_DESC_CRC_FORWARD 0x00200000 /* CRC forward mode */ ++#define APM_DESC_CTL0_EOT 0x10000000 /* End of ring */ ++#define APM_DESC_CTL0_IOC 0x20000000 /* IRQ on complete */ ++#define APM_DESC_CTL0_EOF 0x40000000 /* End of frame */ ++#define APM_DESC_CTL0_SOF 0x80000000 /* Start of frame */ ++//#define APM_DESC_CTL1_LEN 0x00001FFF ++#define APM_DESC_CTL1_LEN 0x00007FFF ++ ++//#define APM_PHY_NOREGS BRCM_PSEUDO_PHY_ADDR ++//#define APM_PHY_MASK 0x1F ++ ++#define APM_MAX_TX_RINGS 4 ++#define APM_MAX_RX_RINGS 1 ++#define APM_TX_MAX_DESCS 512 ++#define APM_RX_MAX_DESCS 512 ++ ++#define APM_RX_HEADER_LEN 28 /* Last 24 bytes are unused. Well... */ ++#define APM_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */ ++#define APM_RX_BUF_OFFSET (NET_SKB_PAD + NET_IP_ALIGN - APM_RX_FRAME_OFFSET) ++#define APM_RX_MAX_FRAME_SIZE 1536 /* Copied from b44/tg3 */ ++#define APM_RX_BUF_SIZE (APM_RX_FRAME_OFFSET + APM_RX_MAX_FRAME_SIZE) ++#define APM_RX_ALLOC_SIZE (SKB_DATA_ALIGN(APM_RX_BUF_SIZE + APM_RX_BUF_OFFSET) + \ ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) ++ ++//#define APM_BFL_ENETROBO 0x0010 /* has ephy roboswitch spi */ ++//#define APM_BFL_ENETADM 0x0080 /* has ADMtek switch */ ++//#define APM_BFL_ENETVLAN 0x0100 /* can do vlan */ ++ ++//#define APM_CHIPCTL_1_IF_TYPE_MASK 0x00000030 ++//#define APM_CHIPCTL_1_IF_TYPE_RMII 0x00000000 ++//#define APM_CHIPCTL_1_IF_TYPE_MII 0x00000010 ++//#define APM_CHIPCTL_1_IF_TYPE_RGMII 0x00000020 ++//#define APM_CHIPCTL_1_SW_TYPE_MASK 0x000000C0 ++//#define APM_CHIPCTL_1_SW_TYPE_EPHY 0x00000000 ++//#define APM_CHIPCTL_1_SW_TYPE_EPHYMII 0x00000040 ++//#define APM_CHIPCTL_1_SW_TYPE_EPHYRMII 0x00000080 ++//#define APM_CHIPCTL_1_SW_TYPE_RGMII 0x000000C0 ++//#define APM_CHIPCTL_1_RXC_DLL_BYPASS 0x00010000 ++// ++//#define APM_CHIPCTL_4_IF_TYPE_MASK 0x00003000 ++//#define APM_CHIPCTL_4_IF_TYPE_RMII 0x00000000 ++//#define APM_CHIPCTL_4_IF_TYPE_MII 0x00001000 ++//#define APM_CHIPCTL_4_IF_TYPE_RGMII 0x00002000 ++//#define APM_CHIPCTL_4_SW_TYPE_MASK 0x0000C000 ++//#define APM_CHIPCTL_4_SW_TYPE_EPHY 0x00000000 ++//#define APM_CHIPCTL_4_SW_TYPE_EPHYMII 0x00004000 ++//#define APM_CHIPCTL_4_SW_TYPE_EPHYRMII 0x00008000 ++//#define APM_CHIPCTL_4_SW_TYPE_RGMII 0x0000C000 ++// ++//#define APM_CHIPCTL_7_IF_TYPE_MASK 0x000000C0 ++//#define APM_CHIPCTL_7_IF_TYPE_RMII 0x00000000 ++//#define APM_CHIPCTL_7_IF_TYPE_MII 0x00000040 ++//#define APM_CHIPCTL_7_IF_TYPE_RGMII 0x00000080 ++ ++#define APM_WEIGHT 64 ++#define ETHER_MAX_LEN 1518 ++ ++/* Feature flags */ ++#define APM_FEAT_TX_MASK_SETUP BIT(0) ++#define APM_FEAT_RX_MASK_SETUP BIT(1) ++ ++/* Loopback flags */ ++#define APM_LOOPBACK_TYPE_NONE 0 ++#define APM_LOOPBACK_TYPE_MAC 1 ++#define APM_LOOPBACK_TYPE_PHY 2 ++ ++struct apm_slot_info { ++ union { ++ struct sk_buff *skb; ++ void *buf; ++ }; ++ dma_addr_t dma_addr; ++}; ++ ++struct apm_dma_desc { ++ __le32 ctl0; ++ __le32 ctl1; ++ __le32 addr_low; ++ __le32 addr_high; ++} __packed; ++ ++enum apm_dma_ring_type { ++ APM_DMA_RING_TYPE_TX = 0, ++ APM_DMA_RING_TYPE_RX, ++ APM_DMA_RING_TYPE_NUM ++}; ++ ++/** ++ * apm_dma_ring - contains info about DMA ring (either TX or RX one) ++ * @start: index of the first slot containing data ++ * @end: index of a slot that can *not* be read (yet) ++ * ++ * Be really aware of the specific @end meaning. It's an index of a slot *after* ++ * the one containing data that can be read. If @start equals @end the ring is ++ * empty. ++ */ ++struct apm_dma_ring { ++ u32 start; ++ u32 end; ++ ++ int desc_num; ++ struct apm_dma_desc *desc_base; ++ dma_addr_t dma_base; ++ u32 index_base; /* Used for unaligned rings only, otherwise 0 */ ++ u16 mmio_base; ++ bool unaligned; ++ ++ struct apm_slot_info *slots; ++}; ++ ++ ++struct apm_rx_header { ++ __le16 len; ++ __le16 flags; ++ __le16 pad[12]; ++}; ++ ++struct apm { ++ union { ++ struct { ++ void *base; ++ void *idm_base; ++ } plat; ++ }; ++ ++ struct device *dev; ++ struct device *dma_dev; ++ ++ struct iproc_pm_ops *pm_ops; ++ u8 land_idx; ++ ++ u8 mac_addr[ETH_ALEN]; ++ u32 feature_flags; ++ ++ struct net_device *net_dev; ++ struct napi_struct napi; ++ struct mii_bus *mii_bus; ++ ++ /* DMA */ ++ struct apm_dma_desc *desc_buf; ++ dma_addr_t dma_addr; ++ struct apm_slot_info *slot_buf; ++ ++ struct apm_dma_ring tx_ring[APM_MAX_TX_RINGS]; ++ struct apm_dma_ring rx_ring[APM_MAX_RX_RINGS]; ++ ++ /* QoS */ ++ u8 tx_channel; ++ bool strict_mode; ++ ++ /* Int */ ++ int irq0; ++ int irq1; ++ int irq2; ++ u32 int_mask; ++ ++ /* Current MAC state */ ++ int mac_speed; ++ int mac_duplex; ++ ++ u8 phyaddr; ++ bool loopback; ++}; ++ ++extern int apm_ethtool_init(struct net_device *net_dev); ++#endif /* _APM_H */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/apm_ethtool.c b/drivers/net/ethernet/broadcom/apm_ethtool.c +--- a/drivers/net/ethernet/broadcom/apm_ethtool.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/apm_ethtool.c 2018-05-10 11:31:31.729401905 +0800 +@@ -0,0 +1,227 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pm.h" ++#include "apm.h" ++ ++static const struct { ++ const char name[ETH_GSTRING_LEN]; ++} apm_stat_name[] = { ++ { "rx_frames" }, ++ { "rx_frame_good" }, ++ { "rx_bytes" }, ++ { "rx_frame_64" }, ++ { "rx_frame_127" }, ++ { "rx_frame_255" }, ++ { "rx_frame_511" }, ++ { "rx_frame_1023" }, ++ { "rx_frame_1518" }, ++ { "rx_frame_1522" }, ++ { "rx_frame_jumbo" }, ++ { "rx_frame_unicast" }, ++ { "rx_frame_multicast" }, ++ { "rx_frame_broadcast" }, ++ { "rx_frame_control" }, ++ { "rx_frame_pause" }, ++ { "rx_frame_jabber" }, ++ { "rx_frame_fragment" }, ++ { "rx_frame_vlan" }, ++ { "rx_frame_dvlan" }, ++ { "rx_frame_fcs_error" }, ++ { "rx_frame_unsupport" }, ++ { "rx_frame_wrong_sa" }, ++ { "rx_frame_align_err" }, ++ { "rx_frame_length_err" }, ++ { "rx_frame_oversize" }, ++ { "rx_frame_mtu_err" }, ++ { "rx_frame_truncated_err" }, ++ { "rx_frame_undersize" }, ++ { "tx_frames" }, ++ { "tx_frame_good" }, ++ { "tx_bytes" }, ++ { "tx_frame_64" }, ++ { "tx_frame_127" }, ++ { "tx_frame_255" }, ++ { "tx_frame_511" }, ++ { "tx_frame_1023" }, ++ { "tx_frame_1518" }, ++ { "tx_frame_1522" }, ++ { "tx_frame_jumbo" }, ++ { "tx_frame_unicast" }, ++ { "tx_frame_multicast" }, ++ { "tx_frame_broadcast" }, ++ { "tx_frame_control" }, ++ { "tx_frame_pause" }, ++ { "tx_frame_jabber" }, ++ { "tx_frame_fragment" }, ++ { "tx_frame_vlan" }, ++ { "tx_frame_dvlan" }, ++ { "tx_frame_fcs_error" }, ++ { "tx_frame_oversize" }, ++ { "tx_frame_error" }, ++ { "tx_frame_fifo_underrun" }, ++ { "tx_frame_collision" }, ++}; ++ ++static int apm_get_sset_count(struct net_device *net_dev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return ARRAY_SIZE(apm_stat_name); ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static void apm_get_strings(struct net_device *net_dev, u32 stringset, ++ u8 *data) ++{ ++ if (stringset == ETH_SS_STATS) { ++ memcpy(data, apm_stat_name, sizeof(apm_stat_name)); ++ } ++} ++ ++static void apm_get_ethtool_stats(struct net_device *net_dev, ++ struct ethtool_stats *ss, uint64_t *data) ++{ ++ struct apm *apm = netdev_priv(net_dev); ++ struct iproc_pm_ops *pm_ops = apm->pm_ops; ++ struct iproc_pm_stats stats; ++ int i = 0; ++ ++ if (pm_ops) { ++ pm_ops->port_stats(apm->land_idx, &stats); ++ ++ data[i++] = stats.rx_frames; ++ data[i++] = stats.rx_frame_good; ++ data[i++] = stats.rx_bytes; ++ data[i++] = stats.rx_frame_64; ++ data[i++] = stats.rx_frame_127; ++ data[i++] = stats.rx_frame_255; ++ data[i++] = stats.rx_frame_511; ++ data[i++] = stats.rx_frame_1023; ++ data[i++] = stats.rx_frame_1518; ++ data[i++] = stats.rx_frame_1522; ++ data[i++] = stats.rx_frame_jumbo; ++ data[i++] = stats.rx_frame_unicast; ++ data[i++] = stats.rx_frame_multicast; ++ data[i++] = stats.rx_frame_broadcast; ++ data[i++] = stats.rx_frame_control; ++ data[i++] = stats.rx_frame_pause; ++ data[i++] = stats.rx_frame_jabber; ++ data[i++] = stats.rx_frame_fragment; ++ data[i++] = stats.rx_frame_vlan; ++ data[i++] = stats.rx_frame_dvlan; ++ data[i++] = stats.rx_frame_fcs_error; ++ data[i++] = stats.rx_frame_unsupport; ++ data[i++] = stats.rx_frame_wrong_sa; ++ data[i++] = stats.rx_frame_align_err; ++ data[i++] = stats.rx_frame_length_err; ++ data[i++] = stats.rx_frame_oversize; ++ data[i++] = stats.rx_frame_mtu_err; ++ data[i++] = stats.rx_frame_truncated_err; ++ data[i++] = stats.rx_frame_undersize; ++ data[i++] = stats.tx_frames; ++ data[i++] = stats.tx_frame_good; ++ data[i++] = stats.tx_bytes; ++ data[i++] = stats.tx_frame_64; ++ data[i++] = stats.tx_frame_127; ++ data[i++] = stats.tx_frame_255; ++ data[i++] = stats.tx_frame_511; ++ data[i++] = stats.tx_frame_1023; ++ data[i++] = stats.tx_frame_1518; ++ data[i++] = stats.tx_frame_1522; ++ data[i++] = stats.tx_frame_jumbo; ++ data[i++] = stats.tx_frame_unicast; ++ data[i++] = stats.tx_frame_multicast; ++ data[i++] = stats.tx_frame_broadcast; ++ data[i++] = stats.tx_frame_control; ++ data[i++] = stats.tx_frame_pause; ++ data[i++] = stats.tx_frame_jabber; ++ data[i++] = stats.tx_frame_fragment; ++ data[i++] = stats.tx_frame_vlan; ++ data[i++] = stats.tx_frame_dvlan; ++ data[i++] = stats.tx_frame_fcs_error; ++ data[i++] = stats.tx_frame_oversize; ++ data[i++] = stats.tx_frame_error; ++ data[i++] = stats.tx_frame_fifo_underrun; ++ data[i++] = stats.tx_frame_collision; ++ } ++} ++ ++static int apm_dump_phy_regs(struct apm *apm, int try_run, char *reg_buf) ++{ ++ struct phy_device *phydev = apm->net_dev->phydev; ++ int idx, len = 0; ++ char *buf, tmp[32]; ++ u16 data = 0; ++ ++ if (phydev) { ++ for (idx = 0; idx < 16; idx++) { ++ if (try_run || !reg_buf) { ++ buf = tmp; ++ } else { ++ buf = reg_buf + len; ++ data = phy_read(phydev, idx); ++ } ++ len += sprintf(buf, "PHY REG %d: 0x%.4x\n", idx, data); ++ } ++ } ++ return len; ++} ++ ++static int apm_get_regs_len(struct net_device *dev) ++{ ++ struct apm *apm = netdev_priv(dev); ++ u32 len = 0; ++ ++ len += apm_dump_phy_regs(apm, 1, NULL); ++ ++ return len; ++} ++ ++static void apm_get_regs(struct net_device *dev, ++ struct ethtool_regs *regs, void *_p) ++{ ++ struct apm *apm = netdev_priv(dev); ++ u32 len = 0; ++ ++ regs->version = 0; ++ ++ /* Dump phy register */ ++ len += apm_dump_phy_regs(apm, 0, (char *)_p + len); ++} ++ ++static void apm_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *info) ++{ ++ strlcpy(info->driver, "apm", sizeof(info->driver)); ++ strlcpy(info->version, "0.1", sizeof(info->version)); ++ strlcpy(info->bus_info, "axi", sizeof(info->bus_info)); ++ info->regdump_len = apm_get_regs_len(net_dev); ++} ++ ++static const struct ethtool_ops apm_ethtool_ops = { ++ .get_regs = apm_get_regs, ++ .get_regs_len = apm_get_regs_len, ++ .get_strings = apm_get_strings, ++ .get_sset_count = apm_get_sset_count, ++ .get_ethtool_stats = apm_get_ethtool_stats, ++ .get_drvinfo = apm_get_drvinfo, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++}; ++ ++int apm_ethtool_init(struct net_device *net_dev) ++{ ++ net_dev->ethtool_ops = &apm_ethtool_ops; ++ return 0; ++} ++ ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c +--- a/drivers/net/ethernet/broadcom/bgmac-platform.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/bgmac-platform.c 2018-05-10 11:31:31.729401905 +0800 +@@ -19,6 +19,12 @@ + #include + #include + #include ++ ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++#include ++#include ++#endif ++ + #include "bgmac.h" + + #define NICPM_PADRING_CFG 0x00000004 +@@ -84,9 +90,16 @@ static void platform_bgmac_clk_enable(st + } + + val = bgmac_idm_read(bgmac, BCMA_IOCTL); ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++ /* To make HX4/KT2 GMAC work */ ++ val |= flags; ++ val &= ~(BGMAC_AWCACHE | BGMAC_ARCACHE | BGMAC_AWUSER | ++ BGMAC_ARUSER); ++#else + /* Some bits of BCMA_IOCTL set by HW/ATF and should not change */ + val |= flags & ~(BGMAC_AWCACHE | BGMAC_ARCACHE | BGMAC_AWUSER | + BGMAC_ARUSER); ++#endif + val |= BGMAC_CLK_EN; + bgmac_idm_write(bgmac, BCMA_IOCTL, val); + bgmac_idm_read(bgmac, BCMA_IOCTL); +@@ -147,18 +160,123 @@ static void bgmac_nicpm_speed_set(struct + bgmac_adjust_link(bgmac->net_dev); + } + ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++#define SERDES_CONTROL_OFFSET 0x1a8 ++#define SC_TX1G_FIFO_RST_MASK 0x00f00000 ++#define SC_TX1G_FIFO_RST_VAL 0x00f00000 ++#define SC_FORCE_SPD_STRAP_MASK 0x00060000 ++#define SC_FORCE_SPD_STRAP_VAL 0x00040000 ++#define SC_FORCE_SPD_100M_VAL 0x00020000 ++#define SC_FORCE_SPD_1G_VAL 0x00040000 ++#define SC_REF_TERM_SEL_MASK 0x00001000 ++#define SC_REFSEL_MASK 0x00000c00 ++#define SC_REFSEL_VAL 0x00000400 ++#define SC_REFDIV_MASK 0x00000300 ++#define SC_REFDIV_VAL 0x00000000 ++#define SC_LCREF_EN_MASK 0x00000040 ++#define SC_RSTB_PLL_MASK 0x00000010 ++#define SC_RSTB_MDIOREGS_MASK 0x00000008 ++#define SC_RSTB_HW_MASK 0x00000004 ++#define SC_IDDQ_MASK 0x00000002 ++#define SC_PWR_DOWN_MASK 0x00000001 ++ ++void amac_serdes_init(struct bgmac *info, struct phy_device *phy_dev) ++{ ++ u32 sdctl; ++ void *serdes_ctl_reg; ++ struct phy_device *phydev = phy_dev; ++ ++ serdes_ctl_reg = info->plat.base + SERDES_CONTROL_OFFSET; ++ ++ sdctl = (SC_TX1G_FIFO_RST_VAL | SC_FORCE_SPD_STRAP_VAL); ++ if (xgs_serdes_hx4_amac(phydev)) ++ sdctl |= (SC_REFSEL_VAL | SC_REF_TERM_SEL_MASK); ++ ++ else if (xgs_serdes_kt2_amac(phydev)) ++ sdctl |= SC_REF_TERM_SEL_MASK; ++ ++ writel(sdctl, serdes_ctl_reg); ++ ++ udelay(1000); ++ ++ sdctl = readl(serdes_ctl_reg); ++ sdctl |= (SC_IDDQ_MASK | SC_PWR_DOWN_MASK); ++ writel(sdctl, serdes_ctl_reg); ++ ++ sdctl = readl(serdes_ctl_reg); ++ sdctl &= ~(SC_IDDQ_MASK | SC_PWR_DOWN_MASK); ++ writel(sdctl, serdes_ctl_reg); ++ ++ /* Bring hardware out of reset */ ++ sdctl = readl(serdes_ctl_reg); ++ sdctl |= SC_RSTB_HW_MASK; ++ writel(sdctl, serdes_ctl_reg); ++ ++ /* Bring MDIOREGS out of reset */ ++ sdctl = readl(serdes_ctl_reg); ++ sdctl |= SC_RSTB_MDIOREGS_MASK; ++ writel(sdctl, serdes_ctl_reg); ++ ++ udelay(1000); ++ ++ /* Bring PLL out of reset */ ++ sdctl = readl(serdes_ctl_reg); ++ sdctl |= SC_RSTB_PLL_MASK; ++ writel(sdctl, serdes_ctl_reg); ++ ++ udelay(1000); ++ ++ return; ++} ++#endif /* IS_ENABLED(CONFIG_ARCH_XGS_IPROC) */ ++ + static int platform_phy_connect(struct bgmac *bgmac) + { + struct phy_device *phy_dev; + +- if (bgmac->plat.nicpm_base) ++ if (bgmac->plat.nicpm_base) { + phy_dev = of_phy_get_and_connect(bgmac->net_dev, + bgmac->dev->of_node, + bgmac_nicpm_speed_set); +- else ++ } ++ else { ++ struct device_node *np = bgmac->dev->of_node; ++ u32 lane; ++ ++ /* For WH2 SGMII case, treat SERDES as PHY */ ++ if (of_device_is_compatible(np, "brcm,xgs-wh2-amac") && ++ is_wh2_amac_sgmii()) { ++ struct device_node *phy_np; ++ phy_interface_t iface = PHY_INTERFACE_MODE_SGMII; ++ ++ phy_np = of_parse_phandle(np, "serdes-phy-handle", 0); ++ if (!phy_np) ++ return -ENODEV; ++ ++ phy_dev = of_phy_find_device(phy_np); ++ if (!phy_dev) ++ return -ENODEV; ++ ++ /* Get lane from DT, otherwise set to default 3 */ ++ if (of_property_read_u32(phy_np, "lane-num", &lane)) ++ lane = 3; ++ xgs_serdes_set_lane(phy_dev, lane); ++ ++ amac_serdes_init(bgmac, phy_dev); ++ ++ phy_connect_direct(bgmac->net_dev, phy_dev, ++ bgmac_adjust_link, iface); ++ ++ put_device(&phy_dev->mdio.dev); ++ of_node_put(phy_np); ++ } ++ else { + phy_dev = of_phy_get_and_connect(bgmac->net_dev, + bgmac->dev->of_node, + bgmac_adjust_link); ++ } ++ } ++ + if (!phy_dev) { + dev_err(bgmac->dev, "PHY connection failed\n"); + return -ENODEV; +@@ -285,6 +403,8 @@ static const struct dev_pm_ops bgmac_pm_ + static const struct of_device_id bgmac_of_enet_match[] = { + {.compatible = "brcm,amac",}, + {.compatible = "brcm,nsp-amac",}, ++ {.compatible = "brcm,xgs-iproc-amac",}, ++ {.compatible = "brcm,xgs-wh2-amac",}, + {.compatible = "brcm,ns2-amac",}, + {}, + }; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c +--- a/drivers/net/ethernet/broadcom/bgmac.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/bgmac.c 2018-05-10 11:31:31.733401909 +0800 +@@ -17,6 +17,13 @@ + #include + #include "bgmac.h" + ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++#include ++#include ++extern bool xgs_mdio_bus_release(void); ++extern void amac_serdes_init(struct bgmac *, struct phy_device *); ++#endif ++ + static bool bgmac_wait_value(struct bgmac *bgmac, u16 reg, u32 mask, + u32 value, int timeout) + { +@@ -1120,6 +1127,7 @@ static void bgmac_chip_init(struct bgmac + + bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN); + ++ if (!IS_ENABLED(CONFIG_ARCH_XGS_IPROC)) + bgmac_chip_intrs_on(bgmac); + + bgmac_enable(bgmac); +@@ -1197,10 +1204,33 @@ static int bgmac_open(struct net_device + } + napi_enable(&bgmac->napi); + ++ if (IS_ENABLED(CONFIG_ARCH_XGS_IPROC)) { ++ /* Reset emulated MIB statistics to zero */ ++ memset(&bgmac->estats, 0, sizeof(struct bgmac_ethtool_stats)); ++ ++ /* ++ * phy_state_machine reschedule could be stopped due to the code ++ * change in phy.c to handle MDIO bus sharing between iProc and ++ * CIMCd of HX4/KT2. ++ */ ++ if (xgs_mdio_bus_release()) ++ phy_start_machine(net_dev->phydev); ++ } ++ + phy_start(net_dev->phydev); + + netif_start_queue(net_dev); + ++ /* ++ * This interrupt enable was originally set in "bgmac_chip_init" which ++ * was run before "napi_enable". If interrupt events come before ++ * napi_enable was run, the NAPI poll routine "bgmac_poll" will not yet ++ * be available for either handling interrupt events or re-enabling the ++ * AMAC interrupt disabled by "bgmac_interrupt". ++ */ ++ if (IS_ENABLED(CONFIG_ARCH_XGS_IPROC)) ++ bgmac_chip_intrs_on(bgmac); ++ + return 0; + } + +@@ -1379,6 +1409,9 @@ static void bgmac_get_ethtool_stats(stru + const struct bgmac_stat *s; + unsigned int i; + u64 val; ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++ u64 *estats = (u64*)&bgmac->estats; ++#endif + + if (!netif_running(dev)) + return; +@@ -1389,18 +1422,70 @@ static void bgmac_get_ethtool_stats(stru + if (s->size == 8) + val = (u64)bgmac_read(bgmac, s->offset + 4) << 32; + val |= bgmac_read(bgmac, s->offset); ++ if (IS_ENABLED(CONFIG_ARCH_XGS_IPROC)) { ++ estats[i] += val; ++ data[i] = estats[i]; ++ } ++ else { + data[i] = val; + } + } ++} ++ ++static int bgmac_dump_phy_regs(struct bgmac *bgmac, int try_run, char *reg_buf) ++{ ++ struct phy_device *phydev = bgmac->net_dev->phydev; ++ int idx, len = 0; ++ char *buf, tmp[32]; ++ u16 data = 0; ++ ++ if (phydev) { ++ for (idx = 0; idx < 16; idx++) { ++ if (try_run || !reg_buf) { ++ buf = tmp; ++ } else { ++ buf = reg_buf + len; ++ data = phy_read(phydev, idx); ++ } ++ len += sprintf(buf, "PHY REG %d: 0x%.4x\n", idx, data); ++ } ++ } ++ return len; ++} ++ ++static int bgmac_get_regs_len(struct net_device *dev) ++{ ++ struct bgmac *bgmac = netdev_priv(dev); ++ u32 len = 0; ++ ++ len += bgmac_dump_phy_regs(bgmac, 1, NULL); ++ ++ return len; ++} ++ ++static void bgmac_get_regs(struct net_device *dev, ++ struct ethtool_regs *regs, void *_p) ++{ ++ struct bgmac *bgmac = netdev_priv(dev); ++ u32 len = 0; ++ ++ regs->version = 0; ++ ++ /* Dump phy register */ ++ len += bgmac_dump_phy_regs(bgmac, 0, (char *)_p + len); ++} + + static void bgmac_get_drvinfo(struct net_device *net_dev, + struct ethtool_drvinfo *info) + { + strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + strlcpy(info->bus_info, "AXI", sizeof(info->bus_info)); ++ info->regdump_len = bgmac_get_regs_len(net_dev); + } + + static const struct ethtool_ops bgmac_ethtool_ops = { ++ .get_regs = bgmac_get_regs, ++ .get_regs_len = bgmac_get_regs_len, + .get_strings = bgmac_get_strings, + .get_sset_count = bgmac_get_sset_count, + .get_ethtool_stats = bgmac_get_ethtool_stats, +@@ -1431,11 +1516,11 @@ void bgmac_adjust_link(struct net_device + } + } + +- if (update) { ++ if (update) + bgmac_mac_speed(bgmac); ++ + phy_print_status(phy_dev); + } +-} + EXPORT_SYMBOL_GPL(bgmac_adjust_link); + + int bgmac_phy_connect_direct(struct bgmac *bgmac) +@@ -1490,6 +1576,12 @@ int bgmac_enet_probe(struct bgmac *bgmac + { + struct net_device *net_dev = bgmac->net_dev; + int err; ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++ struct device_node *serdes_np; ++ struct device_node *amac_np; ++ struct phy_device *serdes_phy_dev = NULL; ++ static u32 serdes_lane2_init = 0; ++#endif + + net_dev->irq = bgmac->irq; + SET_NETDEV_DEV(net_dev, bgmac->dev); +@@ -1534,6 +1626,37 @@ int bgmac_enet_probe(struct bgmac *bgmac + goto err_dma_free; + } + ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++ /* SERDES init required for HX4/KT2/SB2/GH2/WH2 */ ++ amac_np = bgmac->dev->of_node; ++ serdes_np = of_parse_phandle(amac_np, "serdes-handle", 0); ++ if (serdes_np) ++ serdes_phy_dev = of_phy_find_device(serdes_np); ++ ++ if (serdes_phy_dev) { ++ u32 lane; ++ /* If lane available in DT, set lane num */ ++ if (!of_property_read_u32(serdes_np, "lane-num", &lane)) ++ xgs_serdes_set_lane(serdes_phy_dev, lane); ++ ++ amac_serdes_init(bgmac, serdes_phy_dev); ++ phy_init_hw(serdes_phy_dev); ++ } ++ ++ /* Init SERDES lane 2 required by SDK for HX4/KT2 */ ++ if (!serdes_lane2_init) { ++ /* Use alias defined in DTS rather than full path */ ++ serdes_np = of_find_node_by_path("sdk-serdes-lane2"); ++ if (serdes_np) { ++ serdes_phy_dev = of_phy_find_device(serdes_np); ++ if (serdes_phy_dev) { ++ phy_init_hw(serdes_phy_dev); ++ serdes_lane2_init = 1; ++ } ++ } ++ } ++#endif ++ + net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + net_dev->hw_features = net_dev->features; + net_dev->vlan_features = net_dev->features; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h +--- a/drivers/net/ethernet/broadcom/bgmac.h 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/bgmac.h 2018-05-10 11:31:31.733401909 +0800 +@@ -476,6 +476,78 @@ struct bgmac_rx_header { + __le16 pad[12]; + }; + ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++struct bgmac_ethtool_stats { ++ u64 tx_good_octets; ++ u64 tx_good; ++ u64 tx_octets; ++ u64 tx_pkts; ++ u64 tx_broadcast; ++ u64 tx_multicast; ++ u64 tx_64; ++ u64 tx_65_127; ++ u64 tx_128_255; ++ u64 tx_256_511; ++ u64 tx_512_1023; ++ u64 tx_1024_1522; ++ u64 tx_1523_2047; ++ u64 tx_2048_4095; ++ u64 tx_4096_8191; ++ u64 tx_8192_max; ++ u64 tx_jabber; ++ u64 tx_oversize; ++ u64 tx_fragment; ++ u64 tx_underruns; ++ u64 tx_total_cols; ++ u64 tx_single_cols; ++ u64 tx_multiple_cols; ++ u64 tx_excessive_cols; ++ u64 tx_late_cols; ++ u64 tx_defered; ++ u64 tx_carrier_lost; ++ u64 tx_pause; ++ u64 tx_unicast; ++ u64 tx_q0; ++ u64 tx_q0_octets; ++ u64 tx_q1; ++ u64 tx_q1_octets; ++ u64 tx_q2; ++ u64 tx_q2_octets; ++ u64 tx_q3; ++ u64 tx_q3_octets; ++ ++ u64 rx_good_octets; ++ u64 rx_good; ++ u64 rx_octets; ++ u64 rx_pkts; ++ u64 rx_broadcast; ++ u64 rx_multicast; ++ u64 rx_64; ++ u64 rx_65_127; ++ u64 rx_128_255; ++ u64 rx_256_511; ++ u64 rx_512_1023; ++ u64 rx_1024_1522; ++ u64 rx_1523_2047; ++ u64 rx_2048_4095; ++ u64 rx_4096_8191; ++ u64 rx_8192_max; ++ u64 rx_jabber; ++ u64 rx_oversize; ++ u64 rx_fragment; ++ u64 rx_missed; ++ u64 rx_crc_align; ++ u64 rx_undersize; ++ u64 rx_crc; ++ u64 rx_align; ++ u64 rx_symbol; ++ u64 rx_pause; ++ u64 rx_nonpause; ++ u64 rx_sa_changes; ++ u64 rx_unicast; ++}; ++#endif ++ + struct bgmac { + union { + struct { +@@ -520,6 +592,14 @@ struct bgmac { + + bool loopback; + ++#if IS_ENABLED(CONFIG_ARCH_XGS_IPROC) ++ /* For XGS iProc, SW emulated MIB registers are required as the HW ++ * MIB registers will be cleared to zero after reading. ++ * mib_tx_regs/mib_rx_regs defined above seem for the same purpose, ++ * but not used so far. ++ */ ++ struct bgmac_ethtool_stats estats; ++#endif + u32 (*read)(struct bgmac *bgmac, u16 offset); + void (*write)(struct bgmac *bgmac, u16 offset, u32 value); + u32 (*idm_read)(struct bgmac *bgmac, u16 offset); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/merlin16_ucode.h b/drivers/net/ethernet/broadcom/merlin16_ucode.h +--- a/drivers/net/ethernet/broadcom/merlin16_ucode.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/merlin16_ucode.h 2018-05-30 15:50:51.032753168 +0800 +@@ -0,0 +1,1977 @@ ++/* ++ * $Id: merlin16_ucode.c $ ++ * $Copyright: (c) 2013 Broadcom Corporation All Rights Reserved.$ ++ * All Rights Reserved.$ ++ */ ++ ++#define MERLIN16_UCODE_IMAGE_VERSION "D101_0C" /* matches the version number from microcode */ ++#define MERLIN16_UCODE_IMAGE_SIZE 31368 ++#define MERLIN16_UCODE_IMAGE_CRC 0x2C25 ++ ++unsigned short merlin16_ucode_ver = 0xD101; ++unsigned short merlin16_ucode_crc = MERLIN16_UCODE_IMAGE_CRC; ++unsigned short merlin16_ucode_len = MERLIN16_UCODE_IMAGE_SIZE; ++ ++unsigned char merlin16_ucode[] = { ++ 0xf0, 0x0f, 0x00, 0x20, 0x7d, 0x02, 0x00, 0x00, 0x51, 0x74, 0x00, 0x00, 0x5f, 0x74, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x74, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0x7b, 0x74, 0x00, 0x00, ++ 0x89, 0x74, 0x00, 0x00, 0x97, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0xa5, 0x74, 0x00, 0x00, 0xab, 0x74, 0x00, 0x00, 0xb1, 0x74, 0x00, 0x00, 0xb7, 0x74, 0x00, 0x00, ++ 0xbd, 0x74, 0x00, 0x00, 0xc3, 0x74, 0x00, 0x00, 0xc9, 0x74, 0x00, 0x00, 0xcf, 0x74, 0x00, 0x00, ++ 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, 0xd5, 0x74, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x49, 0x6e, 0x66, 0x35, 0x0c, 0x01, 0xd1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x24, 0x00, 0x01, ++ 0x00, 0x01, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, ++ 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x24, 0x04, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x20, ++ 0x00, 0x0a, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x20, 0x44, 0x04, 0x00, 0x20, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0xf0, 0x02, 0xf8, 0x00, 0xf0, 0x3e, 0xf8, 0x0c, 0xa0, 0x30, 0xc8, 0x08, 0x38, 0x24, 0x18, ++ 0x2d, 0x18, 0xa2, 0x46, 0x67, 0x1e, 0xab, 0x46, 0x54, 0x46, 0x5d, 0x46, 0xac, 0x42, 0x01, 0xd1, ++ 0x00, 0xf0, 0x30, 0xf8, 0x7e, 0x46, 0x0f, 0x3e, 0x0f, 0xcc, 0xb6, 0x46, 0x01, 0x26, 0x33, 0x42, ++ 0x00, 0xd0, 0xfb, 0x1a, 0xa2, 0x46, 0xab, 0x46, 0x33, 0x43, 0x18, 0x47, 0x98, 0x78, 0x00, 0x00, ++ 0xb8, 0x78, 0x00, 0x00, 0x10, 0x3a, 0x02, 0xd3, 0x78, 0xc8, 0x78, 0xc1, 0xfa, 0xd8, 0x52, 0x07, ++ 0x01, 0xd3, 0x30, 0xc8, 0x30, 0xc1, 0x01, 0xd5, 0x04, 0x68, 0x0c, 0x60, 0x70, 0x47, 0x00, 0x00, ++ 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x10, 0x3a, 0x01, 0xd3, 0x78, 0xc1, 0xfb, 0xd8, ++ 0x52, 0x07, 0x00, 0xd3, 0x30, 0xc1, 0x00, 0xd5, 0x0b, 0x60, 0x70, 0x47, 0x1f, 0xb5, 0x1f, 0xbd, ++ 0x10, 0xb5, 0x10, 0xbd, 0x07, 0xf0, 0x92, 0xfb, 0x11, 0x46, 0xff, 0xf7, 0xf7, 0xff, 0x00, 0xf0, ++ 0x3f, 0xf8, 0x07, 0xf0, 0xaa, 0xfb, 0x03, 0xb4, 0xff, 0xf7, 0xf2, 0xff, 0x03, 0xbc, 0x00, 0xf0, ++ 0x34, 0xf8, 0x00, 0x00, 0x70, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x16, 0x46, 0x02, 0xe0, 0x0f, 0xcc, ++ 0x0f, 0xc5, 0x10, 0x3e, 0x10, 0x2e, 0xfa, 0xd2, 0x08, 0x2e, 0x02, 0xd3, 0x03, 0xcc, 0x03, 0xc5, ++ 0x08, 0x3e, 0x04, 0x2e, 0x07, 0xd3, 0x01, 0xcc, 0x01, 0xc5, 0x36, 0x1f, 0x03, 0xe0, 0x21, 0x78, ++ 0x29, 0x70, 0x64, 0x1c, 0x6d, 0x1c, 0x76, 0x1e, 0xf9, 0xd2, 0x70, 0xbd, 0xfe, 0xe7, 0xfe, 0xe7, ++ 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, ++ 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0x10, 0xb5, 0xff, 0xf7, ++ 0x7f, 0xff, 0x10, 0xbd, 0x0a, 0x46, 0x03, 0x46, 0x70, 0x47, 0xfe, 0xe7, 0x70, 0x47, 0x00, 0x00, ++ 0xff, 0xf7, 0xfc, 0xff, 0x07, 0xf0, 0x3a, 0xf9, 0x07, 0xf0, 0x96, 0xf9, 0x2f, 0x4d, 0x00, 0x20, ++ 0x2c, 0x46, 0x28, 0x60, 0x05, 0x21, 0x09, 0x07, 0x40, 0x18, 0x28, 0x60, 0x07, 0xf0, 0x6a, 0xf8, ++ 0x07, 0xf0, 0x05, 0xf8, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x29, 0x49, 0x81, 0x82, 0x22, 0x68, ++ 0x49, 0x1c, 0x28, 0x48, 0x12, 0x18, 0x11, 0x85, 0x21, 0x68, 0x08, 0x18, 0x80, 0x8e, 0x2f, 0x1f, ++ 0x00, 0x0b, 0x38, 0x70, 0x02, 0xf0, 0x58, 0xfd, 0x07, 0xf0, 0x94, 0xfa, 0x23, 0x49, 0x22, 0x4e, ++ 0x0e, 0x60, 0x03, 0x20, 0x22, 0x68, 0x40, 0x04, 0x82, 0x43, 0x22, 0x60, 0x2f, 0x46, 0x00, 0x24, ++ 0x0d, 0x46, 0x1a, 0xe0, 0x28, 0x68, 0x92, 0x21, 0x09, 0x5c, 0xc0, 0x22, 0x51, 0x43, 0x40, 0x30, ++ 0x81, 0x80, 0x02, 0xf0, 0x8f, 0xfd, 0x28, 0x68, 0x03, 0x22, 0x80, 0x30, 0xc0, 0x7c, 0x52, 0x04, ++ 0x00, 0x02, 0x80, 0x19, 0x28, 0x60, 0x80, 0x30, 0x80, 0x7c, 0x39, 0x68, 0x80, 0x07, 0x91, 0x43, ++ 0x40, 0x0b, 0x01, 0x43, 0x64, 0x1c, 0xe4, 0xb2, 0x39, 0x60, 0x0c, 0x48, 0x00, 0x1f, 0x00, 0x78, ++ 0x84, 0x42, 0xdf, 0xd3, 0x03, 0x24, 0x64, 0x04, 0x00, 0xf0, 0xdf, 0xf9, 0x28, 0x68, 0x80, 0x30, ++ 0xc0, 0x7c, 0x00, 0x02, 0x80, 0x19, 0x28, 0x60, 0x80, 0x30, 0x80, 0x7c, 0x39, 0x68, 0x80, 0x07, ++ 0xa1, 0x43, 0x40, 0x0b, 0x01, 0x43, 0x39, 0x60, 0xee, 0xe7, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xa1, 0x01, 0x00, 0x00, 0x05, 0x00, 0x20, 0x90, 0x00, 0x00, 0x20, ++ 0xfe, 0x48, 0x56, 0x21, 0x00, 0x68, 0x0a, 0x5c, 0x01, 0x46, 0x80, 0x31, 0x01, 0x2a, 0x04, 0xd0, ++ 0x82, 0x79, 0x4a, 0x73, 0xc0, 0x79, 0x88, 0x73, 0x70, 0x47, 0x02, 0x7a, 0x4a, 0x73, 0x40, 0x7a, ++ 0xf9, 0xe7, 0xf7, 0x49, 0x08, 0x5c, 0x70, 0x47, 0x1c, 0xb5, 0x00, 0x21, 0x6a, 0x46, 0x11, 0x80, ++ 0x90, 0x80, 0xf4, 0x49, 0xf2, 0x4a, 0x09, 0x7b, 0xf0, 0x4c, 0x52, 0x5c, 0x21, 0x68, 0x60, 0x31, ++ 0x0b, 0x78, 0x9a, 0x42, 0x17, 0xd9, 0x16, 0x22, 0x8a, 0x56, 0x01, 0x23, 0xdb, 0x07, 0x9a, 0x42, ++ 0x11, 0xd1, 0x00, 0x07, 0x80, 0x0f, 0x02, 0x28, 0x0d, 0xd0, 0x08, 0x20, 0x6b, 0x46, 0x18, 0x80, ++ 0x52, 0x1e, 0x8a, 0x75, 0x09, 0x7d, 0x01, 0x29, 0x01, 0xd0, 0x05, 0xf0, 0x80, 0xfe, 0x20, 0x68, ++ 0x60, 0x30, 0x00, 0x7d, 0x1c, 0xbd, 0x01, 0x20, 0x08, 0x75, 0xf8, 0xe7, 0xe2, 0x48, 0x02, 0x68, ++ 0xe2, 0x49, 0x52, 0x18, 0xd2, 0x8e, 0x03, 0x68, 0x92, 0x04, 0x52, 0x0f, 0x5b, 0x18, 0xdb, 0x8e, ++ 0x00, 0x68, 0x5b, 0x05, 0x5b, 0x0f, 0xd2, 0x18, 0x52, 0x08, 0x40, 0x18, 0xc0, 0x8e, 0x80, 0x06, ++ 0x80, 0x0e, 0x10, 0x18, 0x70, 0x47, 0xd6, 0x49, 0x15, 0x31, 0x08, 0x5c, 0x70, 0x47, 0x7c, 0xb5, ++ 0x05, 0x46, 0xd4, 0x48, 0xd2, 0x49, 0x00, 0x7b, 0x15, 0x31, 0x0c, 0x5c, 0x00, 0x20, 0x69, 0x46, ++ 0x08, 0x80, 0x8d, 0x80, 0xff, 0xf7, 0xda, 0xff, 0xa9, 0x06, 0x89, 0x0f, 0xcb, 0x4d, 0xa0, 0x42, ++ 0x0a, 0xd8, 0x2a, 0x68, 0x60, 0x32, 0x52, 0x7d, 0xa2, 0x42, 0x05, 0xd2, 0x03, 0x29, 0x03, 0xd0, ++ 0x10, 0x21, 0x6a, 0x46, 0x11, 0x80, 0x15, 0xe0, 0x01, 0x26, 0xa0, 0x42, 0x0f, 0xd9, 0x2a, 0x68, ++ 0x60, 0x32, 0x53, 0x7d, 0xa3, 0x42, 0x0a, 0xd2, 0x1b, 0x18, 0x64, 0x00, 0xa3, 0x42, 0x06, 0xd9, ++ 0x02, 0x29, 0x04, 0xd0, 0x20, 0x21, 0x6b, 0x46, 0x19, 0x80, 0xd6, 0x74, 0x02, 0xe0, 0x29, 0x68, ++ 0x60, 0x31, 0xce, 0x74, 0x29, 0x68, 0x60, 0x31, 0x48, 0x75, 0x68, 0x46, 0x00, 0x88, 0x81, 0x06, ++ 0x89, 0x0f, 0x01, 0xd0, 0x05, 0xf0, 0x23, 0xfe, 0x28, 0x68, 0x60, 0x30, 0xc0, 0x7c, 0x7c, 0xbd, ++ 0xf8, 0xb5, 0xb2, 0x4c, 0x03, 0x26, 0x20, 0x68, 0x36, 0x07, 0x40, 0x30, 0xc0, 0x7a, 0x01, 0x27, ++ 0x25, 0x38, 0xb1, 0x4d, 0x03, 0x00, 0x07, 0xf0, 0x63, 0xfa, 0x07, 0x21, 0x6f, 0x8f, 0x81, 0xa1, ++ 0xb1, 0xbf, 0x05, 0x00, 0xb0, 0x8a, 0x07, 0x20, 0xc0, 0x43, 0xb0, 0x82, 0x2a, 0x68, 0x07, 0x21, ++ 0xaa, 0x48, 0x40, 0x30, 0x12, 0x18, 0x11, 0x85, 0xb1, 0x8a, 0x02, 0x21, 0xc9, 0x43, 0xb1, 0x82, ++ 0x2a, 0x68, 0x02, 0x21, 0x10, 0x18, 0x01, 0x84, 0x08, 0x20, 0x07, 0xf0, 0x73, 0xf9, 0x06, 0xf0, ++ 0x23, 0xff, 0x21, 0x68, 0x48, 0x84, 0x00, 0x20, 0x40, 0x31, 0x08, 0x76, 0x20, 0x68, 0x01, 0x46, ++ 0x80, 0x31, 0x8a, 0x7d, 0x00, 0x2a, 0x09, 0xd0, 0x42, 0x7f, 0x52, 0x07, 0x3c, 0xd5, 0x2b, 0x22, ++ 0x40, 0x30, 0x82, 0x72, 0x4f, 0x76, 0x05, 0xf0, 0x16, 0xfe, 0xf8, 0xbd, 0x06, 0xf0, 0x0c, 0xff, ++ 0x81, 0xb2, 0x20, 0x68, 0x42, 0x8c, 0x51, 0x1a, 0x64, 0x29, 0x2b, 0xdb, 0x58, 0x21, 0x09, 0x5c, ++ 0x00, 0x29, 0x02, 0xd1, 0x00, 0x88, 0xc0, 0x05, 0x0d, 0xd4, 0x02, 0x21, 0x0f, 0x20, 0x07, 0xf0, ++ 0x49, 0xf9, 0xb0, 0x8a, 0x01, 0x20, 0xc0, 0x43, 0xb0, 0x82, 0x28, 0x68, 0x0d, 0x21, 0x49, 0x03, ++ 0x40, 0x18, 0x47, 0x86, 0x16, 0xe0, 0xb0, 0x8a, 0x01, 0x20, 0xc0, 0x43, 0xb0, 0x82, 0x28, 0x68, ++ 0x87, 0x49, 0x40, 0x18, 0xc0, 0x8c, 0x3a, 0x46, 0x82, 0x43, 0x28, 0x68, 0x40, 0x18, 0xc2, 0x84, ++ 0x06, 0xf0, 0xe2, 0xfe, 0x21, 0x68, 0x48, 0x84, 0x40, 0x31, 0x0f, 0x76, 0x02, 0x21, 0x1d, 0x20, ++ 0x07, 0xf0, 0x28, 0xf9, 0x25, 0x21, 0x7f, 0xe0, 0x29, 0x68, 0xff, 0x31, 0x01, 0x31, 0x49, 0x8e, ++ 0x89, 0x06, 0x89, 0x0e, 0x40, 0x30, 0x41, 0x80, 0x20, 0x68, 0x26, 0x22, 0x01, 0x46, 0x40, 0x31, ++ 0xca, 0x72, 0x80, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xb7, 0xd0, 0x48, 0x88, 0xff, 0xf7, 0x37, 0xff, ++ 0x01, 0x28, 0x0d, 0xd0, 0x20, 0x68, 0x28, 0x21, 0x40, 0x30, 0xc1, 0x72, 0x20, 0x68, 0x98, 0x21, ++ 0x09, 0x5c, 0x00, 0x29, 0xa9, 0xd0, 0x14, 0x21, 0x40, 0x30, 0x81, 0x72, 0x26, 0x21, 0x5d, 0xe0, ++ 0x21, 0x68, 0x00, 0x20, 0x40, 0x31, 0x48, 0x80, 0x20, 0x68, 0x27, 0x22, 0x01, 0x46, 0x40, 0x31, ++ 0xca, 0x72, 0x80, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0x97, 0xd0, 0x48, 0x88, 0xff, 0xf7, 0xd4, 0xfe, ++ 0x01, 0x28, 0x0d, 0xd0, 0x20, 0x68, 0x29, 0x21, 0x40, 0x30, 0xc1, 0x72, 0x20, 0x68, 0x98, 0x21, ++ 0x09, 0x5c, 0x00, 0x29, 0x89, 0xd0, 0x14, 0x21, 0x40, 0x30, 0x81, 0x72, 0x27, 0x21, 0x3d, 0xe0, ++ 0x05, 0xf0, 0x99, 0xfd, 0x20, 0x68, 0x2a, 0x21, 0x40, 0x30, 0xc1, 0x72, 0x28, 0x68, 0x57, 0x49, ++ 0x80, 0x31, 0x40, 0x18, 0x80, 0x88, 0x40, 0x07, 0xc0, 0x0f, 0xbd, 0xd0, 0x20, 0x68, 0x99, 0x21, ++ 0x0f, 0x54, 0x2b, 0x21, 0x40, 0x30, 0xc1, 0x72, 0x28, 0x68, 0xff, 0x30, 0x01, 0x30, 0xc0, 0x8d, ++ 0xc0, 0x08, 0xc0, 0x07, 0xc0, 0x0f, 0x00, 0xd0, 0x67, 0xe7, 0x28, 0x68, 0xff, 0x30, 0x01, 0x30, ++ 0xc0, 0x8d, 0x40, 0x07, 0xc0, 0x0f, 0xf7, 0xd1, 0x28, 0x68, 0xff, 0x30, 0x01, 0x30, 0xc0, 0x8d, ++ 0x80, 0x07, 0xc0, 0x0f, 0xf0, 0xd1, 0x28, 0x68, 0xff, 0x30, 0x01, 0x30, 0xc0, 0x8d, 0xc0, 0x07, ++ 0xea, 0xd0, 0xb0, 0x8a, 0x04, 0x20, 0xc0, 0x43, 0xb0, 0x82, 0x2a, 0x68, 0x04, 0x21, 0x3f, 0x48, ++ 0x40, 0x30, 0x10, 0x18, 0x01, 0x84, 0x2c, 0x21, 0x20, 0x68, 0x40, 0x30, 0xc1, 0x72, 0xf8, 0xbd, ++ 0xf8, 0xb5, 0x39, 0x4c, 0x20, 0x68, 0xff, 0x30, 0x01, 0x30, 0x80, 0x8d, 0x33, 0x4a, 0x80, 0x07, ++ 0xc1, 0x0f, 0x36, 0x4f, 0x95, 0x23, 0x10, 0x68, 0x03, 0x25, 0x2d, 0x07, 0x35, 0x4e, 0x40, 0x37, ++ 0x19, 0x54, 0x00, 0x29, 0x19, 0xd0, 0x40, 0x7f, 0x00, 0x07, 0x09, 0xd4, 0x2d, 0x4b, 0x18, 0x22, ++ 0x16, 0x21, 0x17, 0x20, 0x9a, 0x56, 0x59, 0x56, 0x18, 0x56, 0x00, 0x23, 0x06, 0xf0, 0xa1, 0xf9, ++ 0xa8, 0x8a, 0xae, 0x82, 0x21, 0x68, 0x01, 0x20, 0xc9, 0x19, 0x08, 0x84, 0x23, 0x48, 0x00, 0x68, ++ 0x00, 0x78, 0x80, 0x07, 0xc0, 0x17, 0x40, 0x1c, 0xf8, 0xbd, 0xa8, 0x8a, 0xae, 0x82, 0x21, 0x68, ++ 0x04, 0x20, 0xc9, 0x19, 0x08, 0x84, 0x00, 0x20, 0xf8, 0xbd, 0xfe, 0xb5, 0x1b, 0x4d, 0x00, 0x24, ++ 0x28, 0x68, 0x80, 0x30, 0x80, 0x7c, 0x00, 0x28, 0x19, 0xd1, 0x02, 0xf0, 0x0c, 0xfb, 0x0f, 0x27, ++ 0x3f, 0x03, 0x06, 0xf0, 0xdf, 0xfd, 0x1c, 0x4e, 0x00, 0x0c, 0x31, 0x68, 0x09, 0x0c, 0x40, 0x1a, ++ 0xb8, 0x42, 0x0c, 0xdd, 0x19, 0x48, 0xff, 0x21, 0x81, 0x70, 0xf0, 0x21, 0x41, 0x70, 0x04, 0x70, ++ 0x03, 0x20, 0x06, 0xf0, 0xc1, 0xff, 0x30, 0x68, 0x39, 0x04, 0x40, 0x18, 0x30, 0x60, 0x0e, 0x4e, ++ 0x31, 0x68, 0x0f, 0x48, 0x40, 0x30, 0x08, 0x18, 0x00, 0x8d, 0xc0, 0x0b, 0x06, 0xd1, 0x00, 0x23, ++ 0x07, 0x99, 0x1a, 0x46, 0x01, 0x20, 0x00, 0x94, 0x06, 0xf0, 0x73, 0xff, 0x29, 0x68, 0x80, 0x31, ++ 0x88, 0x7a, 0xc8, 0x72, 0x04, 0x48, 0x02, 0x68, 0x0d, 0x20, 0x11, 0xe0, 0x90, 0x00, 0x00, 0x20, ++ 0x9a, 0x79, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, ++ 0x80, 0xa1, 0x01, 0x00, 0xfa, 0xff, 0x00, 0x00, 0x88, 0x00, 0x00, 0x20, 0x8c, 0x00, 0x00, 0x20, ++ 0x40, 0x03, 0x10, 0x18, 0x80, 0x8f, 0xc2, 0x0a, 0x8a, 0x72, 0x01, 0x06, 0xc9, 0x0f, 0x03, 0xd1, ++ 0x80, 0x06, 0x80, 0x0e, 0x01, 0xf0, 0xf6, 0xfe, 0x29, 0x68, 0x48, 0x7c, 0x00, 0x28, 0x09, 0xd0, ++ 0x01, 0x28, 0x26, 0xd0, 0x02, 0x28, 0x22, 0xd0, 0x03, 0x28, 0x23, 0xd0, 0x04, 0x28, 0x24, 0xd0, ++ 0x05, 0x28, 0x25, 0xd0, 0x00, 0x20, 0x52, 0x22, 0x50, 0x54, 0x08, 0x88, 0xfa, 0x4e, 0x82, 0x07, ++ 0x01, 0x24, 0x00, 0x2a, 0x31, 0xdb, 0x80, 0x05, 0x2f, 0xd5, 0x80, 0x31, 0x88, 0x7a, 0x03, 0x28, ++ 0x2b, 0xd9, 0x11, 0x28, 0x29, 0xd0, 0x48, 0x7d, 0x00, 0x28, 0x26, 0xd0, 0xf3, 0x4d, 0x28, 0x68, ++ 0x0d, 0x27, 0x7f, 0x03, 0xc0, 0x19, 0x80, 0x8e, 0xc0, 0x07, 0x0c, 0xd0, 0x1d, 0xe0, 0x00, 0xf0, ++ 0x2e, 0xfe, 0xfe, 0xbd, 0x00, 0xf0, 0xa0, 0xfe, 0xfe, 0xbd, 0x01, 0xf0, 0x57, 0xfc, 0xfe, 0xbd, ++ 0x01, 0xf0, 0x32, 0xf9, 0xfe, 0xbd, 0x06, 0xf0, 0x8f, 0xfd, 0x40, 0x1c, 0xe8, 0x49, 0x40, 0x42, ++ 0x88, 0x42, 0x0a, 0xd3, 0x02, 0x21, 0x1e, 0x20, 0x06, 0xf0, 0xd4, 0xff, 0x03, 0x20, 0x00, 0x07, ++ 0x81, 0x8a, 0x86, 0x82, 0x28, 0x68, 0xc0, 0x19, 0xf0, 0xe2, 0xe2, 0x4d, 0x28, 0x68, 0x80, 0x30, ++ 0xc1, 0x7a, 0x00, 0x29, 0x06, 0xd1, 0x80, 0x7a, 0x00, 0x28, 0x13, 0xd0, 0x01, 0x21, 0x03, 0x20, ++ 0x06, 0xf0, 0xc0, 0xff, 0x28, 0x68, 0x80, 0x30, 0xc1, 0x7a, 0x03, 0x29, 0x01, 0xd9, 0x11, 0x29, ++ 0x08, 0xd1, 0x80, 0x7a, 0x03, 0x28, 0x05, 0xd9, 0x11, 0x28, 0x03, 0xd0, 0x01, 0x21, 0x26, 0x20, ++ 0x06, 0xf0, 0xb0, 0xff, 0xd3, 0x48, 0xd4, 0x4d, 0x00, 0x68, 0x02, 0x46, 0x80, 0x32, 0x91, 0x7a, ++ 0x00, 0x29, 0x21, 0xd0, 0x01, 0x29, 0x7d, 0xd0, 0x02, 0x29, 0x7c, 0xd0, 0x03, 0x29, 0x7b, 0xd0, ++ 0x40, 0x30, 0x82, 0x7a, 0xc8, 0x4f, 0xcb, 0x4d, 0x7f, 0x3f, 0x13, 0x00, 0x07, 0xf0, 0x70, 0xf8, ++ 0x25, 0xfd, 0xfc, 0xfb, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, ++ 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xea, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, ++ 0xe9, 0xea, 0xea, 0xe9, 0xe8, 0xe8, 0xe9, 0x00, 0xd0, 0x7a, 0x00, 0x28, 0x03, 0xd0, 0x02, 0x21, ++ 0x01, 0x20, 0x06, 0xf0, 0x7f, 0xff, 0xb9, 0x4f, 0x39, 0x68, 0xbb, 0x48, 0x08, 0x18, 0x40, 0x8a, ++ 0x40, 0x07, 0x80, 0x0f, 0x24, 0xd0, 0x01, 0x28, 0x2b, 0xd0, 0xb6, 0x4d, 0x28, 0x68, 0x40, 0x30, ++ 0x40, 0x7a, 0x00, 0x28, 0x01, 0xd0, 0x02, 0xf0, 0xa1, 0xf9, 0x28, 0x68, 0x01, 0x21, 0x40, 0x30, ++ 0x81, 0x74, 0x38, 0x68, 0xb1, 0x4d, 0x40, 0x19, 0x00, 0x8e, 0x40, 0x07, 0x80, 0x0f, 0x01, 0x28, ++ 0x7e, 0xd0, 0xaf, 0x4c, 0x20, 0x7d, 0x00, 0x28, 0x00, 0xd0, 0x7b, 0xe7, 0x00, 0x90, 0x03, 0x46, ++ 0x01, 0x22, 0x04, 0x21, 0x01, 0x90, 0x06, 0xf0, 0xdf, 0xfe, 0x01, 0x20, 0x20, 0x75, 0xfe, 0xbd, ++ 0xa4, 0x48, 0x00, 0x68, 0x40, 0x30, 0x40, 0x7a, 0x00, 0x28, 0xf8, 0xd0, 0x02, 0xf0, 0x7e, 0xf9, ++ 0xfe, 0xbd, 0x39, 0x68, 0xa1, 0x48, 0xc0, 0x38, 0x08, 0x18, 0x80, 0x89, 0xc0, 0x07, 0xc0, 0x0f, ++ 0x0b, 0xd0, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x86, 0x82, 0x3a, 0x68, 0x00, 0x20, 0x9b, 0x49, ++ 0xc0, 0x39, 0x51, 0x18, 0x88, 0x81, 0x02, 0xf0, 0x96, 0xf9, 0x03, 0x25, 0x2d, 0x07, 0xa8, 0x8a, ++ 0x02, 0x20, 0xc0, 0x43, 0xa8, 0x82, 0x3a, 0x68, 0x02, 0x20, 0x94, 0x49, 0xc0, 0x39, 0x51, 0x18, ++ 0x48, 0x81, 0x02, 0xe0, 0xb2, 0xe0, 0x2b, 0xe1, 0x12, 0xe2, 0x02, 0xf0, 0x57, 0xf9, 0x8d, 0x48, ++ 0x00, 0x68, 0x00, 0x78, 0xc0, 0x07, 0x01, 0xd0, 0x06, 0xf0, 0xe4, 0xfb, 0x39, 0x68, 0x8a, 0x48, ++ 0x08, 0x18, 0xc0, 0x8a, 0x39, 0x68, 0x00, 0x07, 0x00, 0x0f, 0xff, 0x31, 0x01, 0x31, 0x89, 0x8d, ++ 0x00, 0x23, 0x89, 0x07, 0xc9, 0x0f, 0x09, 0x01, 0x01, 0x43, 0x82, 0x48, 0x00, 0x68, 0x00, 0x88, ++ 0x02, 0x0a, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x00, 0x0a, 0x01, 0x43, 0x03, 0x20, 0x02, 0x22, ++ 0x01, 0x91, 0x00, 0x90, 0x11, 0x46, 0x01, 0x20, 0x06, 0xf0, 0x86, 0xfe, 0x02, 0xf0, 0x89, 0xfa, ++ 0xff, 0xf7, 0x56, 0xfe, 0x00, 0x28, 0x7b, 0x4b, 0xa8, 0x8a, 0x12, 0xd0, 0x02, 0x20, 0xc0, 0x43, ++ 0xa8, 0x82, 0x3a, 0x68, 0x02, 0x20, 0x78, 0x49, 0x51, 0x18, 0xc8, 0x80, 0xa8, 0x8a, 0xab, 0x82, ++ 0x0d, 0x21, 0x3a, 0x68, 0x89, 0x01, 0xd1, 0x20, 0x40, 0x02, 0x10, 0x18, 0xc1, 0x84, 0x11, 0xe0, ++ 0x1d, 0xe0, 0xab, 0x82, 0xff, 0x21, 0x3a, 0x68, 0x41, 0x31, 0xd1, 0x20, 0x40, 0x02, 0x10, 0x18, ++ 0xc1, 0x84, 0xa8, 0x8a, 0x02, 0x20, 0xc0, 0x43, 0xa8, 0x82, 0x3a, 0x68, 0x00, 0x20, 0x6a, 0x49, ++ 0x51, 0x18, 0xc8, 0x80, 0xa8, 0x8a, 0xae, 0x82, 0x39, 0x68, 0x67, 0x48, 0x40, 0x30, 0x08, 0x18, ++ 0x44, 0x81, 0x60, 0x48, 0x00, 0x68, 0xc1, 0x7a, 0x49, 0x1c, 0xc1, 0x72, 0xfe, 0xbd, 0x03, 0x24, ++ 0x24, 0x07, 0xa0, 0x8a, 0x02, 0x20, 0xc0, 0x43, 0xa0, 0x82, 0x39, 0x68, 0x02, 0x20, 0x49, 0x19, ++ 0x48, 0x85, 0x38, 0x68, 0x40, 0x19, 0x80, 0x8d, 0xc0, 0x07, 0xc0, 0x0f, 0x1e, 0xd0, 0x15, 0xe0, ++ 0x42, 0xe3, 0xc2, 0xe1, 0xdd, 0xe2, 0x57, 0xe3, 0xd6, 0xe3, 0x51, 0xe2, 0xc2, 0xe2, 0xbd, 0xe2, ++ 0x66, 0xe3, 0xf3, 0xe2, 0xd1, 0xe2, 0xae, 0xe2, 0x97, 0xe2, 0x43, 0xe3, 0x2b, 0xe2, 0x03, 0xe2, ++ 0x80, 0xe2, 0xf9, 0xe1, 0xdf, 0xe1, 0xbd, 0xe2, 0xca, 0xe1, 0xc1, 0xe1, 0xa0, 0x8a, 0xa6, 0x82, ++ 0x39, 0x68, 0x00, 0x20, 0x49, 0x19, 0x88, 0x85, 0x02, 0xf0, 0x3c, 0xf9, 0x02, 0xf0, 0xe0, 0xf8, ++ 0x47, 0x48, 0x00, 0x78, 0xc0, 0x07, 0x01, 0xd0, 0x06, 0xf0, 0xe8, 0xfb, 0x44, 0x48, 0x02, 0x21, ++ 0x00, 0x88, 0x00, 0x23, 0x40, 0xba, 0x00, 0x91, 0x01, 0x90, 0x01, 0x22, 0x05, 0x21, 0x18, 0x46, ++ 0x06, 0xf0, 0x0a, 0xfe, 0x3e, 0x49, 0x00, 0x20, 0x08, 0x75, 0x02, 0xf0, 0xc6, 0xf9, 0xa0, 0x8a, ++ 0xa6, 0x82, 0x39, 0x68, 0x01, 0x20, 0x49, 0x19, 0x48, 0x85, 0xfe, 0xbd, 0x01, 0x46, 0x40, 0x31, ++ 0x4a, 0x7a, 0x34, 0x4d, 0x00, 0x2a, 0x05, 0xd0, 0x80, 0x78, 0x00, 0x28, 0x0e, 0xd1, 0x08, 0x7a, ++ 0x00, 0x28, 0x0b, 0xd0, 0x00, 0x20, 0x88, 0x72, 0x2c, 0x4b, 0x18, 0x68, 0x0d, 0x26, 0x76, 0x03, ++ 0x80, 0x19, 0x40, 0x8e, 0x80, 0x07, 0xc0, 0x0f, 0x1d, 0xd0, 0x26, 0xe0, 0x02, 0xf0, 0x8e, 0xf8, ++ 0xff, 0xf7, 0xb6, 0xfd, 0x00, 0x28, 0xef, 0xd0, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x86, 0x82, ++ 0x22, 0x49, 0x0b, 0x68, 0xd1, 0x22, 0x52, 0x02, 0x9b, 0x18, 0xdc, 0x84, 0x83, 0x8a, 0x86, 0x82, ++ 0x0b, 0x68, 0xff, 0x33, 0x01, 0x33, 0x9c, 0x85, 0x83, 0x8a, 0x86, 0x82, 0x09, 0x68, 0x00, 0x20, ++ 0x89, 0x18, 0xc8, 0x84, 0xd8, 0xe7, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x1f, 0x49, 0x81, 0x82, ++ 0x01, 0x20, 0x19, 0x68, 0x40, 0x03, 0x89, 0x19, 0x08, 0x84, 0x18, 0x68, 0x80, 0x19, 0x80, 0x8f, ++ 0xc2, 0x0a, 0x28, 0x68, 0x01, 0x46, 0x80, 0x31, 0x8a, 0x72, 0x01, 0x2a, 0x0c, 0xd0, 0x81, 0x7a, ++ 0x49, 0x1c, 0x81, 0x72, 0x18, 0x68, 0x80, 0x19, 0x40, 0x8f, 0x00, 0x23, 0xc0, 0xb2, 0x02, 0x22, ++ 0x07, 0x21, 0x00, 0x94, 0x01, 0x90, 0x0b, 0xe0, 0xc8, 0x7a, 0x01, 0x28, 0x0b, 0xd0, 0x18, 0x68, ++ 0x80, 0x19, 0x40, 0x8f, 0x00, 0x23, 0xc0, 0xb2, 0x02, 0x22, 0x06, 0x21, 0x00, 0x94, 0x01, 0x90, ++ 0x01, 0x20, 0x06, 0xf0, 0x99, 0xfd, 0x1c, 0xe1, 0xfe, 0xff, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0x60, 0xea, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, 0x00, 0xa3, 0x01, 0x00, 0xc0, 0xa1, 0x01, 0x00, ++ 0x00, 0x04, 0x00, 0x20, 0x0f, 0xfc, 0x00, 0x00, 0xc0, 0xa0, 0x01, 0x00, 0xff, 0xdf, 0x00, 0x00, ++ 0x01, 0x46, 0x40, 0x31, 0x8a, 0x7a, 0xf7, 0x4f, 0x00, 0x2a, 0x4c, 0x72, 0x03, 0xd0, 0x02, 0x20, ++ 0x00, 0x94, 0x01, 0x90, 0x04, 0xe1, 0xca, 0x79, 0x52, 0x08, 0x52, 0x00, 0xca, 0x71, 0x80, 0x78, ++ 0x00, 0x28, 0x58, 0xd1, 0x08, 0x7a, 0x00, 0x28, 0x55, 0xd0, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x20, 0x21, 0xc9, 0x43, 0x81, 0x82, 0xec, 0x48, 0x00, 0x21, 0x02, 0x68, 0x0d, 0x20, 0x40, 0x03, ++ 0x10, 0x18, 0x01, 0x84, 0x02, 0xf0, 0x4f, 0xfb, 0xe7, 0x49, 0x08, 0x68, 0x40, 0x19, 0xc0, 0x8a, ++ 0x09, 0x68, 0x00, 0x07, 0x00, 0x0f, 0xff, 0x31, 0x01, 0x31, 0x89, 0x8d, 0x00, 0x23, 0x89, 0x07, ++ 0xc9, 0x0f, 0x09, 0x01, 0x01, 0x43, 0x38, 0x68, 0x00, 0x88, 0x02, 0x0a, 0x12, 0x02, 0x11, 0x43, ++ 0x00, 0x06, 0x00, 0x0a, 0x01, 0x43, 0x03, 0x20, 0x01, 0x91, 0x00, 0x90, 0x02, 0x22, 0x1a, 0x21, ++ 0x01, 0x20, 0x06, 0xf0, 0x41, 0xfd, 0xd9, 0x48, 0x02, 0x21, 0x00, 0x88, 0x0a, 0x46, 0x40, 0xba, ++ 0x00, 0x91, 0x01, 0x90, 0x00, 0x23, 0x19, 0x21, 0x01, 0x20, 0x06, 0xf0, 0x35, 0xfd, 0x38, 0x68, ++ 0x80, 0x30, 0x84, 0x46, 0x00, 0x7a, 0x40, 0x06, 0x7e, 0xd4, 0xcf, 0x4d, 0x00, 0x22, 0x03, 0x21, ++ 0x09, 0x07, 0x88, 0x8a, 0x84, 0x20, 0xc0, 0x43, 0x88, 0x82, 0xd0, 0x07, 0x2e, 0x68, 0x00, 0x0e, ++ 0xcb, 0x4b, 0xf6, 0x18, 0x00, 0x1d, 0xb0, 0x85, 0x00, 0x20, 0x00, 0x21, 0x10, 0x28, 0x05, 0xd2, ++ 0x1f, 0x23, 0x1b, 0x1a, 0x04, 0xe0, 0x02, 0xf0, 0x76, 0xfa, 0xb5, 0xe7, 0x03, 0x46, 0x10, 0x3b, ++ 0xc4, 0x4f, 0xdb, 0xb2, 0xbe, 0x8a, 0x00, 0x2a, 0x07, 0xd0, 0x1f, 0x26, 0xf6, 0x43, 0xbe, 0x82, ++ 0x2f, 0x68, 0xbf, 0x4e, 0xbe, 0x19, 0xf3, 0x85, 0x06, 0xe0, 0xbf, 0x4e, 0xbe, 0x82, 0x2f, 0x68, ++ 0x1e, 0x02, 0xbb, 0x4b, 0xfb, 0x18, 0x9e, 0x85, 0xb9, 0x4f, 0x00, 0x23, 0x80, 0x37, 0x2e, 0x68, ++ 0xf6, 0x19, 0x36, 0x8a, 0x36, 0x0a, 0xf6, 0x07, 0xf6, 0x0f, 0x01, 0xd0, 0x49, 0x1c, 0xc9, 0xb2, ++ 0x5b, 0x1c, 0xdb, 0xb2, 0x0a, 0x2b, 0xf2, 0xd3, 0x00, 0x28, 0x04, 0xd0, 0x05, 0x29, 0x2d, 0xd8, ++ 0x1f, 0x28, 0x0f, 0xd0, 0x26, 0xe0, 0x05, 0x29, 0x24, 0xd9, 0x00, 0x2a, 0x17, 0xd0, 0xad, 0x48, ++ 0x81, 0x8a, 0x1f, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x2b, 0x68, 0x10, 0x21, 0xa8, 0x48, 0x18, 0x18, ++ 0xc1, 0x85, 0x1b, 0xe0, 0x00, 0x2a, 0x0a, 0xd0, 0xa6, 0x48, 0x81, 0x8a, 0x1f, 0x21, 0xc9, 0x43, ++ 0x81, 0x82, 0x2b, 0x68, 0x10, 0x20, 0xa2, 0x49, 0x59, 0x18, 0xc8, 0x85, 0x0e, 0xe0, 0xa1, 0x48, ++ 0x81, 0x8a, 0xa1, 0x49, 0x81, 0x82, 0x01, 0x20, 0x2b, 0x68, 0x00, 0x03, 0x9c, 0x49, 0x59, 0x18, ++ 0x88, 0x85, 0x03, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0x20, 0x28, 0x9e, 0xd3, 0x52, 0x1c, 0xd2, 0xb2, ++ 0x02, 0x2a, 0x8c, 0xd3, 0x97, 0x48, 0x81, 0x8a, 0x04, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x2a, 0x68, ++ 0x00, 0x20, 0x93, 0x49, 0x51, 0x18, 0x00, 0xe0, 0x06, 0xe0, 0x88, 0x85, 0x60, 0x46, 0x00, 0x7a, ++ 0x40, 0x21, 0x08, 0x43, 0x61, 0x46, 0x08, 0x72, 0x8e, 0x48, 0x81, 0x8a, 0x8f, 0x49, 0x81, 0x82, ++ 0x89, 0x48, 0x01, 0x22, 0x01, 0x68, 0x92, 0x03, 0x0d, 0x20, 0x40, 0x03, 0x08, 0x18, 0x02, 0x84, ++ 0x85, 0x48, 0x01, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x08, 0x18, 0x80, 0x8f, 0x81, 0x4d, 0xc0, 0x0a, ++ 0x29, 0x68, 0x80, 0x31, 0x88, 0x72, 0x03, 0x28, 0x05, 0xd0, 0xc9, 0x7a, 0x03, 0x29, 0x08, 0xd9, ++ 0x11, 0x29, 0x06, 0xd0, 0x0d, 0xe0, 0xc8, 0x7a, 0x03, 0x28, 0x0a, 0xd0, 0x01, 0x21, 0x25, 0x20, ++ 0x05, 0xe0, 0x03, 0x28, 0x05, 0xd9, 0x11, 0x28, 0x03, 0xd0, 0x01, 0x21, 0x26, 0x20, 0x06, 0xf0, ++ 0xf1, 0xfc, 0x28, 0x68, 0x40, 0x30, 0x84, 0x74, 0xfe, 0xbd, 0x44, 0x72, 0x00, 0x94, 0x01, 0x94, ++ 0x00, 0x23, 0x02, 0x22, 0x15, 0x21, 0x01, 0x20, 0x06, 0xf0, 0x6e, 0xfc, 0x71, 0x48, 0x81, 0x8a, ++ 0x86, 0x82, 0x6d, 0x48, 0x01, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x08, 0x18, 0x44, 0x86, 0xfe, 0xbd, ++ 0x11, 0x29, 0x0a, 0xd0, 0x00, 0x20, 0xc0, 0x43, 0x06, 0xf0, 0x62, 0xfa, 0x06, 0xf0, 0x75, 0xfa, ++ 0x28, 0x68, 0x8a, 0x21, 0x09, 0x5c, 0x07, 0x29, 0x03, 0xd0, 0x28, 0x68, 0x40, 0x30, 0x84, 0x72, ++ 0xfe, 0xbd, 0x81, 0x78, 0x00, 0x29, 0x06, 0xd1, 0x40, 0x30, 0x01, 0x7a, 0x00, 0x29, 0x02, 0xd0, ++ 0x13, 0x21, 0x81, 0x72, 0xd6, 0xe0, 0x03, 0xf0, 0x17, 0xf9, 0x02, 0x28, 0xf0, 0xd0, 0x5d, 0x48, ++ 0x81, 0x8a, 0x87, 0x82, 0x58, 0x4c, 0x80, 0x23, 0x26, 0x68, 0x0d, 0x22, 0x52, 0x03, 0xb6, 0x18, ++ 0x73, 0x80, 0x83, 0x8a, 0x87, 0x82, 0x21, 0x68, 0x00, 0x20, 0x89, 0x18, 0x48, 0x80, 0x28, 0x68, ++ 0x06, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfe, 0xbd, 0x04, 0xf0, 0xc3, 0xfd, 0x02, 0x28, 0xfa, 0xd0, ++ 0x04, 0xf0, 0xbf, 0xfd, 0x01, 0x28, 0xf6, 0xd0, 0x03, 0xf0, 0xcd, 0xfe, 0x02, 0x28, 0xf2, 0xd0, ++ 0x28, 0x68, 0x53, 0x21, 0x09, 0x5c, 0x00, 0x29, 0x04, 0xd0, 0x01, 0x29, 0x26, 0xd1, 0x01, 0x78, ++ 0x49, 0x07, 0x23, 0xd5, 0x00, 0x78, 0x00, 0x06, 0x20, 0xd4, 0x17, 0x20, 0x00, 0xf0, 0x82, 0xfa, ++ 0x03, 0xf0, 0xca, 0xf8, 0x28, 0x68, 0x05, 0x21, 0x41, 0x84, 0x09, 0x20, 0x03, 0xf0, 0x19, 0xff, ++ 0x03, 0xf0, 0x9a, 0xfc, 0x29, 0x68, 0x60, 0x31, 0x08, 0x70, 0x00, 0xf0, 0x48, 0xfa, 0x28, 0x68, ++ 0x0b, 0x21, 0x40, 0x30, 0x81, 0x72, 0x00, 0xf0, 0x8a, 0xfa, 0x00, 0x28, 0xcb, 0xd0, 0x04, 0xf0, ++ 0x8f, 0xf8, 0x28, 0x68, 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xee, 0xd0, 0x28, 0x68, 0x00, 0x23, ++ 0x60, 0x30, 0x02, 0x78, 0x41, 0x78, 0x12, 0x02, 0x80, 0x78, 0x11, 0x43, 0x00, 0x04, 0x01, 0x43, ++ 0x03, 0x20, 0x01, 0x22, 0x01, 0x91, 0x00, 0x90, 0x12, 0x21, 0x10, 0x46, 0x06, 0xf0, 0xe4, 0xfb, ++ 0x28, 0x68, 0x00, 0x21, 0x40, 0x30, 0x81, 0x74, 0x01, 0x75, 0x28, 0x68, 0x01, 0x46, 0x40, 0x31, ++ 0xca, 0x7a, 0x28, 0x2a, 0x01, 0xd0, 0x29, 0x2a, 0x02, 0xd1, 0x0a, 0x7d, 0x01, 0x2a, 0x73, 0xd0, ++ 0xca, 0x7c, 0x00, 0x2a, 0x04, 0xd0, 0x01, 0x2a, 0x0a, 0xd1, 0x03, 0x78, 0x5b, 0x07, 0x07, 0xd5, ++ 0x03, 0x78, 0x1b, 0x06, 0x04, 0xd4, 0x00, 0x23, 0x60, 0x30, 0x83, 0x71, 0x03, 0x72, 0x02, 0xe0, ++ 0x60, 0x30, 0x84, 0x71, 0x04, 0x72, 0x02, 0x2a, 0x27, 0xd3, 0x1a, 0x48, 0x82, 0x8a, 0x0f, 0x22, ++ 0xd2, 0x43, 0x82, 0x82, 0x14, 0x4a, 0x02, 0x24, 0x15, 0x68, 0x0d, 0x23, 0x5b, 0x03, 0xed, 0x18, ++ 0x2c, 0x86, 0x84, 0x8a, 0x16, 0x4c, 0x84, 0x82, 0x12, 0x68, 0x00, 0x15, 0xd2, 0x18, 0x10, 0x86, ++ 0x09, 0x20, 0x27, 0xe1, 0x00, 0x21, 0x81, 0x72, 0x0e, 0x48, 0x82, 0x8a, 0x0f, 0x22, 0xd2, 0x43, ++ 0x82, 0x82, 0x09, 0x4a, 0x13, 0x68, 0x0d, 0x26, 0x76, 0x03, 0x9b, 0x19, 0x19, 0x86, 0x83, 0x8a, ++ 0x0b, 0x4b, 0x83, 0x82, 0x10, 0x68, 0x80, 0x19, 0x01, 0x86, 0x04, 0xf0, 0xb1, 0xfc, 0x00, 0x28, ++ 0x10, 0xd0, 0x60, 0xe7, 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, ++ 0x00, 0xa1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xbf, 0x00, 0x00, ++ 0xff, 0xfc, 0x00, 0x00, 0x52, 0xe0, 0x03, 0xf0, 0x53, 0xfe, 0x02, 0x28, 0xe9, 0xd0, 0x28, 0x68, ++ 0x80, 0x30, 0xc1, 0x7b, 0x00, 0x29, 0x18, 0xd0, 0x00, 0x21, 0xc1, 0x73, 0x04, 0xf0, 0xd2, 0xfd, ++ 0x00, 0x28, 0xde, 0xd1, 0x92, 0x49, 0x0a, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x12, 0x18, 0x92, 0x8e, ++ 0xd2, 0x07, 0x7d, 0xd0, 0x28, 0x68, 0x88, 0x21, 0x09, 0x5c, 0x49, 0x07, 0x79, 0xd5, 0x40, 0x30, ++ 0xc0, 0x7c, 0x00, 0x28, 0x76, 0xd0, 0xe3, 0xe0, 0x44, 0xe0, 0x04, 0xf0, 0xa2, 0xfb, 0x02, 0x28, ++ 0xc7, 0xd0, 0x28, 0x68, 0x40, 0x30, 0x81, 0x79, 0x49, 0x07, 0x05, 0xd5, 0x80, 0x7d, 0x01, 0x28, ++ 0x02, 0xd0, 0x04, 0xf0, 0xd4, 0xf9, 0x01, 0xe0, 0x04, 0xf0, 0x27, 0xfa, 0x02, 0x28, 0xb8, 0xd0, ++ 0x28, 0x68, 0x84, 0x21, 0x09, 0x5c, 0x00, 0x29, 0x4e, 0xd1, 0x60, 0x30, 0x81, 0x79, 0x02, 0x29, ++ 0x02, 0xd0, 0x00, 0x29, 0x02, 0xd0, 0x05, 0xe0, 0x84, 0x71, 0x08, 0xe0, 0x04, 0xf0, 0xb5, 0xfa, ++ 0x02, 0x28, 0xa6, 0xd0, 0x28, 0x68, 0x60, 0x30, 0x80, 0x79, 0x01, 0x28, 0xb3, 0xd1, 0x28, 0x68, ++ 0x60, 0x30, 0x01, 0x7a, 0x02, 0x29, 0x1c, 0xd0, 0x04, 0xf0, 0x93, 0xf8, 0x28, 0x68, 0x60, 0x30, ++ 0x81, 0x79, 0x01, 0x29, 0xa7, 0xd1, 0x00, 0x7a, 0x01, 0x28, 0xa4, 0xd1, 0x28, 0x68, 0x40, 0x30, ++ 0x81, 0x7d, 0x01, 0x29, 0x06, 0xd0, 0x01, 0x7d, 0x49, 0x1c, 0xc9, 0xb2, 0x01, 0x75, 0x04, 0x29, ++ 0x00, 0xd2, 0x3a, 0xe7, 0x29, 0x68, 0x0a, 0x46, 0x40, 0x32, 0xd0, 0x7c, 0x00, 0x28, 0x02, 0xd0, ++ 0x23, 0xe0, 0x04, 0x72, 0xea, 0xe7, 0x08, 0x88, 0x43, 0x07, 0x1e, 0xd5, 0x0b, 0x79, 0x1e, 0x06, ++ 0x05, 0xd5, 0x58, 0x06, 0x40, 0x0e, 0xd0, 0x73, 0x00, 0xf0, 0xee, 0xfb, 0x15, 0xe0, 0x83, 0x06, ++ 0x9b, 0x0f, 0x02, 0x2b, 0x11, 0xd0, 0x92, 0x79, 0x12, 0x07, 0x0e, 0xd5, 0x00, 0x06, 0x0c, 0xd4, ++ 0x80, 0x31, 0x48, 0x7b, 0xc0, 0x06, 0x08, 0xd4, 0x04, 0xf0, 0x92, 0xfe, 0x02, 0x28, 0x97, 0xd0, ++ 0x28, 0x68, 0x80, 0x30, 0x00, 0x79, 0x00, 0x28, 0x8f, 0xd1, 0x95, 0x21, 0x28, 0x68, 0x02, 0xe0, ++ 0x2b, 0xe0, 0x73, 0xe0, 0x68, 0xe0, 0x09, 0x5c, 0x00, 0x29, 0x0d, 0xd0, 0x40, 0x30, 0xc1, 0x7a, ++ 0x2c, 0x29, 0x09, 0xd0, 0x16, 0x21, 0x81, 0x72, 0xff, 0xf7, 0xba, 0xf9, 0x28, 0x68, 0x40, 0x30, ++ 0xc0, 0x7a, 0x2c, 0x28, 0x00, 0xd0, 0xa6, 0xe6, 0x28, 0x68, 0x56, 0x21, 0x09, 0x5c, 0x01, 0x29, ++ 0x00, 0xd1, 0x5b, 0xe7, 0x01, 0x78, 0x09, 0x06, 0xfb, 0xd4, 0x00, 0x21, 0x60, 0x30, 0xc1, 0x71, ++ 0x04, 0xf0, 0x57, 0xfb, 0x02, 0x28, 0xee, 0xd0, 0x28, 0x68, 0x60, 0x30, 0xc0, 0x79, 0x00, 0x28, ++ 0xf6, 0xd0, 0x28, 0x68, 0x80, 0x30, 0xc4, 0x73, 0x3d, 0xe7, 0x03, 0x26, 0x36, 0x07, 0xb2, 0x8a, ++ 0x38, 0x4b, 0xb3, 0x82, 0x36, 0x4a, 0x00, 0x27, 0x11, 0x68, 0x09, 0x18, 0x0f, 0x84, 0xb1, 0x8a, ++ 0xb3, 0x82, 0x12, 0x68, 0x20, 0x21, 0x10, 0x18, 0x01, 0x84, 0x06, 0xf0, 0xd5, 0xf8, 0x40, 0x1c, ++ 0x40, 0x42, 0x01, 0x21, 0xc0, 0x08, 0x09, 0x04, 0x88, 0x42, 0x01, 0xd3, 0x49, 0x1e, 0x00, 0xe0, ++ 0x81, 0xb2, 0x28, 0x68, 0x41, 0x82, 0x01, 0x7b, 0x49, 0x1c, 0x01, 0x73, 0x40, 0x30, 0x04, 0x72, ++ 0x02, 0x21, 0x0e, 0x20, 0x06, 0xf0, 0x0e, 0xfb, 0x28, 0x68, 0x01, 0x46, 0x80, 0x30, 0x42, 0x7d, ++ 0x00, 0x2a, 0x0b, 0xd0, 0x42, 0x7e, 0x00, 0x2a, 0x08, 0xd0, 0xb2, 0x8a, 0x07, 0x22, 0xd2, 0x43, ++ 0xb2, 0x82, 0x1f, 0x4a, 0x12, 0x68, 0x20, 0x4b, 0xd2, 0x18, 0x17, 0x85, 0x07, 0x73, 0x40, 0x31, ++ 0x8c, 0x74, 0x02, 0x20, 0x88, 0x72, 0xfe, 0xbd, 0x03, 0xf0, 0x26, 0xf8, 0x02, 0x28, 0xfa, 0xd0, ++ 0x28, 0x68, 0xfb, 0x22, 0x80, 0x30, 0x01, 0x7a, 0x11, 0x40, 0x01, 0x72, 0x1f, 0x20, 0x03, 0xf0, ++ 0xd8, 0xfd, 0x28, 0x68, 0x15, 0x21, 0x40, 0x30, 0x81, 0x72, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x87, 0x82, 0x0f, 0x48, 0x80, 0x21, 0x02, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x10, 0x18, 0x01, 0x84, ++ 0x29, 0x68, 0xff, 0x20, 0x80, 0x31, 0x88, 0x72, 0x28, 0x68, 0x40, 0x30, 0x84, 0x74, 0x00, 0xf0, ++ 0xe6, 0xf8, 0x00, 0x28, 0xd7, 0xd0, 0x28, 0x68, 0x01, 0x7a, 0xc9, 0x09, 0xe5, 0xd1, 0x90, 0x21, ++ 0x09, 0x5c, 0x00, 0x29, 0xe1, 0xd1, 0x40, 0x30, 0x84, 0x75, 0xff, 0xf7, 0x91, 0xf8, 0x67, 0xe6, ++ 0x84, 0x00, 0x00, 0x20, 0xdf, 0xff, 0x00, 0x00, 0x80, 0xa0, 0x01, 0x00, 0x00, 0x28, 0x16, 0xd0, ++ 0x01, 0x28, 0x15, 0xd0, 0x00, 0x21, 0x40, 0x00, 0x40, 0x08, 0x49, 0x1c, 0x40, 0x00, 0x49, 0xb2, ++ 0x00, 0x28, 0xfa, 0xda, 0xc0, 0x0d, 0xe0, 0x22, 0x10, 0x40, 0xca, 0x17, 0xd2, 0x0e, 0x52, 0x18, ++ 0x52, 0x09, 0x52, 0x01, 0x89, 0x1a, 0x1f, 0x22, 0x51, 0x1a, 0x40, 0x18, 0xc0, 0xb2, 0x70, 0x47, ++ 0xe0, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x03, 0x24, 0x24, 0x07, 0xa1, 0x8a, 0xfa, 0x49, 0xa1, 0x82, ++ 0x00, 0x28, 0x01, 0xdd, 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0xf8, 0x4a, 0x89, 0x02, 0xf8, 0x4e, ++ 0x89, 0x18, 0x32, 0x68, 0x0d, 0x27, 0x7f, 0x03, 0xd2, 0x19, 0x11, 0x81, 0x01, 0x23, 0x00, 0x21, ++ 0x5b, 0x02, 0x45, 0x42, 0x07, 0xe0, 0xa2, 0x8a, 0xf2, 0x4a, 0xa2, 0x82, 0x32, 0x68, 0xd2, 0x19, ++ 0x13, 0x81, 0x49, 0x1c, 0x49, 0xb2, 0x00, 0x28, 0x01, 0xdb, 0x02, 0x46, 0x00, 0xe0, 0x2a, 0x46, ++ 0x8a, 0x42, 0xf0, 0xdc, 0xf0, 0xbd, 0xf0, 0xb5, 0xeb, 0x48, 0x53, 0x21, 0x00, 0x68, 0x01, 0x23, ++ 0x09, 0x5c, 0x0d, 0x27, 0x03, 0x24, 0xe7, 0x4a, 0x5b, 0x02, 0x7f, 0x03, 0x24, 0x07, 0xe4, 0x4d, ++ 0x00, 0x29, 0x0c, 0xd0, 0x26, 0x21, 0x41, 0x5e, 0xe4, 0x4e, 0x08, 0x46, 0x11, 0x30, 0x0c, 0xd0, ++ 0x0f, 0x29, 0x17, 0xd0, 0xa0, 0x8a, 0xa2, 0x82, 0x28, 0x68, 0xc0, 0x19, 0x03, 0x81, 0xa0, 0x8a, ++ 0xa2, 0x82, 0x28, 0x68, 0xc0, 0x19, 0x03, 0x81, 0x1b, 0xe0, 0x3e, 0x20, 0xc0, 0x43, 0xff, 0xf7, ++ 0xb1, 0xff, 0x01, 0x20, 0xff, 0xf7, 0xae, 0xff, 0xa0, 0x8a, 0xff, 0x20, 0xa0, 0x82, 0x01, 0x20, ++ 0x80, 0x02, 0x0b, 0xe0, 0x3e, 0x20, 0xc0, 0x43, 0xff, 0xf7, 0xa4, 0xff, 0x01, 0x20, 0xff, 0xf7, ++ 0xa1, 0xff, 0xa0, 0x8a, 0xff, 0x20, 0xa0, 0x82, 0x01, 0x20, 0xc0, 0x02, 0x29, 0x68, 0x89, 0x19, ++ 0x88, 0x84, 0xcd, 0x48, 0x00, 0x68, 0xc1, 0x8c, 0x49, 0x1c, 0xc1, 0x84, 0xf0, 0xbd, 0x30, 0xb5, ++ 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xca, 0x4a, 0x82, 0x82, 0xc5, 0x49, 0x00, 0x24, 0x0d, 0x68, ++ 0xc6, 0x4b, 0xed, 0x18, 0x2c, 0x84, 0x84, 0x8a, 0x82, 0x82, 0x0c, 0x68, 0x52, 0x1c, 0xe3, 0x18, ++ 0x1a, 0x84, 0x82, 0x8a, 0x80, 0x22, 0xd2, 0x43, 0x82, 0x82, 0x09, 0x68, 0x80, 0x20, 0x0d, 0x22, ++ 0x52, 0x03, 0x89, 0x18, 0x08, 0x84, 0xbc, 0x48, 0xff, 0x21, 0x00, 0x68, 0x80, 0x30, 0x81, 0x72, ++ 0x30, 0xbd, 0xb7, 0x48, 0x00, 0x68, 0xb9, 0x49, 0x40, 0x18, 0x80, 0x8e, 0x80, 0x04, 0x80, 0x16, ++ 0x40, 0x42, 0x70, 0x47, 0x30, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8a, 0x13, 0x8a, 0x82, ++ 0x42, 0x42, 0x92, 0x06, 0x0d, 0x23, 0xd2, 0x0d, 0x5b, 0x02, 0xd4, 0x18, 0xac, 0x4b, 0x1d, 0x68, ++ 0xae, 0x4a, 0xad, 0x18, 0xec, 0x82, 0x8c, 0x8a, 0xad, 0x4c, 0x8c, 0x82, 0x1b, 0x68, 0x61, 0x1c, ++ 0x9a, 0x18, 0xd1, 0x82, 0xa8, 0x49, 0x09, 0x68, 0x60, 0x31, 0x48, 0x70, 0x30, 0xbd, 0xa6, 0x48, ++ 0x00, 0x68, 0x80, 0x30, 0x80, 0x7a, 0x07, 0x28, 0x01, 0xd0, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, ++ 0x70, 0x47, 0x70, 0xb5, 0xa0, 0x48, 0x00, 0x21, 0x04, 0x68, 0x22, 0x7f, 0xa3, 0x7d, 0x9a, 0x42, ++ 0x01, 0xd3, 0xd0, 0x1a, 0x02, 0xe0, 0xbf, 0x20, 0xc0, 0x1a, 0x80, 0x18, 0xc5, 0xb2, 0xe0, 0x8c, ++ 0x63, 0x28, 0x01, 0xd1, 0x01, 0x21, 0xc9, 0x03, 0xbf, 0x2a, 0x01, 0xd3, 0x00, 0x20, 0x00, 0xe0, ++ 0x50, 0x1c, 0xc0, 0xb2, 0x83, 0x42, 0x02, 0xd1, 0x01, 0x26, 0xb6, 0x03, 0x31, 0x43, 0x9a, 0x42, ++ 0x02, 0xd1, 0x01, 0x22, 0x52, 0x03, 0x11, 0x43, 0x29, 0x43, 0xa1, 0x82, 0x70, 0xbd, 0x70, 0xb5, ++ 0xff, 0xf7, 0xd7, 0xff, 0x05, 0x46, 0xff, 0xf7, 0xca, 0xff, 0x00, 0x28, 0x63, 0xd0, 0x8a, 0x4c, ++ 0x21, 0x68, 0x08, 0x7d, 0xbb, 0x28, 0x5e, 0xd2, 0x26, 0x22, 0x8a, 0x5e, 0x63, 0x2a, 0x5a, 0xd0, ++ 0x40, 0x31, 0xce, 0x7c, 0x82, 0x48, 0x85, 0x49, 0x86, 0x4b, 0x00, 0x2e, 0x16, 0xd0, 0x10, 0x32, ++ 0x1f, 0x2a, 0x02, 0x68, 0x1d, 0xd8, 0x56, 0x18, 0x28, 0x22, 0xb2, 0x5e, 0x00, 0x68, 0x92, 0x02, ++ 0x40, 0x18, 0x40, 0x8d, 0xc0, 0xb2, 0x10, 0x43, 0xff, 0xf7, 0xd8, 0xfe, 0x02, 0x46, 0x20, 0x68, ++ 0x44, 0x21, 0x09, 0x5a, 0x00, 0x7f, 0x08, 0x18, 0x1a, 0x54, 0x1c, 0xe0, 0x02, 0x68, 0x56, 0x18, ++ 0x30, 0x22, 0xb2, 0x5e, 0x00, 0x68, 0x92, 0x02, 0x40, 0x18, 0x40, 0x8e, 0x80, 0x05, 0x80, 0x0d, ++ 0x07, 0xe0, 0x56, 0x18, 0x2c, 0x22, 0xb2, 0x5e, 0x00, 0x68, 0x92, 0x02, 0x40, 0x18, 0xc0, 0x8d, ++ 0xc0, 0xb2, 0x10, 0x43, 0xff, 0xf7, 0xba, 0xfe, 0x01, 0x46, 0x20, 0x68, 0x44, 0x22, 0x12, 0x5a, ++ 0x00, 0x7f, 0x10, 0x18, 0x19, 0x54, 0x20, 0x68, 0x05, 0x77, 0xff, 0xf7, 0x5a, 0xff, 0x1f, 0x21, ++ 0xc8, 0x42, 0x1c, 0xdc, 0x20, 0x68, 0x44, 0x22, 0x12, 0x5a, 0x04, 0x7f, 0x00, 0x21, 0x12, 0x19, ++ 0x99, 0x54, 0x01, 0x7f, 0xbf, 0x29, 0x01, 0xd3, 0x00, 0x21, 0x00, 0xe0, 0x49, 0x1c, 0x01, 0x77, ++ 0x26, 0x21, 0x41, 0x5e, 0x1f, 0x29, 0x07, 0xda, 0xff, 0xf7, 0xdd, 0xfe, 0x1f, 0x20, 0xff, 0xf7, ++ 0x49, 0xff, 0xff, 0xf7, 0x1c, 0xff, 0x70, 0xbd, 0x63, 0x21, 0xc1, 0x84, 0x70, 0xbd, 0xff, 0xf7, ++ 0x38, 0xff, 0x40, 0x1e, 0x40, 0xb2, 0xf2, 0xe7, 0xf0, 0xb5, 0xff, 0xf7, 0x62, 0xff, 0x07, 0x46, ++ 0xff, 0xf7, 0x55, 0xff, 0x00, 0x28, 0x6f, 0xd0, 0x4f, 0x4e, 0x30, 0x68, 0x01, 0x7d, 0xbb, 0x29, ++ 0x6a, 0xd2, 0x26, 0x21, 0x41, 0x5e, 0x63, 0x29, 0x66, 0xd0, 0x40, 0x30, 0xc0, 0x7c, 0x48, 0x4c, ++ 0x4a, 0x4d, 0x4c, 0x4b, 0x00, 0x28, 0x0b, 0xd0, 0x10, 0x31, 0x20, 0x68, 0x1f, 0x29, 0x12, 0xd8, ++ 0x41, 0x19, 0x28, 0x20, 0x08, 0x5e, 0x21, 0x68, 0x80, 0x02, 0x49, 0x19, 0x49, 0x8d, 0x11, 0xe0, ++ 0x20, 0x68, 0x41, 0x19, 0x30, 0x20, 0x08, 0x5e, 0x21, 0x68, 0x80, 0x02, 0x49, 0x19, 0x49, 0x8e, ++ 0x89, 0x05, 0x89, 0x0d, 0x07, 0xe0, 0x41, 0x19, 0x2c, 0x20, 0x08, 0x5e, 0x21, 0x68, 0x80, 0x02, ++ 0x49, 0x19, 0xc9, 0x8d, 0xc9, 0xb2, 0x08, 0x43, 0xff, 0xf7, 0x50, 0xfe, 0x01, 0x46, 0x30, 0x68, ++ 0x44, 0x22, 0x12, 0x5a, 0x00, 0x7f, 0x10, 0x18, 0x19, 0x54, 0x30, 0x68, 0x26, 0x21, 0x07, 0x77, ++ 0x41, 0x5e, 0x1f, 0x29, 0x02, 0xda, 0xff, 0xf7, 0x86, 0xfe, 0x2b, 0xe0, 0x44, 0x22, 0x12, 0x5a, ++ 0x00, 0x21, 0xd2, 0x19, 0x99, 0x54, 0x01, 0x7f, 0xbf, 0x29, 0x01, 0xd3, 0x00, 0x21, 0x00, 0xe0, ++ 0x49, 0x1c, 0x01, 0x77, 0xff, 0xf7, 0xdd, 0xfe, 0x1e, 0x27, 0xff, 0x43, 0xb8, 0x42, 0x24, 0xdd, ++ 0x30, 0x68, 0x40, 0x30, 0xc0, 0x7c, 0x00, 0x28, 0x17, 0xd0, 0x04, 0x20, 0xff, 0xf7, 0x42, 0xfe, ++ 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xff, 0x21, 0x81, 0x82, 0x01, 0x20, 0x21, 0x68, 0x40, 0x02, ++ 0x49, 0x19, 0x88, 0x84, 0x30, 0x68, 0xc7, 0x84, 0xff, 0xf7, 0xc3, 0xfe, 0x40, 0x1e, 0x40, 0xb2, ++ 0xff, 0xf7, 0xc8, 0xfe, 0xff, 0xf7, 0x9b, 0xfe, 0xf0, 0xbd, 0x3e, 0x20, 0xc0, 0x43, 0xff, 0xf7, ++ 0x29, 0xfe, 0x01, 0x20, 0xff, 0xf7, 0x26, 0xfe, 0xec, 0xe7, 0x31, 0x68, 0x63, 0x20, 0xc8, 0x84, ++ 0xf0, 0xbd, 0x10, 0xb5, 0x05, 0xf0, 0x3e, 0xfe, 0x0f, 0x49, 0x02, 0x0c, 0x09, 0x68, 0x08, 0x87, ++ 0xca, 0x86, 0x88, 0x84, 0x4a, 0x84, 0x10, 0xbd, 0x10, 0xb5, 0x09, 0x4a, 0x11, 0x68, 0x0e, 0x4b, ++ 0xc9, 0x18, 0x89, 0x8e, 0x00, 0x24, 0x49, 0x04, 0x04, 0x70, 0x48, 0x08, 0x11, 0x68, 0xc9, 0x18, ++ 0xc9, 0x8e, 0x08, 0x43, 0x10, 0xbd, 0x00, 0x00, 0x80, 0x8b, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, ++ 0x84, 0x00, 0x00, 0x20, 0xff, 0xfd, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, ++ 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x80, 0xa1, 0x01, 0x00, 0x10, 0xb5, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0xff, 0x21, 0x04, 0x31, 0x81, 0x82, 0xff, 0x4a, 0x00, 0x21, 0x14, 0x68, ++ 0xfe, 0x4b, 0xe4, 0x18, 0x21, 0x84, 0x84, 0x8a, 0x81, 0x82, 0x14, 0x68, 0xe4, 0x18, 0x61, 0x84, ++ 0x84, 0x8a, 0x81, 0x82, 0x14, 0x68, 0xe4, 0x18, 0xa1, 0x84, 0x84, 0x8a, 0x81, 0x82, 0x10, 0x68, ++ 0xc0, 0x18, 0xc1, 0x84, 0xce, 0xe7, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xdf, 0xff, 0x03, 0x21, ++ 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0xef, 0x48, 0xe2, 0x06, 0x03, 0x68, ++ 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0xec, 0x4a, 0x8a, 0x82, ++ 0x04, 0x68, 0x0b, 0x14, 0xe9, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, ++ 0x01, 0x23, 0x04, 0x68, 0x9b, 0x02, 0xa4, 0x18, 0xa3, 0x84, 0x8b, 0x8a, 0x03, 0x23, 0xdb, 0x43, ++ 0x8b, 0x82, 0x00, 0x68, 0x03, 0x21, 0x80, 0x18, 0xc1, 0x84, 0xa3, 0xe7, 0x10, 0xb5, 0x1f, 0x20, ++ 0xff, 0xf7, 0xd1, 0xff, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x30, 0x21, 0xc9, 0x43, 0x81, 0x82, ++ 0xd9, 0x49, 0x10, 0x22, 0x0b, 0x68, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x84, 0x82, 0x8a, ++ 0xd8, 0x4a, 0x82, 0x82, 0x01, 0x20, 0x09, 0x68, 0x80, 0x02, 0xd7, 0x4a, 0x89, 0x18, 0x48, 0x84, ++ 0x88, 0xe7, 0xf8, 0xb5, 0xd5, 0x4e, 0x26, 0x21, 0x30, 0x68, 0x41, 0x5e, 0x0c, 0x12, 0x4d, 0xb2, ++ 0x29, 0x46, 0x1f, 0x31, 0x3f, 0x29, 0x04, 0xd2, 0x1f, 0x2c, 0x02, 0xdc, 0x1f, 0x21, 0xcc, 0x42, ++ 0x09, 0xda, 0x01, 0x22, 0xe1, 0xb2, 0xd2, 0x03, 0x89, 0x18, 0x81, 0x82, 0x80, 0x30, 0x44, 0x70, ++ 0x85, 0x70, 0x01, 0x20, 0xf8, 0xbd, 0xff, 0xf7, 0x04, 0xfe, 0x31, 0x68, 0x40, 0x31, 0x48, 0x76, ++ 0x28, 0x46, 0xff, 0xf7, 0x07, 0xfe, 0xff, 0xf7, 0xc1, 0xff, 0x31, 0x68, 0x53, 0x20, 0x40, 0x5c, ++ 0x00, 0x28, 0x0e, 0xd0, 0x03, 0x20, 0x10, 0x27, 0x00, 0x07, 0xff, 0x22, 0xba, 0x4b, 0xfc, 0x42, ++ 0x09, 0xda, 0x67, 0x00, 0x40, 0x37, 0xcf, 0x84, 0x87, 0x8a, 0x82, 0x82, 0x01, 0x22, 0x52, 0x02, ++ 0x0a, 0xe0, 0xcc, 0x84, 0x0f, 0xe0, 0x0f, 0x2c, 0x0b, 0xdd, 0x67, 0x00, 0x3c, 0x3f, 0xcf, 0x84, ++ 0x87, 0x8a, 0x82, 0x82, 0x01, 0x22, 0xd2, 0x02, 0x1b, 0x68, 0xb0, 0x48, 0x18, 0x18, 0x82, 0x84, ++ 0x01, 0xe0, 0x60, 0x00, 0xc8, 0x84, 0xc8, 0x8c, 0x40, 0xb2, 0xff, 0xf7, 0x43, 0xfd, 0x68, 0x46, ++ 0xff, 0xf7, 0x2a, 0xff, 0xff, 0xf7, 0x1d, 0xff, 0xff, 0xf7, 0xa9, 0xfd, 0x30, 0x68, 0x01, 0x21, ++ 0x81, 0x82, 0x80, 0x30, 0x44, 0x70, 0x85, 0x70, 0x00, 0x20, 0xf8, 0xbd, 0xf0, 0xb5, 0xa2, 0x4c, ++ 0x21, 0x68, 0x0d, 0x23, 0x5b, 0x03, 0xc9, 0x18, 0x89, 0x8a, 0xa4, 0x4a, 0x09, 0x12, 0x15, 0x68, ++ 0x77, 0x22, 0x52, 0x5d, 0x09, 0x18, 0x51, 0x18, 0x49, 0x00, 0x49, 0xb2, 0x49, 0x10, 0x03, 0x22, ++ 0x12, 0x07, 0x96, 0x8a, 0x9a, 0x4e, 0x0c, 0x36, 0x96, 0x82, 0x01, 0x26, 0x27, 0x68, 0x76, 0x03, ++ 0xff, 0x18, 0x3e, 0x81, 0x0f, 0x06, 0x97, 0x4e, 0x97, 0x8a, 0x96, 0x82, 0x05, 0xd5, 0x27, 0x68, ++ 0x00, 0x26, 0xff, 0x18, 0x3e, 0x81, 0x49, 0x42, 0x04, 0xe0, 0x01, 0x26, 0x27, 0x68, 0xb6, 0x02, ++ 0xff, 0x18, 0x3e, 0x81, 0x96, 0x8a, 0x7f, 0x26, 0xf6, 0x43, 0x96, 0x82, 0x27, 0x68, 0x01, 0x26, ++ 0xff, 0x18, 0x3e, 0x81, 0x00, 0x26, 0x0a, 0xe0, 0x94, 0x8a, 0x8d, 0x4c, 0x94, 0x82, 0x86, 0x4f, ++ 0x01, 0x24, 0x3f, 0x68, 0x64, 0x02, 0xff, 0x18, 0x3c, 0x81, 0x76, 0x1c, 0x76, 0xb2, 0x8e, 0x42, ++ 0xf2, 0xdb, 0x40, 0x35, 0x28, 0x74, 0xf0, 0xbd, 0xf0, 0xb5, 0x7f, 0x4d, 0x29, 0x68, 0x0d, 0x26, ++ 0x76, 0x03, 0x89, 0x19, 0x89, 0x8a, 0x03, 0x24, 0x08, 0x18, 0x40, 0x00, 0x40, 0xb2, 0x40, 0x10, ++ 0x24, 0x07, 0xa1, 0x8a, 0x7a, 0x49, 0x0c, 0x31, 0xa1, 0x82, 0x01, 0x21, 0x2a, 0x68, 0x89, 0x03, ++ 0x92, 0x19, 0x11, 0x81, 0x03, 0x06, 0x00, 0x21, 0x00, 0x2b, 0x76, 0x4a, 0xa3, 0x8a, 0xa2, 0x82, ++ 0x04, 0xda, 0x2a, 0x68, 0x92, 0x19, 0x11, 0x81, 0x40, 0x42, 0x04, 0xe0, 0x01, 0x22, 0x2b, 0x68, ++ 0x92, 0x02, 0x9b, 0x19, 0x1a, 0x81, 0x71, 0x4a, 0x71, 0x4f, 0x12, 0x68, 0x40, 0x32, 0x93, 0x7b, ++ 0x01, 0x22, 0x52, 0x02, 0x00, 0x2b, 0x13, 0xd0, 0xa1, 0x8a, 0x7f, 0x21, 0xc9, 0x43, 0xa1, 0x82, ++ 0x2b, 0x68, 0x01, 0x21, 0x9b, 0x19, 0x19, 0x81, 0x00, 0x21, 0x06, 0xe0, 0xa3, 0x8a, 0xa7, 0x82, ++ 0x2b, 0x68, 0x9b, 0x19, 0x1a, 0x81, 0x49, 0x1c, 0x49, 0xb2, 0x81, 0x42, 0xf6, 0xdb, 0xf0, 0xbd, ++ 0xa3, 0x8a, 0x64, 0x4b, 0xa3, 0x82, 0x40, 0x06, 0x01, 0x23, 0x40, 0x0e, 0xdb, 0x02, 0xc0, 0x18, ++ 0x2b, 0x68, 0x9b, 0x19, 0x18, 0x81, 0xa0, 0x8a, 0xa7, 0x82, 0x28, 0x68, 0x80, 0x19, 0x02, 0x81, ++ 0xa0, 0x8a, 0x5c, 0x48, 0x7f, 0x30, 0xa0, 0x82, 0x28, 0x68, 0x80, 0x19, 0x01, 0x81, 0xf0, 0xbd, ++ 0x0f, 0x30, 0x40, 0x10, 0x70, 0x47, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8a, 0x13, ++ 0x8a, 0x82, 0xc0, 0x05, 0x11, 0x22, 0xc0, 0x0d, 0x52, 0x02, 0x83, 0x18, 0x4a, 0x4a, 0x14, 0x68, ++ 0x4a, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0x4f, 0x4b, 0x8b, 0x82, 0x12, 0x68, 0x59, 0x1c, ++ 0x10, 0x18, 0xc1, 0x82, 0x6e, 0xe6, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8a, 0x13, ++ 0x8a, 0x82, 0xc0, 0x05, 0x09, 0x22, 0xc0, 0x0d, 0x92, 0x02, 0x83, 0x18, 0x3e, 0x4a, 0x14, 0x68, ++ 0x3e, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0x43, 0x4b, 0x8b, 0x82, 0x12, 0x68, 0x59, 0x1c, ++ 0x10, 0x18, 0xc1, 0x82, 0x56, 0xe6, 0x10, 0xb5, 0x3c, 0x4c, 0x20, 0x68, 0xc2, 0x7d, 0x01, 0x46, ++ 0x53, 0x07, 0x40, 0x31, 0x00, 0x2b, 0x14, 0xda, 0x92, 0x07, 0x0d, 0xd4, 0x81, 0x21, 0x41, 0x56, ++ 0x0f, 0x31, 0x48, 0x10, 0xff, 0xf7, 0xd7, 0xff, 0x21, 0x68, 0x82, 0x20, 0x08, 0x56, 0x0f, 0x30, ++ 0x40, 0x10, 0xff, 0xf7, 0xb8, 0xff, 0x0d, 0xe0, 0x0f, 0x20, 0x08, 0x56, 0xff, 0xf7, 0x54, 0xff, ++ 0x08, 0xe0, 0x19, 0x20, 0x08, 0x56, 0xff, 0xf7, 0xd5, 0xfc, 0x21, 0x68, 0x50, 0x20, 0x08, 0x56, ++ 0xff, 0xf7, 0x04, 0xff, 0x21, 0x68, 0x01, 0x20, 0x48, 0x74, 0x2b, 0xe6, 0x70, 0xb5, 0x06, 0x46, ++ 0x05, 0xf0, 0x50, 0xfc, 0x25, 0x4d, 0x04, 0x46, 0x28, 0x68, 0x22, 0x30, 0x05, 0xf0, 0x64, 0xff, ++ 0x01, 0x46, 0x10, 0x20, 0xc1, 0x41, 0x60, 0x1a, 0x30, 0x60, 0x2d, 0x68, 0x28, 0x46, 0x36, 0x30, ++ 0x05, 0xf0, 0x5a, 0xff, 0x01, 0x46, 0x10, 0x20, 0xc1, 0x41, 0x20, 0x48, 0x6a, 0x7c, 0x61, 0x1a, ++ 0x40, 0x7c, 0x05, 0x2a, 0x04, 0xd0, 0x40, 0x04, 0x88, 0x42, 0x03, 0xd2, 0x01, 0x20, 0x70, 0xbd, ++ 0xc0, 0x01, 0xf9, 0xe7, 0x00, 0x20, 0x70, 0xbd, 0xf8, 0xb5, 0x14, 0x48, 0x00, 0x68, 0x80, 0x8a, ++ 0x00, 0x04, 0x18, 0xd4, 0x03, 0x26, 0x36, 0x07, 0xb0, 0x8a, 0x15, 0x4f, 0xb7, 0x82, 0x0a, 0x4c, ++ 0x20, 0x21, 0x22, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x10, 0x18, 0x41, 0x84, 0x68, 0x46, 0xff, 0xf7, ++ 0xc5, 0xff, 0x00, 0x25, 0x01, 0x28, 0x1d, 0xd0, 0xb0, 0x8a, 0xb7, 0x82, 0x21, 0x68, 0x0d, 0x20, ++ 0x40, 0x03, 0x08, 0x18, 0x45, 0x84, 0xf8, 0xbd, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, ++ 0xf3, 0x8f, 0x00, 0x00, 0xff, 0xfb, 0x00, 0x00, 0x80, 0xa1, 0x01, 0x00, 0x90, 0x00, 0x00, 0x20, ++ 0xff, 0xfd, 0x00, 0x00, 0x80, 0xf7, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, ++ 0xdf, 0xff, 0x00, 0x00, 0xff, 0xf7, 0x77, 0xff, 0xf9, 0x48, 0x53, 0x21, 0x00, 0x68, 0x09, 0x5c, ++ 0x00, 0x29, 0x0e, 0xd0, 0x81, 0x22, 0x11, 0x56, 0xf6, 0x4a, 0x10, 0x31, 0x1f, 0x29, 0x21, 0x68, ++ 0x0a, 0xd8, 0x8b, 0x18, 0x28, 0x21, 0x59, 0x5e, 0x23, 0x68, 0x89, 0x02, 0x9a, 0x18, 0x52, 0x8d, ++ 0x09, 0xe0, 0x05, 0x83, 0x45, 0x83, 0x0b, 0xe0, 0x8b, 0x18, 0x2c, 0x21, 0x59, 0x5e, 0x23, 0x68, ++ 0x89, 0x02, 0x9a, 0x18, 0xd2, 0x8d, 0xd2, 0xb2, 0x11, 0x43, 0x0a, 0x0c, 0x02, 0x83, 0x41, 0x83, ++ 0xe9, 0x49, 0x81, 0x82, 0xbf, 0xe7, 0x30, 0xb5, 0xff, 0xf7, 0x3b, 0xfc, 0xe4, 0x4d, 0x29, 0x68, ++ 0x40, 0x31, 0x48, 0x76, 0x1f, 0x20, 0xff, 0xf7, 0x3d, 0xfc, 0x1e, 0x21, 0x28, 0x68, 0xc9, 0x43, ++ 0xc1, 0x84, 0x40, 0x30, 0xc0, 0x7c, 0x00, 0x28, 0x1d, 0xd0, 0x02, 0x20, 0xff, 0xf7, 0x9a, 0xfb, ++ 0x28, 0x68, 0x00, 0x24, 0x04, 0x85, 0x04, 0x77, 0x84, 0x75, 0x1f, 0x20, 0xff, 0xf7, 0xbb, 0xfd, ++ 0x28, 0x68, 0x53, 0x21, 0x09, 0x5c, 0x00, 0x29, 0x0b, 0xd0, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, ++ 0xff, 0x22, 0x8a, 0x82, 0xd5, 0x4a, 0x01, 0x21, 0x12, 0x68, 0x49, 0x02, 0xd1, 0x4b, 0xd2, 0x18, ++ 0x91, 0x84, 0x84, 0x82, 0x30, 0xbd, 0x1f, 0x20, 0xc0, 0x43, 0xff, 0xf7, 0x7b, 0xfb, 0x01, 0x20, ++ 0xdc, 0xe7, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0x81, 0xfd, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, ++ 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0xc9, 0x48, 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, ++ 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0xc5, 0x4a, 0x8a, 0x82, 0xc5, 0x4b, 0x04, 0x68, ++ 0xc0, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, 0x01, 0x21, 0x00, 0x68, ++ 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x4d, 0xe5, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfb, 0xb8, 0x49, ++ 0x59, 0x22, 0x09, 0x68, 0x50, 0x54, 0x00, 0x20, 0x08, 0x77, 0x88, 0x75, 0x1c, 0x20, 0xff, 0xf7, ++ 0xd0, 0xff, 0x00, 0xbd, 0x00, 0xb5, 0xff, 0xf7, 0xe6, 0xfe, 0xff, 0xf7, 0x4f, 0xfd, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0x30, 0x21, 0xc9, 0x43, 0x81, 0x82, 0xb0, 0x49, 0x00, 0x20, 0x09, 0x68, ++ 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, 0x48, 0x84, 0x00, 0xbd, 0x10, 0xb5, 0x00, 0x23, 0x00, 0x28, ++ 0x1c, 0xd0, 0xad, 0x4c, 0x00, 0x22, 0xa0, 0x42, 0x00, 0xd9, 0x20, 0x46, 0x52, 0x1c, 0x40, 0x00, ++ 0x52, 0xb2, 0x00, 0x28, 0xfa, 0xda, 0xd4, 0x17, 0xe4, 0x0e, 0xa4, 0x18, 0x64, 0x09, 0x64, 0x01, ++ 0x12, 0x1b, 0x1f, 0x24, 0xa2, 0x1a, 0xd2, 0xb2, 0x0a, 0x70, 0x08, 0x2a, 0x09, 0xd2, 0x00, 0x0e, ++ 0x00, 0x06, 0xa2, 0x1a, 0xd0, 0x40, 0xc0, 0xb2, 0x0b, 0x70, 0x0b, 0xe5, 0x0b, 0x70, 0x00, 0x20, ++ 0x08, 0xe5, 0x00, 0x0e, 0xd2, 0x1f, 0x0a, 0x70, 0x04, 0xe5, 0xf0, 0xb5, 0x03, 0x24, 0x24, 0x07, ++ 0xa1, 0x8a, 0x9a, 0x49, 0xa1, 0x82, 0x00, 0x28, 0x01, 0xdd, 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, ++ 0x97, 0x4a, 0x89, 0x02, 0x91, 0x4e, 0x89, 0x18, 0x32, 0x68, 0x0d, 0x27, 0x7f, 0x03, 0xd2, 0x19, ++ 0x11, 0x81, 0x01, 0x23, 0x00, 0x21, 0x5b, 0x02, 0x45, 0x42, 0x07, 0xe0, 0xa2, 0x8a, 0x91, 0x4a, ++ 0xa2, 0x82, 0x32, 0x68, 0xd2, 0x19, 0x13, 0x81, 0x49, 0x1c, 0x49, 0xb2, 0x00, 0x28, 0x01, 0xdb, ++ 0x02, 0x46, 0x00, 0xe0, 0x2a, 0x46, 0x8a, 0x42, 0xf0, 0xdc, 0xf0, 0xbd, 0xf0, 0xb5, 0x0e, 0x27, ++ 0x00, 0x22, 0x82, 0x4d, 0x88, 0x4e, 0xff, 0x43, 0x7d, 0x4c, 0x0f, 0x23, 0x00, 0x29, 0x16, 0xd0, ++ 0x00, 0x28, 0x09, 0xd0, 0x10, 0x46, 0x09, 0xe0, 0x29, 0x68, 0x89, 0x19, 0x89, 0x88, 0x89, 0x06, ++ 0x89, 0x16, 0x79, 0x1a, 0xc1, 0x84, 0xf0, 0xbd, 0x1f, 0x46, 0x18, 0x46, 0xff, 0xf7, 0x53, 0xfe, ++ 0x20, 0x68, 0xc1, 0x7d, 0x09, 0x09, 0xc9, 0x43, 0x89, 0x07, 0xed, 0xd1, 0xf0, 0xbd, 0x00, 0x28, ++ 0x01, 0xd0, 0x10, 0x46, 0x01, 0xe0, 0x1f, 0x46, 0x18, 0x46, 0xff, 0xf7, 0x2c, 0xfe, 0x28, 0x68, ++ 0x80, 0x19, 0x40, 0x88, 0x21, 0x68, 0x80, 0x06, 0x80, 0x16, 0x38, 0x1a, 0xc8, 0x84, 0xf0, 0xbd, ++ 0x40, 0x00, 0x0f, 0x38, 0x40, 0xb2, 0x70, 0x47, 0x30, 0xb5, 0x65, 0x4c, 0x00, 0x20, 0x21, 0x68, ++ 0x66, 0x4a, 0x08, 0x85, 0x10, 0x68, 0x6c, 0x4b, 0xc0, 0x18, 0x80, 0x88, 0x80, 0x06, 0x80, 0x16, ++ 0xff, 0xf7, 0xee, 0xff, 0x21, 0x68, 0x80, 0x31, 0x48, 0x70, 0x10, 0x68, 0xc0, 0x18, 0x40, 0x88, ++ 0x80, 0x06, 0x80, 0x16, 0xff, 0xf7, 0xe4, 0xff, 0x21, 0x68, 0x01, 0x22, 0x0b, 0x46, 0x80, 0x33, ++ 0x98, 0x70, 0x9a, 0x56, 0x00, 0x2a, 0x01, 0xdb, 0x15, 0x46, 0x00, 0xe0, 0x55, 0x42, 0x00, 0x28, ++ 0x01, 0xdb, 0x03, 0x46, 0x00, 0xe0, 0x43, 0x42, 0x9d, 0x42, 0x03, 0xdd, 0x0b, 0x8d, 0x04, 0x25, ++ 0x2b, 0x43, 0x0b, 0x85, 0x00, 0x2a, 0x03, 0xdd, 0x0a, 0x8d, 0x02, 0x23, 0x1a, 0x43, 0x0a, 0x85, ++ 0x00, 0x28, 0x03, 0xdd, 0x08, 0x8d, 0x01, 0x22, 0x10, 0x43, 0x08, 0x85, 0xca, 0x7d, 0x90, 0x06, ++ 0x80, 0x0f, 0x13, 0xd0, 0x01, 0x28, 0x20, 0xd0, 0x02, 0x28, 0x21, 0xd0, 0x03, 0x28, 0x0c, 0xd1, ++ 0x08, 0x8d, 0x01, 0x21, 0x80, 0x07, 0xc0, 0x0f, 0xff, 0xf7, 0x80, 0xff, 0x20, 0x68, 0x00, 0x8d, ++ 0xc0, 0x07, 0xc0, 0x0f, 0x00, 0x21, 0xff, 0xf7, 0x79, 0xff, 0x30, 0xbd, 0x28, 0x20, 0x08, 0x5e, ++ 0x04, 0x28, 0x01, 0xdb, 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x04, 0x28, 0x02, 0xdb, 0x80, 0x07, ++ 0xc0, 0x0f, 0xf0, 0xe7, 0xc0, 0x07, 0xc0, 0x0f, 0xed, 0xe7, 0xd0, 0x07, 0xc0, 0x0f, 0xe9, 0xe7, ++ 0xd0, 0x07, 0xc0, 0x0f, 0x01, 0x21, 0xe6, 0xe7, 0xf8, 0xb5, 0xff, 0xf7, 0xd2, 0xfa, 0x30, 0x4c, ++ 0x59, 0x22, 0x21, 0x68, 0x00, 0x27, 0x50, 0x54, 0x8f, 0x82, 0xc8, 0x7d, 0x39, 0x4d, 0x03, 0x07, ++ 0x36, 0x48, 0x37, 0x4a, 0xab, 0x8a, 0xa8, 0x82, 0x04, 0xd5, 0x2c, 0x48, 0x00, 0x68, 0x80, 0x18, ++ 0x07, 0x80, 0x04, 0xe0, 0x29, 0x48, 0x08, 0x23, 0x00, 0x68, 0x80, 0x18, 0x03, 0x80, 0xc8, 0x7d, ++ 0x1e, 0x26, 0x40, 0x07, 0x40, 0x0f, 0xf6, 0x43, 0x03, 0x00, 0x05, 0xf0, 0x99, 0xfd, 0x08, 0x05, ++ 0x0e, 0x17, 0x2d, 0x5d, 0x5d, 0x85, 0x8d, 0x5f, 0x1f, 0x20, 0xff, 0xf7, 0xb3, 0xfa, 0x21, 0x68, ++ 0x50, 0x20, 0x08, 0x56, 0xff, 0xf7, 0xe2, 0xfc, 0x14, 0xe0, 0x30, 0x46, 0xff, 0xf7, 0xaa, 0xfa, ++ 0x21, 0x68, 0x50, 0x20, 0x08, 0x56, 0xff, 0xf7, 0xd9, 0xfc, 0x20, 0xe0, 0x00, 0x20, 0xff, 0xf7, ++ 0xa1, 0xfa, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7c, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x20, 0xc0, 0x43, ++ 0xff, 0xf7, 0x00, 0xfa, 0x21, 0x68, 0x1f, 0x20, 0xc8, 0x84, 0x37, 0xe0, 0x20, 0x20, 0xff, 0xf7, ++ 0xf9, 0xf9, 0x00, 0x20, 0xc0, 0x43, 0xf3, 0xe7, 0x00, 0x20, 0xff, 0xf7, 0x8b, 0xfa, 0x20, 0x68, ++ 0x40, 0x30, 0xc0, 0x7c, 0x00, 0x28, 0x05, 0xd0, 0x02, 0x20, 0xff, 0xf7, 0xeb, 0xf9, 0x20, 0x68, ++ 0xc6, 0x84, 0x23, 0xe0, 0x1f, 0x20, 0xc0, 0x43, 0xff, 0xf7, 0xe4, 0xf9, 0x01, 0x20, 0xf4, 0xe7, ++ 0x90, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, 0x01, 0xec, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0xf3, 0x0f, 0x00, 0x00, 0x0c, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x80, 0x8b, 0x00, 0x00, ++ 0x01, 0x40, 0x00, 0x00, 0xff, 0xfd, 0x00, 0x00, 0x80, 0xa2, 0x01, 0x00, 0xf7, 0xff, 0x00, 0x00, ++ 0x80, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xf7, 0x16, 0xff, 0x20, 0x68, 0xc0, 0x7d, ++ 0x40, 0x07, 0x15, 0xd4, 0xff, 0xf7, 0x12, 0xfc, 0x20, 0x68, 0x53, 0x21, 0x09, 0x5c, 0x00, 0x29, ++ 0x0c, 0xd0, 0xc0, 0x7d, 0x80, 0x07, 0x09, 0xd5, 0xa8, 0x8a, 0xff, 0x20, 0xa8, 0x82, 0xf9, 0x48, ++ 0x01, 0x21, 0x00, 0x68, 0xc9, 0x02, 0xf8, 0x4a, 0x80, 0x18, 0x81, 0x84, 0xff, 0xf7, 0x17, 0xfa, ++ 0xff, 0xf7, 0x87, 0xfb, 0x20, 0x68, 0x5e, 0x30, 0xff, 0xf7, 0x8e, 0xfb, 0x20, 0x68, 0x87, 0x75, ++ 0x07, 0x77, 0x47, 0x87, 0x87, 0x87, 0xae, 0xe5, 0x20, 0x20, 0xff, 0xf7, 0x8e, 0xfe, 0x00, 0x20, ++ 0xc0, 0x43, 0xff, 0xf7, 0x8a, 0xfe, 0x95, 0xe7, 0x1f, 0x20, 0xc0, 0x43, 0xff, 0xf7, 0x85, 0xfe, ++ 0x01, 0x20, 0xff, 0xf7, 0x82, 0xfe, 0xa2, 0xe7, 0x10, 0xb5, 0x05, 0xf0, 0xab, 0xf9, 0xe7, 0x49, ++ 0x09, 0x68, 0x88, 0x84, 0x00, 0x0c, 0x48, 0x84, 0x0c, 0xe5, 0x7c, 0xb5, 0x06, 0x46, 0x08, 0x68, ++ 0x69, 0x46, 0xc0, 0x08, 0xff, 0xf7, 0x49, 0xfe, 0xe0, 0x4d, 0x44, 0x22, 0x29, 0x68, 0xe0, 0x4c, ++ 0x52, 0x5a, 0x0b, 0x7f, 0xd2, 0x18, 0xa0, 0x54, 0x08, 0x7f, 0xbf, 0x28, 0x01, 0xd3, 0xbf, 0x20, ++ 0x00, 0xe0, 0x40, 0x1c, 0x08, 0x77, 0x01, 0xa9, 0x30, 0x68, 0xff, 0xf7, 0x36, 0xfe, 0x69, 0x46, ++ 0x09, 0x78, 0x0a, 0x01, 0x69, 0x46, 0x09, 0x79, 0x0a, 0x43, 0x29, 0x68, 0x0b, 0x46, 0x40, 0x33, ++ 0x9d, 0x88, 0x0e, 0x7f, 0xad, 0x19, 0x62, 0x55, 0x0a, 0x7f, 0xbf, 0x2a, 0x01, 0xd3, 0xbf, 0x22, ++ 0x00, 0xe0, 0x52, 0x1c, 0xd2, 0xb2, 0x0a, 0x77, 0x9b, 0x88, 0x9a, 0x18, 0xa0, 0x54, 0x08, 0x7f, ++ 0xbf, 0x28, 0x01, 0xd3, 0xbf, 0x20, 0x00, 0xe0, 0x40, 0x1c, 0x08, 0x77, 0x7c, 0xbd, 0x70, 0xb5, ++ 0xc6, 0x4a, 0x0e, 0x23, 0x14, 0x68, 0x00, 0x25, 0xe3, 0x84, 0xc2, 0x4b, 0xc5, 0x4c, 0x00, 0x29, ++ 0x2b, 0xd0, 0x00, 0x28, 0x18, 0x68, 0x11, 0xd0, 0x00, 0x19, 0x80, 0x88, 0x80, 0x06, 0x80, 0x16, ++ 0xff, 0xf7, 0x86, 0xfe, 0x11, 0x68, 0x81, 0x26, 0x8e, 0x57, 0xb0, 0x42, 0x1a, 0xda, 0x18, 0x68, ++ 0x00, 0x19, 0x80, 0x88, 0x80, 0x06, 0x80, 0x16, 0x40, 0x1c, 0x10, 0xe0, 0x00, 0x19, 0x80, 0x88, ++ 0x80, 0x06, 0x80, 0x16, 0xff, 0xf7, 0x74, 0xfe, 0x11, 0x68, 0x81, 0x26, 0x8e, 0x57, 0xb0, 0x42, ++ 0x08, 0xdd, 0x18, 0x68, 0x00, 0x19, 0x80, 0x88, 0x80, 0x06, 0x80, 0x16, 0x40, 0x1e, 0xff, 0xf7, ++ 0xa2, 0xfc, 0x70, 0xbd, 0x10, 0x68, 0xc5, 0x84, 0x70, 0xbd, 0x00, 0x28, 0x18, 0x68, 0x11, 0xd0, ++ 0x00, 0x19, 0x40, 0x88, 0x80, 0x06, 0x80, 0x16, 0xff, 0xf7, 0x5a, 0xfe, 0x11, 0x68, 0x82, 0x26, ++ 0x8e, 0x57, 0xb0, 0x42, 0xee, 0xda, 0x18, 0x68, 0x00, 0x19, 0x40, 0x88, 0x80, 0x06, 0x80, 0x16, ++ 0x40, 0x1c, 0x10, 0xe0, 0x00, 0x19, 0x40, 0x88, 0x80, 0x06, 0x80, 0x16, 0xff, 0xf7, 0x48, 0xfe, ++ 0x11, 0x68, 0x82, 0x26, 0x8e, 0x57, 0xb0, 0x42, 0xdc, 0xdd, 0x18, 0x68, 0x00, 0x19, 0x40, 0x88, ++ 0x80, 0x06, 0x80, 0x16, 0x40, 0x1e, 0xff, 0xf7, 0x5e, 0xfc, 0x70, 0xbd, 0xf0, 0xb5, 0x85, 0xb0, ++ 0x00, 0x20, 0x69, 0x46, 0x95, 0x4f, 0x08, 0x72, 0x38, 0x68, 0x81, 0x8a, 0x09, 0x04, 0x7d, 0xd4, ++ 0x03, 0x25, 0x2d, 0x07, 0xa9, 0x8a, 0x20, 0x21, 0xc9, 0x43, 0xa9, 0x82, 0x8d, 0x4c, 0x20, 0x21, ++ 0x22, 0x68, 0x0d, 0x26, 0x76, 0x03, 0x92, 0x19, 0x51, 0x84, 0x53, 0x21, 0x09, 0x5c, 0x00, 0x29, ++ 0x11, 0xd0, 0x26, 0x21, 0x41, 0x5e, 0x10, 0x31, 0x1f, 0x29, 0x02, 0xd9, 0xc0, 0x7d, 0x80, 0x07, ++ 0x0d, 0xd4, 0x20, 0x68, 0x84, 0x49, 0x42, 0x18, 0x28, 0x20, 0x10, 0x5e, 0x22, 0x68, 0x80, 0x02, ++ 0x51, 0x18, 0x49, 0x8d, 0x0c, 0xe0, 0x02, 0xa8, 0xff, 0xf7, 0xa6, 0xfa, 0x0a, 0xe0, 0x20, 0x68, ++ 0x7d, 0x49, 0x42, 0x18, 0x2c, 0x20, 0x10, 0x5e, 0x22, 0x68, 0x80, 0x02, 0x51, 0x18, 0xc9, 0x8d, ++ 0xc9, 0xb2, 0x08, 0x43, 0x00, 0x90, 0x01, 0xa8, 0xff, 0xf7, 0x78, 0xfc, 0x03, 0x90, 0x77, 0x48, ++ 0x07, 0x68, 0x38, 0x46, 0x3a, 0x30, 0x05, 0xf0, 0xdf, 0xfb, 0x10, 0x21, 0xc8, 0x41, 0x00, 0x99, ++ 0x40, 0x18, 0x88, 0x42, 0x01, 0xd2, 0x00, 0x20, 0xc0, 0x43, 0x03, 0x99, 0x00, 0x90, 0x01, 0x29, ++ 0x21, 0xd0, 0xf9, 0x8c, 0x00, 0x29, 0x1e, 0xd0, 0x6f, 0x49, 0x89, 0x7c, 0x09, 0x01, 0x81, 0x42, ++ 0x7c, 0xd2, 0x27, 0x22, 0x01, 0x99, 0x12, 0x02, 0x91, 0x42, 0x05, 0xd8, 0x6b, 0x4a, 0x91, 0x42, ++ 0x74, 0xd9, 0xf9, 0x7d, 0x49, 0x06, 0x71, 0xd5, 0x01, 0xa9, 0x68, 0x46, 0xff, 0xf7, 0xfd, 0xfe, ++ 0x62, 0x4a, 0x11, 0x68, 0xcb, 0x7d, 0xd8, 0x07, 0x65, 0x48, 0x08, 0x5e, 0x20, 0xd0, 0x00, 0x28, ++ 0x1c, 0xda, 0x40, 0x1c, 0x1f, 0xe0, 0x01, 0xa9, 0x68, 0x46, 0xff, 0xf7, 0xee, 0xfe, 0x68, 0x46, ++ 0x00, 0x7a, 0x00, 0x28, 0x10, 0xd0, 0x00, 0x20, 0x01, 0x21, 0x80, 0x03, 0xc9, 0x03, 0x41, 0x18, ++ 0x03, 0x98, 0x40, 0x03, 0x01, 0x43, 0x55, 0x48, 0x00, 0x68, 0x00, 0xe0, 0x02, 0xe0, 0x02, 0x7f, ++ 0x11, 0x43, 0x81, 0x82, 0x05, 0xb0, 0xf0, 0xbd, 0x01, 0x20, 0xed, 0xe7, 0x00, 0x20, 0x02, 0xe0, ++ 0x00, 0x28, 0xfb, 0xdd, 0x40, 0x1e, 0xc8, 0x84, 0x98, 0x07, 0x40, 0xd5, 0x53, 0x20, 0x47, 0x5c, ++ 0x01, 0x20, 0x50, 0x4a, 0x40, 0x02, 0x00, 0x2f, 0x01, 0xd0, 0x5f, 0x07, 0x05, 0xd5, 0xa9, 0x8a, ++ 0xaa, 0x82, 0x21, 0x68, 0x89, 0x19, 0x08, 0x81, 0x66, 0xe0, 0xdb, 0x07, 0xff, 0x27, 0x00, 0x2b, ++ 0x13, 0xd0, 0x26, 0x23, 0xcb, 0x5e, 0x10, 0x33, 0x12, 0xd1, 0x3e, 0x20, 0xc0, 0x43, 0xff, 0xf7, ++ 0x39, 0xf8, 0x01, 0x20, 0xff, 0xf7, 0x36, 0xf8, 0xa8, 0x8a, 0xaf, 0x82, 0x01, 0x21, 0x22, 0x68, ++ 0x89, 0x02, 0x39, 0x48, 0x10, 0x18, 0x81, 0x84, 0x4e, 0xe0, 0xc9, 0x8c, 0x0f, 0x29, 0x05, 0xd0, ++ 0xa9, 0x8a, 0xaa, 0x82, 0x21, 0x68, 0x89, 0x19, 0x08, 0x81, 0xd8, 0xe7, 0x3f, 0x20, 0xff, 0xf7, ++ 0x21, 0xf8, 0x00, 0x20, 0xc0, 0x43, 0xff, 0xf7, 0x1d, 0xf8, 0xa8, 0x8a, 0xaf, 0x82, 0x01, 0x20, ++ 0x22, 0x68, 0x80, 0x02, 0x2c, 0x49, 0x51, 0x18, 0x88, 0x84, 0x35, 0xe0, 0x64, 0xe0, 0x2b, 0x4f, ++ 0x58, 0x07, 0x2d, 0xd5, 0x98, 0x06, 0x80, 0x0f, 0x06, 0xd0, 0x01, 0x28, 0x15, 0xd0, 0x02, 0x28, ++ 0x16, 0xd0, 0x03, 0x28, 0x28, 0xd1, 0x17, 0xe0, 0x28, 0x20, 0x08, 0x5e, 0x04, 0x28, 0x01, 0xdb, ++ 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x03, 0x28, 0x02, 0xdb, 0x80, 0x07, 0xc0, 0x0f, 0x01, 0xe0, ++ 0xc0, 0x07, 0xc0, 0x0f, 0xff, 0xf7, 0xab, 0xfe, 0x16, 0xe0, 0xd8, 0x07, 0xc0, 0x0f, 0x0d, 0xe0, ++ 0xd8, 0x07, 0xc0, 0x0f, 0x01, 0x21, 0xf5, 0xe7, 0x08, 0x8d, 0x01, 0x21, 0x80, 0x07, 0xc0, 0x0f, ++ 0xff, 0xf7, 0x9d, 0xfe, 0x38, 0x68, 0x00, 0x8d, 0xc0, 0x07, 0xc0, 0x0f, 0x00, 0x21, 0xe9, 0xe7, ++ 0xc8, 0x8c, 0x40, 0xb2, 0xff, 0xf7, 0x76, 0xf8, 0xff, 0xf7, 0x4e, 0xfe, 0x0f, 0x48, 0x00, 0x27, ++ 0x00, 0x68, 0x47, 0x87, 0x87, 0x87, 0xff, 0xf7, 0x42, 0xf8, 0x02, 0xa8, 0xff, 0xf7, 0xbc, 0xf9, ++ 0x00, 0x90, 0xa8, 0x8a, 0x20, 0x20, 0xc0, 0x43, 0xa8, 0x82, 0x20, 0x68, 0x80, 0x19, 0x47, 0x84, ++ 0x06, 0x48, 0x00, 0x68, 0xc1, 0x8c, 0x02, 0x7f, 0x49, 0x06, 0x49, 0x0c, 0x0a, 0x43, 0x82, 0x82, ++ 0x60, 0xe7, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x20, ++ 0x00, 0x01, 0x00, 0x20, 0x80, 0xa2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x20, 0xcc, 0x07, 0x00, 0x00, ++ 0x26, 0x00, 0x00, 0x00, 0xff, 0xfd, 0x00, 0x00, 0x01, 0x0c, 0x79, 0x87, 0xb8, 0x87, 0xff, 0xf7, ++ 0x16, 0xf8, 0xa8, 0x8a, 0x20, 0x20, 0xc0, 0x43, 0xa8, 0x82, 0x21, 0x68, 0x00, 0x20, 0x89, 0x19, ++ 0x48, 0x84, 0xd5, 0xe7, 0xf0, 0xb5, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xfa, 0x49, 0x81, 0x82, ++ 0xfa, 0x49, 0x00, 0x22, 0x0c, 0x68, 0x0d, 0x23, 0x5b, 0x03, 0xe4, 0x18, 0x62, 0x80, 0x84, 0x8a, ++ 0x01, 0x26, 0x86, 0x82, 0x69, 0x24, 0x0d, 0x68, 0x24, 0x01, 0xed, 0x18, 0xac, 0x80, 0x84, 0x8a, ++ 0x94, 0x1e, 0x84, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0xe2, 0x80, 0x84, 0x8a, 0xf0, 0x4c, 0x84, 0x82, ++ 0x0c, 0x68, 0xe4, 0x18, 0x22, 0x81, 0x84, 0x8a, 0xee, 0x4c, 0x84, 0x82, 0x0c, 0x68, 0xe4, 0x18, ++ 0x22, 0x84, 0x84, 0x8a, 0xec, 0x4d, 0x85, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0x62, 0x84, 0x84, 0x8a, ++ 0xea, 0x4c, 0x84, 0x82, 0x0f, 0x68, 0xdc, 0x10, 0xff, 0x18, 0x3c, 0x85, 0x84, 0x8a, 0x1f, 0x24, ++ 0xe4, 0x43, 0x84, 0x82, 0x0f, 0x68, 0x0d, 0x24, 0xff, 0x18, 0x7c, 0x85, 0x84, 0x8a, 0xe4, 0x4c, ++ 0x84, 0x82, 0x0c, 0x68, 0xe3, 0x18, 0x1e, 0x86, 0x83, 0x8a, 0xe2, 0x4b, 0x83, 0x82, 0x0c, 0x68, ++ 0xe1, 0x4b, 0xe4, 0x18, 0x22, 0x80, 0x84, 0x8a, 0xe0, 0x4e, 0x86, 0x82, 0x0c, 0x68, 0xe4, 0x18, ++ 0x62, 0x80, 0x84, 0x8a, 0x86, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0xa2, 0x80, 0x84, 0x8a, 0xb4, 0x1c, ++ 0x84, 0x82, 0x0e, 0x68, 0xf6, 0x18, 0xf2, 0x80, 0x86, 0x8a, 0x84, 0x82, 0x0e, 0x68, 0xf6, 0x18, ++ 0x32, 0x81, 0x86, 0x8a, 0x84, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0x62, 0x81, 0x84, 0x8a, 0xd4, 0x4c, ++ 0x84, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0xa2, 0x81, 0x84, 0x8a, 0xc0, 0x24, 0xe4, 0x43, 0x84, 0x82, ++ 0x0e, 0x68, 0x40, 0x24, 0xf6, 0x18, 0xf4, 0x81, 0x84, 0x8a, 0x01, 0x24, 0xa4, 0x03, 0x84, 0x82, ++ 0x0c, 0x68, 0xe4, 0x18, 0xe2, 0x82, 0x84, 0x8a, 0xff, 0x24, 0x04, 0x34, 0x84, 0x82, 0x0c, 0x68, ++ 0xe4, 0x18, 0x22, 0x84, 0x84, 0x8a, 0x82, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0x62, 0x84, 0x84, 0x8a, ++ 0x82, 0x82, 0x0c, 0x68, 0xe4, 0x18, 0xa2, 0x84, 0x84, 0x8a, 0x82, 0x82, 0x0c, 0x68, 0xe3, 0x18, ++ 0xda, 0x84, 0x83, 0x8a, 0x19, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x0e, 0x68, 0x10, 0x24, 0xba, 0x4b, ++ 0x40, 0x33, 0xf6, 0x18, 0x34, 0x80, 0x84, 0x8a, 0x0f, 0x24, 0xe4, 0x43, 0x84, 0x82, 0x0c, 0x68, ++ 0xe4, 0x18, 0x62, 0x80, 0x84, 0x8a, 0xb0, 0x4c, 0x29, 0x34, 0x84, 0x82, 0x0e, 0x68, 0xf6, 0x18, ++ 0xb2, 0x80, 0x86, 0x8a, 0x84, 0x82, 0x0f, 0x68, 0x04, 0x26, 0xff, 0x18, 0x3e, 0x84, 0x86, 0x8a, ++ 0x84, 0x82, 0x0e, 0x68, 0xf3, 0x18, 0x1a, 0x85, 0x83, 0x8a, 0x82, 0x82, 0x0e, 0x68, 0xaa, 0x4b, ++ 0x80, 0x33, 0xf6, 0x18, 0x32, 0x80, 0x86, 0x8a, 0x82, 0x82, 0x0e, 0x68, 0xf6, 0x18, 0x72, 0x80, ++ 0x86, 0x8a, 0x84, 0x82, 0x0c, 0x68, 0xe3, 0x18, 0x9a, 0x80, 0x83, 0x8a, 0x85, 0x82, 0x0b, 0x68, ++ 0xa1, 0x4c, 0xc0, 0x34, 0x1b, 0x19, 0xda, 0x84, 0x83, 0x8a, 0x9d, 0x4b, 0xf1, 0x3b, 0x83, 0x82, ++ 0x08, 0x68, 0xa0, 0x49, 0x40, 0x18, 0x42, 0x84, 0xf0, 0xbd, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, ++ 0x00, 0x22, 0x8a, 0x82, 0x91, 0x49, 0x00, 0x02, 0x09, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, ++ 0x80, 0x30, 0x48, 0x83, 0x70, 0x47, 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, 0x96, 0x4c, 0x07, 0xe0, ++ 0xc3, 0x07, 0x02, 0xd0, 0x4b, 0x00, 0xe3, 0x5a, 0x5a, 0x40, 0x49, 0x1c, 0x89, 0xb2, 0x40, 0x08, ++ 0x00, 0x28, 0xf5, 0xd1, 0x10, 0x46, 0x27, 0xe5, 0xf0, 0xb5, 0x84, 0x48, 0x86, 0x4d, 0x00, 0x68, ++ 0x30, 0x35, 0x0d, 0x21, 0x49, 0x03, 0x40, 0x18, 0x86, 0x8b, 0x00, 0x27, 0x3c, 0x46, 0x09, 0xe0, ++ 0x38, 0x5d, 0x29, 0x0a, 0x48, 0x40, 0xff, 0xf7, 0xde, 0xff, 0x29, 0x02, 0x48, 0x40, 0x64, 0x1c, ++ 0x85, 0xb2, 0xa4, 0xb2, 0xb4, 0x42, 0xf3, 0xd3, 0x28, 0x46, 0xf0, 0xbd, 0x03, 0x22, 0x12, 0x07, ++ 0x93, 0x8a, 0x00, 0x23, 0x93, 0x82, 0x09, 0x07, 0x00, 0x01, 0x09, 0x0f, 0x08, 0x43, 0x00, 0x02, ++ 0x80, 0x21, 0x40, 0x30, 0x08, 0x43, 0x71, 0x49, 0x09, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, ++ 0x48, 0x83, 0x70, 0x47, 0xfe, 0xb5, 0x02, 0x46, 0x78, 0x48, 0x6c, 0x4f, 0x40, 0x7d, 0x00, 0x26, ++ 0xc0, 0x00, 0x01, 0x90, 0x76, 0x48, 0x13, 0x00, 0x04, 0x68, 0x21, 0x46, 0x80, 0x31, 0x00, 0x91, ++ 0x25, 0x46, 0x74, 0x49, 0x40, 0x35, 0x05, 0xf0, 0xe3, 0xf9, 0x15, 0x0c, 0x19, 0x18, 0x18, 0x8b, ++ 0xb8, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0x18, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, ++ 0x18, 0x00, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xc0, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x3a, 0x68, ++ 0x80, 0x21, 0x0d, 0x20, 0x40, 0x03, 0x10, 0x18, 0x41, 0x83, 0xfe, 0xbd, 0x57, 0x49, 0x09, 0x68, ++ 0x0d, 0x27, 0x7f, 0x03, 0xc9, 0x19, 0x49, 0x8b, 0x09, 0x0a, 0x06, 0xd0, 0x01, 0x29, 0x0a, 0xd0, ++ 0x02, 0x29, 0x2c, 0xd0, 0x01, 0x21, 0x08, 0x46, 0x34, 0xe1, 0xa8, 0x7c, 0x00, 0x28, 0xec, 0xd0, ++ 0x01, 0x20, 0x60, 0x74, 0xfb, 0xe1, 0x05, 0x46, 0x00, 0x98, 0x04, 0x21, 0x82, 0x7c, 0x57, 0x48, ++ 0x08, 0x24, 0x43, 0x7e, 0x9a, 0x42, 0x10, 0xd0, 0x83, 0x7e, 0x9a, 0x42, 0x02, 0xd1, 0x05, 0x21, ++ 0x09, 0x24, 0x0a, 0xe0, 0xc3, 0x7e, 0x9a, 0x42, 0x02, 0xd1, 0x06, 0x21, 0x0a, 0x24, 0x04, 0xe0, ++ 0x00, 0x7f, 0x82, 0x42, 0x01, 0xd1, 0x07, 0x21, 0x0b, 0x24, 0x08, 0x46, 0x00, 0xf0, 0x93, 0xff, ++ 0x20, 0x46, 0x00, 0xf0, 0x90, 0xff, 0x29, 0x68, 0x01, 0x20, 0x48, 0x74, 0xd7, 0xe1, 0x01, 0x21, ++ 0x69, 0x72, 0x66, 0x74, 0xfd, 0xf7, 0x84, 0xfe, 0x38, 0x48, 0x01, 0x68, 0xc9, 0x19, 0x89, 0x8e, ++ 0xc9, 0x07, 0x09, 0xd0, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x20, 0x22, 0xd2, 0x43, 0x8a, 0x82, ++ 0x00, 0x68, 0x20, 0x21, 0xc0, 0x19, 0x01, 0x84, 0x00, 0x20, 0xff, 0xf7, 0x36, 0xff, 0x3c, 0x49, ++ 0x3a, 0x4a, 0x09, 0x68, 0x53, 0x7e, 0x80, 0x31, 0x89, 0x7c, 0x04, 0x20, 0x08, 0x24, 0x99, 0x42, ++ 0x10, 0xd0, 0x93, 0x7e, 0x99, 0x42, 0x02, 0xd1, 0x05, 0x20, 0x09, 0x24, 0x0a, 0xe0, 0xd3, 0x7e, ++ 0x99, 0x42, 0x02, 0xd1, 0x06, 0x20, 0x0a, 0x24, 0x04, 0xe0, 0x12, 0x7f, 0x91, 0x42, 0x01, 0xd1, ++ 0x07, 0x20, 0x0b, 0x24, 0x00, 0xf0, 0x4d, 0xff, 0x20, 0x46, 0x00, 0xf0, 0x4a, 0xff, 0xfe, 0xbd, ++ 0x38, 0x68, 0x0d, 0x24, 0x64, 0x03, 0x00, 0x19, 0x40, 0x8b, 0x00, 0x0a, 0x06, 0xd0, 0x01, 0x28, ++ 0x0b, 0xd0, 0x02, 0x28, 0x13, 0xd0, 0x03, 0x28, 0x94, 0xd1, 0x17, 0xe0, 0x03, 0x20, 0x00, 0x07, ++ 0x81, 0x8a, 0x86, 0x82, 0x04, 0xf0, 0xf6, 0xfd, 0x05, 0xe0, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x86, 0x82, 0x04, 0xf0, 0xea, 0xfd, 0x39, 0x68, 0x09, 0x19, 0x88, 0x83, 0x7f, 0xe1, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0x86, 0x82, 0x00, 0x98, 0x80, 0x7c, 0xf4, 0xe7, 0x03, 0x20, 0x00, 0x07, ++ 0x81, 0x8a, 0x86, 0x82, 0x04, 0xf0, 0x08, 0xfe, 0xed, 0xe7, 0x3a, 0x68, 0x0d, 0x21, 0x49, 0x03, ++ 0x52, 0x18, 0x52, 0x8b, 0x12, 0x0a, 0x92, 0x1e, 0x13, 0x00, 0x05, 0xf0, 0x21, 0xf9, 0x05, 0x55, ++ 0x62, 0x7b, 0x8d, 0x33, 0x04, 0x00, 0xc2, 0xe7, 0x7f, 0xf8, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0x80, 0x81, 0x00, 0x00, 0x1f, 0xbf, 0x00, 0x00, 0xcf, 0xff, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, ++ 0xf0, 0xfc, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x40, 0xa0, 0x01, 0x00, 0xfd, 0x13, 0x00, 0x00, ++ 0xc0, 0xc0, 0x00, 0x00, 0x80, 0xa1, 0x01, 0x00, 0xc4, 0x79, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, ++ 0x90, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0xf9, 0xe1, 0x88, 0xe1, 0xd9, 0xe1, 0xc3, 0xe1, ++ 0x44, 0xe1, 0xef, 0xe0, 0xdb, 0xe0, 0xc7, 0xe0, 0xb8, 0xe0, 0xa5, 0xe0, 0x98, 0xe0, 0x8e, 0xe0, ++ 0x82, 0xe0, 0x79, 0xe0, 0x62, 0x7c, 0x02, 0x2a, 0x01, 0xd3, 0x11, 0x46, 0x3c, 0xe1, 0xeb, 0x7c, ++ 0x01, 0x2b, 0x70, 0xd8, 0xab, 0x7c, 0x00, 0x2b, 0x01, 0xd1, 0x00, 0x2a, 0x87, 0xd0, 0x2a, 0x76, ++ 0x38, 0x68, 0x0d, 0x46, 0x40, 0x19, 0x80, 0x8b, 0xe0, 0x84, 0xfe, 0xf7, 0xd2, 0xff, 0x01, 0x00, ++ 0x01, 0xd0, 0x06, 0x20, 0x4e, 0xe0, 0xff, 0x48, 0x05, 0x21, 0x00, 0x68, 0x41, 0x74, 0x03, 0x21, ++ 0x09, 0x07, 0x8a, 0x8a, 0x8e, 0x82, 0x56, 0xe1, 0xa8, 0x7c, 0x00, 0x28, 0x02, 0xd1, 0x60, 0x7c, ++ 0x00, 0x28, 0xa8, 0xd0, 0x60, 0x7c, 0x28, 0x76, 0x01, 0x20, 0x60, 0x74, 0xff, 0xf7, 0xf4, 0xf9, ++ 0x05, 0xe1, 0x01, 0x21, 0x07, 0x46, 0x69, 0x72, 0x60, 0x7c, 0x02, 0x28, 0x0a, 0xd3, 0xf2, 0x48, ++ 0xf3, 0x4c, 0x06, 0x60, 0xf1, 0x48, 0x60, 0x81, 0x20, 0x81, 0x41, 0x1c, 0xf1, 0x48, 0x05, 0xf0, ++ 0x6f, 0xf8, 0x66, 0x75, 0xff, 0xf7, 0xee, 0xf9, 0x38, 0x68, 0x58, 0x21, 0x09, 0x5c, 0x41, 0x74, ++ 0x86, 0x82, 0xec, 0xe0, 0x60, 0x7c, 0x02, 0x28, 0x11, 0xd2, 0xe9, 0x7c, 0x01, 0x29, 0xb8, 0xd8, ++ 0xa9, 0x7c, 0x00, 0x29, 0x01, 0xd1, 0x00, 0x28, 0xb8, 0xd0, 0xe5, 0x49, 0x01, 0x20, 0x48, 0x75, ++ 0x60, 0x7c, 0x28, 0x76, 0x02, 0x20, 0x18, 0xe0, 0x60, 0x7c, 0x02, 0x28, 0x03, 0xd3, 0x01, 0x99, ++ 0x01, 0x43, 0xc9, 0xb2, 0xe0, 0xe0, 0xe9, 0x7c, 0x01, 0x29, 0xa2, 0xd8, 0xa9, 0x7c, 0x00, 0x29, ++ 0x05, 0xd1, 0x02, 0xe0, 0xff, 0xf7, 0x7a, 0xfe, 0xfe, 0xbd, 0x00, 0x28, 0xfc, 0xd0, 0xd8, 0x49, ++ 0x01, 0x20, 0x48, 0x75, 0x60, 0x7c, 0x28, 0x76, 0x03, 0x20, 0x60, 0x74, 0xff, 0xf7, 0x53, 0xf9, ++ 0xfe, 0xf7, 0x6d, 0xfd, 0xbb, 0xe0, 0xda, 0xe0, 0x38, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x80, 0x18, ++ 0x40, 0x8b, 0x00, 0x0a, 0x20, 0x5c, 0x2a, 0xe0, 0x39, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x09, 0x18, ++ 0x49, 0x8b, 0x3a, 0x68, 0x09, 0x0a, 0x10, 0x18, 0x80, 0x8b, 0x60, 0x54, 0xa7, 0xe0, 0x38, 0x68, ++ 0x0d, 0x22, 0x52, 0x03, 0x80, 0x18, 0x40, 0x8b, 0x01, 0x0a, 0xc5, 0x48, 0x40, 0x5c, 0x16, 0xe0, ++ 0x38, 0x68, 0x0d, 0x21, 0x49, 0x03, 0x40, 0x18, 0x80, 0x8b, 0x3a, 0x68, 0x51, 0x18, 0x49, 0x8b, ++ 0x0a, 0x0a, 0xbf, 0x49, 0x88, 0x54, 0x92, 0xe0, 0x38, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x80, 0x18, ++ 0x40, 0x8b, 0x00, 0x0a, 0x21, 0x18, 0x49, 0x78, 0x20, 0x5c, 0x09, 0x02, 0x08, 0x43, 0x03, 0x21, ++ 0x09, 0x07, 0x8b, 0x8a, 0x8e, 0x82, 0x39, 0x68, 0x89, 0x18, 0xfe, 0xe6, 0x38, 0x68, 0x0d, 0x21, ++ 0x49, 0x03, 0x40, 0x18, 0x80, 0x8b, 0x3a, 0x68, 0x51, 0x18, 0x49, 0x8b, 0x09, 0x0a, 0x60, 0x54, ++ 0x00, 0x0a, 0x61, 0x18, 0x48, 0x70, 0x72, 0xe0, 0x38, 0x68, 0x0d, 0x23, 0x5b, 0x03, 0xc0, 0x18, ++ 0x40, 0x8b, 0xab, 0x4a, 0x00, 0x0a, 0x11, 0x18, 0x49, 0x78, 0x10, 0x5c, 0x09, 0x02, 0x08, 0x43, ++ 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8e, 0x82, 0x39, 0x68, 0xc9, 0x18, 0xdd, 0xe6, 0x38, 0x68, ++ 0x0d, 0x21, 0x49, 0x03, 0x40, 0x18, 0x80, 0x8b, 0x3a, 0x68, 0x03, 0x0a, 0x52, 0x18, 0x52, 0x8b, ++ 0x14, 0x0a, 0x9f, 0x4a, 0xa4, 0x18, 0x63, 0x70, 0x3b, 0x68, 0x59, 0x18, 0x49, 0x8b, 0x09, 0x0a, ++ 0x50, 0x54, 0x4c, 0xe0, 0x60, 0x7c, 0x02, 0x28, 0x4d, 0xd2, 0x38, 0x68, 0x0d, 0x23, 0x5b, 0x03, ++ 0xc0, 0x18, 0x40, 0x8b, 0x00, 0x0a, 0x10, 0xd0, 0x01, 0x28, 0x23, 0xd0, 0x02, 0x28, 0x00, 0xd0, ++ 0x72, 0xe7, 0x93, 0x48, 0x90, 0x49, 0x46, 0x75, 0x0e, 0x60, 0x90, 0x49, 0x41, 0x81, 0x01, 0x81, ++ 0x49, 0x1c, 0x90, 0x48, 0x04, 0xf0, 0xac, 0xff, 0x2f, 0xe0, 0x00, 0x23, 0x00, 0x96, 0x1a, 0x46, ++ 0x11, 0x21, 0x02, 0x20, 0x01, 0x96, 0x04, 0xf0, 0x97, 0xfe, 0x89, 0x49, 0x01, 0x20, 0x48, 0x75, ++ 0x48, 0x89, 0x86, 0x4a, 0x08, 0x81, 0x90, 0x42, 0x01, 0xd1, 0x00, 0x20, 0x00, 0xe0, 0x40, 0x1c, ++ 0x08, 0x81, 0x1c, 0xe0, 0x82, 0x4c, 0x22, 0x89, 0x88, 0x5c, 0x61, 0x89, 0x8a, 0x42, 0x03, 0xd1, ++ 0xff, 0x21, 0x01, 0x31, 0x08, 0x43, 0x06, 0xe0, 0x7c, 0x49, 0x8a, 0x42, 0x01, 0xd1, 0x00, 0x22, ++ 0x00, 0xe0, 0x52, 0x1c, 0x22, 0x81, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8e, 0x82, 0x3a, 0x68, ++ 0xc1, 0xb2, 0xd2, 0x18, 0x91, 0x83, 0x00, 0x0a, 0x01, 0xd0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, ++ 0xff, 0xf7, 0x73, 0xfd, 0xfe, 0xbd, 0x00, 0x21, 0x05, 0x20, 0x2b, 0xe7, 0x61, 0x7c, 0x02, 0x29, ++ 0x04, 0xd3, 0x01, 0x98, 0x08, 0x43, 0xc1, 0xb2, 0x0c, 0x20, 0x23, 0xe7, 0x3a, 0x68, 0x0d, 0x20, ++ 0x40, 0x03, 0x12, 0x18, 0x52, 0x8b, 0x12, 0x0a, 0x52, 0x07, 0x05, 0xd5, 0x3b, 0x68, 0x6a, 0x4a, ++ 0x9b, 0x18, 0x5b, 0x8e, 0xdb, 0x07, 0x05, 0xd0, 0xeb, 0x7c, 0x01, 0x2b, 0x09, 0xd9, 0x02, 0x21, ++ 0x0d, 0x20, 0x0f, 0xe7, 0x38, 0x68, 0x80, 0x18, 0x40, 0x8e, 0xc1, 0x07, 0xc9, 0x0f, 0x08, 0x20, ++ 0x08, 0xe7, 0xab, 0x7c, 0x00, 0x2b, 0x01, 0xd1, 0x00, 0x29, 0xd3, 0xd0, 0x5c, 0x4b, 0x01, 0x21, ++ 0x59, 0x75, 0x61, 0x7c, 0x29, 0x76, 0x04, 0x21, 0x61, 0x74, 0x39, 0x68, 0x05, 0x46, 0x48, 0x19, ++ 0x40, 0x8b, 0x00, 0x0a, 0xe0, 0x75, 0xff, 0xf7, 0xbf, 0xf9, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x86, 0x82, 0x50, 0x48, 0x00, 0x68, 0x39, 0x68, 0xc0, 0x8c, 0x49, 0x19, 0x35, 0xe6, 0x01, 0x21, ++ 0x69, 0x72, 0x4d, 0x48, 0x00, 0x21, 0x01, 0x60, 0x4c, 0x48, 0x4d, 0x4e, 0x41, 0x1c, 0x70, 0x81, ++ 0x30, 0x81, 0x4c, 0x48, 0x04, 0xf0, 0x24, 0xff, 0x00, 0x20, 0x70, 0x75, 0xe0, 0x7d, 0x41, 0x07, ++ 0x15, 0xd5, 0x44, 0x4c, 0x80, 0x07, 0x0e, 0xd4, 0x00, 0x99, 0x01, 0x20, 0x08, 0x56, 0x0f, 0x30, ++ 0x40, 0x10, 0xfe, 0xf7, 0x68, 0xff, 0x21, 0x68, 0x82, 0x20, 0x08, 0x56, 0x0f, 0x30, 0x40, 0x10, ++ 0xfe, 0xf7, 0x49, 0xff, 0x03, 0xe0, 0x0f, 0x20, 0x28, 0x56, 0xfe, 0xf7, 0xe5, 0xfe, 0xff, 0xf7, ++ 0x89, 0xf8, 0x38, 0x48, 0x00, 0x21, 0x00, 0x68, 0x81, 0x82, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, ++ 0x08, 0x22, 0xd2, 0x43, 0x8a, 0x82, 0x3a, 0x68, 0x08, 0x21, 0x38, 0x4b, 0xd2, 0x18, 0x11, 0x80, ++ 0x58, 0x21, 0x09, 0x5c, 0x41, 0x74, 0x7a, 0xe7, 0xa8, 0x88, 0xa2, 0x7d, 0x80, 0x18, 0x08, 0x5c, ++ 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x8e, 0x82, 0x3a, 0x68, 0x0d, 0x21, 0x49, 0x03, 0x51, 0x18, ++ 0x88, 0x83, 0xa0, 0x7d, 0xbf, 0x28, 0x01, 0xd3, 0x00, 0x20, 0x00, 0xe0, 0x40, 0x1c, 0xa0, 0x75, ++ 0x65, 0xe7, 0xaa, 0x88, 0xa0, 0x7d, 0x13, 0x18, 0xcb, 0x5c, 0xbf, 0x28, 0x01, 0xd3, 0x00, 0x20, ++ 0x00, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0xa0, 0x75, 0x12, 0x18, 0x89, 0x5c, 0xbf, 0x28, 0x01, 0xd3, ++ 0x00, 0x20, 0x00, 0xe0, 0x40, 0x1c, 0xa0, 0x75, 0x03, 0x20, 0x00, 0x07, 0x82, 0x8a, 0x86, 0x82, ++ 0x18, 0x02, 0x08, 0x43, 0x3a, 0x68, 0x0d, 0x21, 0x49, 0x03, 0x51, 0x18, 0xc5, 0xe5, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0x86, 0x82, 0xff, 0xf7, 0xd7, 0xfc, 0xf3, 0xe7, 0x70, 0xb5, 0x01, 0xf0, ++ 0x63, 0xfa, 0x10, 0x49, 0x00, 0x20, 0x0b, 0x68, 0x11, 0x49, 0x18, 0x86, 0x1a, 0x46, 0x58, 0x86, ++ 0x80, 0x32, 0x90, 0x72, 0x1c, 0x46, 0xd0, 0x72, 0x40, 0x34, 0x20, 0x72, 0x60, 0x72, 0xa0, 0x72, ++ 0xe0, 0x72, 0x20, 0x73, 0xd0, 0x73, 0xa0, 0x73, 0x89, 0x7f, 0xe1, 0x73, 0x19, 0x46, 0x20, 0x74, ++ 0x60, 0x31, 0xc8, 0x75, 0x10, 0x71, 0x50, 0x71, 0x20, 0x75, 0xa0, 0x75, 0x08, 0x71, 0x48, 0x71, ++ 0x50, 0x72, 0x0d, 0xe0, 0x90, 0x00, 0x00, 0x20, 0x88, 0x00, 0x00, 0x20, 0xff, 0x02, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x80, 0xa1, 0x01, 0x00, 0x80, 0xa0, 0x01, 0x00, ++ 0xe0, 0x77, 0x58, 0x85, 0x88, 0x71, 0xc8, 0x71, 0x08, 0x72, 0x98, 0x85, 0xd8, 0x85, 0x48, 0x72, ++ 0x08, 0x75, 0xc8, 0x74, 0x48, 0x75, 0x88, 0x75, 0x48, 0x76, 0x88, 0x76, 0xc8, 0x76, 0x08, 0x77, ++ 0x90, 0x75, 0x10, 0x76, 0x01, 0x25, 0xd5, 0x75, 0x60, 0x80, 0x50, 0x76, 0x90, 0x76, 0xd0, 0x76, ++ 0x58, 0x82, 0x58, 0x73, 0x98, 0x73, 0xd8, 0x73, 0x18, 0x74, 0x48, 0x77, 0x88, 0x77, 0xc8, 0x77, ++ 0x10, 0x70, 0x08, 0x76, 0x90, 0x71, 0x98, 0x86, 0x10, 0x74, 0x70, 0xbd, 0x10, 0xb5, 0xff, 0xf7, ++ 0x89, 0xfb, 0xff, 0xf7, 0xa3, 0xff, 0x00, 0x21, 0x01, 0x20, 0x01, 0xf0, 0x81, 0xfb, 0x00, 0x21, ++ 0x02, 0x20, 0x01, 0xf0, 0x7d, 0xfb, 0x00, 0x21, 0x03, 0x20, 0x01, 0xf0, 0x79, 0xfb, 0x00, 0x21, ++ 0x04, 0x20, 0x01, 0xf0, 0x75, 0xfb, 0x00, 0x21, 0x05, 0x20, 0x01, 0xf0, 0x71, 0xfb, 0x62, 0xe4, ++ 0xf8, 0x48, 0x00, 0x68, 0xf8, 0x49, 0x40, 0x18, 0x80, 0x8a, 0xf8, 0x49, 0x00, 0x06, 0x02, 0x0f, ++ 0x08, 0x7c, 0xd2, 0x1e, 0x0b, 0x2a, 0x02, 0xd3, 0x10, 0x22, 0x10, 0x43, 0x01, 0xe0, 0xef, 0x22, ++ 0x10, 0x40, 0x08, 0x74, 0x70, 0x47, 0x70, 0xb5, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xf0, 0x49, ++ 0x81, 0x82, 0xec, 0x49, 0x01, 0x22, 0x0c, 0x68, 0xd2, 0x02, 0xeb, 0x4b, 0x40, 0x3b, 0xe4, 0x18, ++ 0x22, 0x85, 0x82, 0x8a, 0x40, 0x22, 0xd2, 0x43, 0x82, 0x82, 0x0c, 0x68, 0x40, 0x22, 0xe4, 0x18, ++ 0x22, 0x84, 0xe6, 0x4a, 0xd2, 0x7b, 0x00, 0x2a, 0x2b, 0xd1, 0x82, 0x8a, 0xe5, 0x4a, 0x82, 0x82, ++ 0x0d, 0x68, 0x84, 0x14, 0xe0, 0x4a, 0xad, 0x18, 0xec, 0x81, 0x85, 0x8a, 0xe2, 0x4d, 0x85, 0x82, ++ 0x0e, 0x68, 0x80, 0x25, 0xb6, 0x18, 0xf5, 0x81, 0x85, 0x8a, 0xe0, 0x4d, 0x85, 0x82, 0x0d, 0x68, ++ 0xad, 0x18, 0xec, 0x80, 0x84, 0x8a, 0xde, 0x4c, 0x84, 0x82, 0xff, 0x24, 0x0d, 0x68, 0xc1, 0x34, ++ 0xad, 0x18, 0xec, 0x80, 0x84, 0x8a, 0x78, 0x24, 0xe4, 0x43, 0x84, 0x82, 0x0d, 0x68, 0x08, 0x24, ++ 0xaa, 0x18, 0x14, 0x80, 0x82, 0x8a, 0xd7, 0x4a, 0x82, 0x82, 0x09, 0x68, 0xa0, 0x02, 0xc9, 0x18, ++ 0xc8, 0x84, 0x70, 0xbd, 0x70, 0x47, 0x70, 0xb5, 0x04, 0xf0, 0xdc, 0xfa, 0xcb, 0x4a, 0xd1, 0x88, ++ 0x00, 0x29, 0x14, 0xd0, 0xcb, 0x08, 0xc0, 0x1a, 0x08, 0x18, 0xd0, 0x80, 0x10, 0x7b, 0x01, 0x21, ++ 0x14, 0x28, 0x0e, 0xd2, 0xcc, 0x4b, 0xcd, 0x4d, 0x43, 0x43, 0x5b, 0x19, 0x9b, 0x12, 0xd4, 0x88, ++ 0x5b, 0x1c, 0x5b, 0x10, 0x9c, 0x42, 0x04, 0xdc, 0xd1, 0x74, 0x40, 0x1c, 0x0f, 0xe0, 0xc0, 0x00, ++ 0xeb, 0xe7, 0x00, 0x28, 0x0d, 0xd0, 0xc4, 0x4b, 0xc5, 0x4d, 0x43, 0x43, 0x5b, 0x19, 0x9b, 0x12, ++ 0xd4, 0x88, 0x5b, 0x1c, 0x5b, 0x10, 0x9c, 0x42, 0x03, 0xdb, 0xd1, 0x74, 0x40, 0x1e, 0x10, 0x73, ++ 0x70, 0xbd, 0x00, 0x20, 0xd0, 0x74, 0x70, 0xbd, 0x70, 0xb5, 0x24, 0x21, 0xb3, 0x48, 0x04, 0xf0, ++ 0xb7, 0xfd, 0xb2, 0x4c, 0x26, 0x20, 0x20, 0x80, 0xba, 0x48, 0xa0, 0x80, 0x0c, 0x20, 0xa0, 0x73, ++ 0x0b, 0x20, 0x00, 0x26, 0x20, 0x73, 0xe6, 0x74, 0x26, 0x75, 0x66, 0x75, 0x04, 0xf0, 0x9a, 0xfa, ++ 0xc0, 0x00, 0xe0, 0x80, 0x00, 0x25, 0xff, 0xf7, 0xb6, 0xff, 0x6d, 0x1c, 0xed, 0xb2, 0x08, 0x2d, ++ 0xf9, 0xd3, 0xa4, 0x48, 0x00, 0x68, 0xa4, 0x49, 0x40, 0x18, 0xc0, 0x8f, 0x28, 0x21, 0x00, 0x07, ++ 0x00, 0x0f, 0xe0, 0x73, 0x26, 0x74, 0x01, 0x20, 0x60, 0x73, 0xa1, 0x75, 0x04, 0x21, 0xe1, 0x75, ++ 0x10, 0x21, 0x21, 0x76, 0x66, 0x76, 0xa0, 0x76, 0x02, 0x20, 0xe0, 0x76, 0x03, 0x20, 0x20, 0x77, ++ 0x24, 0x20, 0x60, 0x77, 0x20, 0x20, 0xa0, 0x77, 0x05, 0x20, 0xe6, 0x77, 0xc0, 0x01, 0x20, 0x84, ++ 0x0b, 0x20, 0x80, 0x01, 0x60, 0x84, 0x5f, 0x21, 0xc9, 0x00, 0x9f, 0x48, 0x04, 0xf0, 0x78, 0xfd, ++ 0x9e, 0x48, 0x06, 0x60, 0x9e, 0x48, 0x60, 0x81, 0x20, 0x81, 0x41, 0x1c, 0x9a, 0x48, 0x04, 0xf0, ++ 0x6f, 0xfd, 0x70, 0xbd, 0x10, 0xb5, 0x9b, 0x48, 0x00, 0x21, 0x00, 0x68, 0x0a, 0x23, 0x02, 0x46, ++ 0x01, 0x80, 0x40, 0x32, 0x93, 0x71, 0xd1, 0x71, 0xc1, 0x72, 0x81, 0x72, 0x01, 0x73, 0x41, 0x73, ++ 0x81, 0x73, 0x01, 0x74, 0xc1, 0x73, 0x41, 0x82, 0x41, 0x74, 0x91, 0x74, 0x01, 0x71, 0x81, 0x71, ++ 0xc1, 0x71, 0x01, 0x72, 0x41, 0x72, 0x41, 0x77, 0x02, 0x22, 0x42, 0x71, 0x01, 0x22, 0x82, 0x70, ++ 0x80, 0x30, 0x01, 0x72, 0xff, 0xf7, 0x92, 0xfe, 0x01, 0xe7, 0x70, 0xb5, 0x7b, 0x4a, 0x79, 0x4b, ++ 0xd0, 0x7b, 0x00, 0x28, 0x22, 0xd1, 0x18, 0x68, 0x77, 0x4c, 0x00, 0x19, 0x80, 0x8a, 0x0f, 0x21, ++ 0x00, 0x06, 0x00, 0x0f, 0x09, 0x1a, 0x03, 0x20, 0x00, 0x07, 0x85, 0x8a, 0x77, 0x4d, 0x0f, 0x3d, ++ 0x85, 0x82, 0x8d, 0x02, 0x1e, 0x68, 0x0d, 0x43, 0x36, 0x19, 0xb5, 0x84, 0x85, 0x8a, 0x0f, 0x25, ++ 0xed, 0x43, 0x85, 0x82, 0x1d, 0x68, 0x2c, 0x19, 0xa1, 0x85, 0x81, 0x8a, 0x2a, 0x21, 0xc9, 0x43, ++ 0x81, 0x82, 0x19, 0x68, 0x2a, 0x20, 0x78, 0x4c, 0x09, 0x19, 0x88, 0x81, 0x19, 0x68, 0x76, 0x48, ++ 0x40, 0x30, 0x09, 0x18, 0x09, 0x8c, 0xc9, 0x06, 0xc9, 0x0e, 0x51, 0x76, 0x19, 0x68, 0x09, 0x18, ++ 0x49, 0x8c, 0xc9, 0x06, 0xc9, 0x0e, 0x91, 0x76, 0x19, 0x68, 0x09, 0x18, 0x89, 0x8c, 0xc9, 0x06, ++ 0xc9, 0x0e, 0xd1, 0x76, 0x19, 0x68, 0x08, 0x18, 0xc0, 0x8c, 0xc0, 0x06, 0xc0, 0x0e, 0x10, 0x77, ++ 0x70, 0xbd, 0xf8, 0xb5, 0x57, 0x4d, 0x29, 0x68, 0x67, 0x48, 0xc0, 0x30, 0x08, 0x18, 0xc0, 0x8a, ++ 0x64, 0x4f, 0x01, 0x07, 0x38, 0x68, 0x09, 0x0f, 0x40, 0x30, 0xc1, 0x74, 0x53, 0x48, 0x03, 0x24, ++ 0xc0, 0x7b, 0x51, 0x4e, 0x24, 0x07, 0x00, 0x28, 0x2e, 0xd1, 0x28, 0x68, 0x80, 0x19, 0x80, 0x8a, ++ 0x0f, 0x21, 0x00, 0x06, 0x00, 0x0f, 0x0b, 0x1a, 0xa0, 0x8a, 0x5c, 0x48, 0xa0, 0x82, 0x2a, 0x68, ++ 0x19, 0x03, 0x49, 0x48, 0x40, 0x38, 0x12, 0x18, 0x11, 0x85, 0xa1, 0x8a, 0x0f, 0x21, 0xc9, 0x43, ++ 0xa1, 0x82, 0x29, 0x68, 0x09, 0x18, 0x4b, 0x85, 0xa1, 0x8a, 0x03, 0x21, 0xc9, 0x43, 0xa1, 0x82, ++ 0x2a, 0x68, 0x03, 0x21, 0x10, 0x18, 0x01, 0x86, 0xa0, 0x8a, 0x78, 0x20, 0xc0, 0x43, 0xa0, 0x82, ++ 0x29, 0x68, 0xd8, 0x00, 0x89, 0x19, 0x08, 0x80, 0xa0, 0x8a, 0x02, 0x20, 0xc0, 0x43, 0xa0, 0x82, ++ 0x29, 0x68, 0x02, 0x20, 0x89, 0x19, 0x48, 0x82, 0xfd, 0xf7, 0xfa, 0xf9, 0x38, 0x68, 0x36, 0x4a, ++ 0x01, 0x78, 0x47, 0x4b, 0x4f, 0x07, 0xc0, 0x3a, 0x00, 0x21, 0x00, 0x2f, 0x09, 0xdb, 0x53, 0x27, ++ 0x3f, 0x5c, 0x00, 0x2f, 0x0b, 0xd1, 0x31, 0x4f, 0x3f, 0x78, 0xbf, 0x06, 0xff, 0x0e, 0x06, 0x2f, ++ 0x05, 0xd3, 0xa7, 0x8a, 0xa3, 0x82, 0x2b, 0x68, 0x9b, 0x18, 0x19, 0x80, 0x05, 0xe0, 0xa7, 0x8a, ++ 0xa3, 0x82, 0x2f, 0x68, 0x04, 0x23, 0xbf, 0x18, 0x3b, 0x80, 0x03, 0x78, 0x5b, 0x07, 0x12, 0xd4, ++ 0x53, 0x23, 0x1b, 0x5c, 0x00, 0x2b, 0x0e, 0xd1, 0x24, 0x4b, 0x1b, 0x78, 0x9b, 0x06, 0xdb, 0x0e, ++ 0x0e, 0x2b, 0x08, 0xd9, 0xa3, 0x8a, 0x80, 0x23, 0xdb, 0x43, 0xa3, 0x82, 0x2f, 0x68, 0x80, 0x23, ++ 0xba, 0x18, 0x13, 0x80, 0x06, 0xe0, 0xa3, 0x8a, 0x80, 0x23, 0xdb, 0x43, 0xa3, 0x82, 0x2b, 0x68, ++ 0x9a, 0x18, 0x11, 0x80, 0x02, 0x78, 0x52, 0x07, 0x14, 0xd5, 0x53, 0x22, 0x12, 0x5c, 0x00, 0x2a, ++ 0x10, 0xd1, 0x16, 0x4a, 0x12, 0x78, 0x92, 0x06, 0xd2, 0x0e, 0x16, 0x2a, 0x0a, 0xd9, 0xa2, 0x8a, ++ 0x02, 0x22, 0xd2, 0x43, 0xa2, 0x82, 0x2f, 0x68, 0x02, 0x22, 0x0f, 0x4b, 0x40, 0x3b, 0xfb, 0x18, ++ 0x9a, 0x85, 0x08, 0xe0, 0xa2, 0x8a, 0x02, 0x22, 0xd2, 0x43, 0xa2, 0x82, 0x2b, 0x68, 0x0a, 0x4a, ++ 0x40, 0x3a, 0x9a, 0x18, 0x91, 0x85, 0x02, 0x78, 0x53, 0x07, 0x09, 0x4a, 0xa3, 0x8a, 0xa2, 0x82, ++ 0x30, 0xd5, 0x01, 0x23, 0x2f, 0x68, 0xdb, 0x02, 0x03, 0x4a, 0x40, 0x3a, 0xba, 0x18, 0x53, 0x85, ++ 0x2c, 0xe0, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa1, 0x01, 0x00, 0x00, 0x04, 0x00, 0x20, ++ 0xff, 0xf7, 0x00, 0x00, 0xff, 0xe1, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0xff, 0xc3, 0x00, 0x00, ++ 0x3f, 0xfc, 0x00, 0x00, 0xff, 0xdf, 0x00, 0x00, 0x99, 0x56, 0xfc, 0xff, 0xe6, 0xf7, 0xd3, 0x00, ++ 0x5a, 0x60, 0xda, 0x00, 0x01, 0xd1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x88, 0x00, 0x00, 0x20, ++ 0xff, 0x02, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, 0x40, 0xa2, 0x01, 0x00, 0xff, 0x0f, 0x00, 0x00, ++ 0xfb, 0xff, 0x00, 0x00, 0x2b, 0x68, 0xfe, 0x4a, 0x9a, 0x18, 0x51, 0x85, 0x2a, 0x68, 0xff, 0x32, ++ 0x01, 0x32, 0x92, 0x8d, 0x92, 0x07, 0xd3, 0x0f, 0x02, 0x46, 0x80, 0x32, 0x53, 0x75, 0x94, 0x46, ++ 0x00, 0x2b, 0xf8, 0x4a, 0xa3, 0x8a, 0xa2, 0x82, 0x02, 0xd0, 0x1b, 0x23, 0x5b, 0x01, 0x01, 0xe0, ++ 0x11, 0x23, 0x5b, 0x01, 0x2f, 0x68, 0xf2, 0x4a, 0x80, 0x32, 0xba, 0x18, 0x13, 0x80, 0x62, 0x46, ++ 0x52, 0x7d, 0x00, 0x2a, 0x07, 0xd0, 0xa2, 0x8a, 0xef, 0x4a, 0xa2, 0x82, 0x07, 0x22, 0x2b, 0x68, ++ 0xd2, 0x02, 0x9b, 0x19, 0x5a, 0x81, 0xa2, 0x8a, 0x01, 0x22, 0xd2, 0x43, 0xa2, 0x82, 0x2f, 0x68, ++ 0x01, 0x22, 0x0d, 0x23, 0x5b, 0x03, 0xfb, 0x18, 0x5a, 0x80, 0x40, 0x30, 0xc2, 0x7c, 0xe5, 0x48, ++ 0x92, 0x1e, 0xe0, 0x30, 0x13, 0x00, 0x04, 0xf0, 0x33, 0xfc, 0x08, 0x05, 0x05, 0x05, 0x0a, 0x0a, ++ 0x05, 0x05, 0x0a, 0x14, 0xa2, 0x8a, 0xa0, 0x82, 0xff, 0x22, 0x01, 0x32, 0x03, 0xe0, 0xa2, 0x8a, ++ 0xa0, 0x82, 0x01, 0x22, 0x52, 0x02, 0x2b, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x18, 0x18, 0xc2, 0x80, ++ 0x06, 0xe0, 0xa2, 0x8a, 0xa0, 0x82, 0x2a, 0x68, 0x0d, 0x20, 0x40, 0x03, 0x10, 0x18, 0xc1, 0x80, ++ 0x2a, 0x68, 0xd6, 0x48, 0x10, 0x18, 0xc0, 0x8e, 0x00, 0x07, 0x00, 0x0f, 0x01, 0x28, 0x0f, 0xd0, ++ 0x04, 0x28, 0xa0, 0x8a, 0xd2, 0x48, 0xa0, 0x82, 0x28, 0x68, 0x11, 0xd0, 0x80, 0x19, 0x01, 0x80, ++ 0xa0, 0x8a, 0x01, 0x20, 0xc0, 0x43, 0xa0, 0x82, 0x28, 0x68, 0x80, 0x19, 0x41, 0x80, 0xf8, 0xbd, ++ 0xa0, 0x8a, 0xcb, 0x48, 0xa0, 0x82, 0x2a, 0x68, 0x80, 0x20, 0x92, 0x19, 0x10, 0x80, 0xef, 0xe7, ++ 0x80, 0x19, 0x01, 0x80, 0xa0, 0x8a, 0x01, 0x20, 0xc0, 0x43, 0xa0, 0x82, 0x29, 0x68, 0x01, 0x20, ++ 0x89, 0x19, 0x48, 0x80, 0xf8, 0xbd, 0xf8, 0xb5, 0x1f, 0x20, 0x01, 0xf0, 0x9e, 0xfd, 0x01, 0xf0, ++ 0x2b, 0xfb, 0xc0, 0x4f, 0x03, 0x24, 0x39, 0x68, 0x60, 0x31, 0x08, 0x70, 0x24, 0x07, 0xa0, 0x8a, ++ 0x09, 0x20, 0xc0, 0x43, 0xa0, 0x82, 0xbc, 0x4d, 0x08, 0x20, 0x29, 0x68, 0xb4, 0x4e, 0x80, 0x3e, ++ 0x89, 0x19, 0x08, 0x80, 0x00, 0x20, 0xfe, 0xf7, 0xf5, 0xf8, 0xb8, 0x49, 0xb8, 0x4a, 0xc8, 0x7f, ++ 0x03, 0x06, 0x15, 0xd5, 0xa3, 0x8a, 0xa2, 0x82, 0x40, 0x06, 0x40, 0x0e, 0x2a, 0x68, 0x92, 0x19, ++ 0x50, 0x80, 0xb0, 0x48, 0x00, 0x27, 0x00, 0x68, 0x02, 0x46, 0x40, 0x32, 0xd6, 0x7c, 0x33, 0x00, ++ 0x04, 0xf0, 0xbe, 0xfb, 0x09, 0x1b, 0x19, 0x43, 0x14, 0x43, 0x43, 0x14, 0x43, 0x14, 0x43, 0x00, ++ 0x38, 0x68, 0x03, 0x88, 0x9c, 0x46, 0x1b, 0x06, 0xeb, 0xd4, 0x83, 0x79, 0xdb, 0x07, 0xe8, 0xd1, ++ 0x63, 0x46, 0xa0, 0x8a, 0x5b, 0x07, 0xa2, 0x82, 0x07, 0x20, 0xdf, 0xe7, 0x2a, 0x21, 0xd1, 0x73, ++ 0x15, 0x21, 0x11, 0x74, 0x0d, 0xe0, 0xd7, 0x73, 0x0a, 0xe0, 0x03, 0x79, 0x1e, 0x06, 0x02, 0xd5, ++ 0x59, 0x06, 0x49, 0x0e, 0x03, 0xe0, 0x03, 0x78, 0x5b, 0x07, 0x1e, 0xd5, 0x49, 0x7f, 0xd1, 0x73, ++ 0x17, 0x74, 0x60, 0x30, 0xc7, 0x75, 0x0f, 0x20, 0x96, 0x4e, 0x10, 0x56, 0xfe, 0xf7, 0x2c, 0xfb, ++ 0x31, 0x68, 0x50, 0x20, 0x08, 0x56, 0xfe, 0xf7, 0xe1, 0xfa, 0x30, 0x68, 0x95, 0x4f, 0x00, 0x78, ++ 0x40, 0x07, 0x1b, 0xd5, 0x01, 0xf0, 0xef, 0xfd, 0x30, 0x68, 0x01, 0x78, 0x49, 0x07, 0x15, 0xd5, ++ 0x40, 0x30, 0xc0, 0x7c, 0x01, 0x28, 0x02, 0xd0, 0x10, 0xe0, 0x89, 0x7f, 0xdf, 0xe7, 0xa0, 0x8a, ++ 0x10, 0x20, 0xc0, 0x43, 0xa0, 0x82, 0x2a, 0x68, 0x10, 0x21, 0x81, 0x48, 0x12, 0x18, 0xd1, 0x84, ++ 0xa1, 0x8a, 0xa7, 0x82, 0x2a, 0x68, 0x20, 0x21, 0x10, 0x18, 0xc1, 0x84, 0xa0, 0x8a, 0xa7, 0x82, ++ 0x29, 0x68, 0x20, 0x20, 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, 0x08, 0x84, 0x30, 0x68, 0x01, 0x21, ++ 0x40, 0x30, 0x81, 0x73, 0xf8, 0xbd, 0x10, 0xb5, 0x7a, 0x4c, 0x20, 0x68, 0x60, 0x30, 0x00, 0x78, ++ 0x01, 0xf0, 0x0b, 0xfd, 0x21, 0x68, 0x61, 0x20, 0x08, 0x56, 0xfe, 0xf7, 0x73, 0xf8, 0x21, 0x68, ++ 0x00, 0x20, 0x40, 0x31, 0x88, 0x73, 0x0f, 0x20, 0x08, 0x56, 0xfe, 0xf7, 0xe5, 0xfa, 0x21, 0x68, ++ 0x50, 0x20, 0x08, 0x56, 0xfe, 0xf7, 0x9a, 0xfa, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x20, 0x21, ++ 0xc9, 0x43, 0x81, 0x82, 0x6c, 0x49, 0x20, 0x20, 0x09, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, ++ 0x08, 0x84, 0x20, 0x68, 0x01, 0x21, 0x40, 0x30, 0x81, 0x73, 0xa8, 0xe4, 0x30, 0xb5, 0x66, 0x4c, ++ 0x20, 0x68, 0x5f, 0x4d, 0xc0, 0x3d, 0x40, 0x19, 0xc0, 0x8e, 0x21, 0x68, 0x80, 0x04, 0x40, 0x0f, ++ 0x49, 0x19, 0xc9, 0x8e, 0x49, 0x05, 0x49, 0x0f, 0x40, 0x18, 0x21, 0x68, 0x40, 0x08, 0x49, 0x19, ++ 0xc9, 0x8e, 0x89, 0x06, 0x89, 0x0e, 0x43, 0x18, 0x20, 0x68, 0x40, 0x19, 0x00, 0x8f, 0x21, 0x68, ++ 0x80, 0x04, 0x40, 0x0f, 0x49, 0x19, 0x09, 0x8f, 0xc9, 0x06, 0xc9, 0x0e, 0x40, 0x18, 0x21, 0x68, ++ 0x49, 0x19, 0x09, 0x8f, 0x89, 0x09, 0xc9, 0x07, 0xc9, 0x0f, 0x00, 0xd0, 0x40, 0x42, 0x21, 0x68, ++ 0x49, 0x19, 0x09, 0x8f, 0x22, 0x68, 0x49, 0x05, 0x49, 0x0f, 0x52, 0x19, 0x12, 0x8f, 0xd2, 0x06, ++ 0xd2, 0x0e, 0x89, 0x18, 0x22, 0x68, 0x52, 0x19, 0x12, 0x8f, 0x52, 0x09, 0xd2, 0x07, 0xd2, 0x0f, ++ 0x00, 0xd0, 0x49, 0x42, 0x40, 0x18, 0x42, 0x10, 0x20, 0x68, 0x40, 0x19, 0x40, 0x8f, 0x80, 0x06, ++ 0x81, 0x16, 0x20, 0x68, 0x40, 0x19, 0x40, 0x8f, 0x24, 0x68, 0x40, 0x05, 0xc0, 0x16, 0x65, 0x19, ++ 0x3a, 0x24, 0x2c, 0x5f, 0xe4, 0x12, 0x00, 0x2b, 0x00, 0xda, 0x5b, 0x42, 0x00, 0x2a, 0x00, 0xda, ++ 0x52, 0x42, 0x9a, 0x18, 0x00, 0x29, 0x00, 0xda, 0x49, 0x42, 0x51, 0x18, 0x00, 0x28, 0x00, 0xda, ++ 0x40, 0x42, 0x08, 0x18, 0x00, 0x2c, 0x00, 0xda, 0x64, 0x42, 0x00, 0x19, 0x80, 0xb2, 0x30, 0xbd, ++ 0xf0, 0xb5, 0x35, 0x4c, 0x21, 0x68, 0x2e, 0x48, 0xc0, 0x38, 0x09, 0x18, 0xc9, 0x8e, 0x22, 0x68, ++ 0x89, 0x04, 0x49, 0x0f, 0x12, 0x18, 0xd2, 0x8e, 0x52, 0x05, 0x52, 0x0f, 0x89, 0x18, 0x22, 0x68, ++ 0x49, 0x08, 0x12, 0x18, 0xd2, 0x8e, 0x92, 0x06, 0x92, 0x0e, 0x8e, 0x18, 0x21, 0x68, 0x09, 0x18, ++ 0x09, 0x8f, 0x22, 0x68, 0x89, 0x04, 0x49, 0x0f, 0x12, 0x18, 0x12, 0x8f, 0xd2, 0x06, 0xd2, 0x0e, ++ 0x89, 0x18, 0x22, 0x68, 0x12, 0x18, 0x12, 0x8f, 0x92, 0x09, 0xd2, 0x07, 0xd2, 0x0f, 0x00, 0xd0, ++ 0x49, 0x42, 0x22, 0x68, 0x12, 0x18, 0x12, 0x8f, 0x23, 0x68, 0x52, 0x05, 0x52, 0x0f, 0x1b, 0x18, ++ 0x1b, 0x8f, 0xdb, 0x06, 0xdb, 0x0e, 0xd2, 0x18, 0x23, 0x68, 0x1b, 0x18, 0x1b, 0x8f, 0x5b, 0x09, ++ 0xdb, 0x07, 0xdb, 0x0f, 0x00, 0xd0, 0x52, 0x42, 0x89, 0x18, 0x4a, 0x10, 0x21, 0x68, 0x10, 0x48, ++ 0xc0, 0x38, 0x09, 0x18, 0x49, 0x8f, 0x27, 0x68, 0x89, 0x06, 0x89, 0x16, 0x55, 0x18, 0x4b, 0x00, ++ 0x5d, 0x19, 0x3f, 0x18, 0x7f, 0x8f, 0x7f, 0x05, 0xff, 0x16, 0x7f, 0x00, 0xed, 0x19, 0x27, 0x68, ++ 0x3f, 0x18, 0x3a, 0x20, 0x38, 0x5e, 0xc0, 0x12, 0x28, 0x18, 0x0a, 0x4d, 0x2d, 0x68, 0x2d, 0x88, ++ 0xaf, 0x06, 0xbf, 0x0f, 0x02, 0x2f, 0x28, 0xd1, 0x6d, 0x07, 0x26, 0xd5, 0x50, 0x00, 0x13, 0xe0, ++ 0x00, 0xa1, 0x01, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0xff, 0xc7, 0x00, 0x00, 0x00, 0xa3, 0x01, 0x00, ++ 0x7f, 0xff, 0xff, 0xff, 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, ++ 0xf0, 0xff, 0x00, 0x00, 0xdf, 0xff, 0x00, 0x00, 0x80, 0x19, 0x40, 0x18, 0x22, 0x68, 0xc1, 0x18, ++ 0x2e, 0x48, 0x12, 0x18, 0x52, 0x8f, 0x52, 0x05, 0xd2, 0x16, 0x52, 0x00, 0x89, 0x18, 0x22, 0x68, ++ 0x12, 0x18, 0x3a, 0x20, 0x10, 0x5e, 0xc0, 0x12, 0x08, 0x18, 0xf0, 0xbd, 0x00, 0xb5, 0xff, 0xf7, ++ 0x15, 0xff, 0x81, 0x00, 0x40, 0x00, 0x08, 0x18, 0x80, 0xb2, 0x00, 0xbd, 0x00, 0xb5, 0x00, 0x22, ++ 0xfd, 0xf7, 0x57, 0xff, 0x00, 0x28, 0x01, 0xda, 0x40, 0x42, 0x01, 0x22, 0x20, 0x49, 0x09, 0x68, ++ 0x1e, 0x4b, 0x40, 0x33, 0xc9, 0x18, 0x09, 0x88, 0xc9, 0x08, 0xc9, 0x07, 0xc9, 0x0f, 0x02, 0xd0, ++ 0x40, 0x00, 0x1c, 0x49, 0x02, 0xe0, 0x1b, 0x49, 0x40, 0x00, 0x40, 0x39, 0x08, 0x5e, 0x00, 0x2a, ++ 0x01, 0xd0, 0x40, 0x42, 0x00, 0xb2, 0x00, 0xbd, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, ++ 0x8a, 0x13, 0x8a, 0x82, 0x12, 0x4a, 0x80, 0x06, 0x14, 0x68, 0xc3, 0x0d, 0x0f, 0x48, 0x24, 0x18, ++ 0xe3, 0x82, 0x8b, 0x8a, 0x10, 0x4b, 0x8b, 0x82, 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, ++ 0x82, 0xe4, 0xc2, 0x06, 0xd2, 0x0e, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x0b, 0x4a, 0x80, 0x00, ++ 0x80, 0x18, 0x01, 0x60, 0x70, 0x47, 0xc2, 0x06, 0xd2, 0x0e, 0x01, 0x21, 0x91, 0x40, 0x07, 0x4a, ++ 0x40, 0x09, 0x80, 0x00, 0x80, 0x32, 0x80, 0x18, 0x01, 0x60, 0x70, 0x47, 0x40, 0xa0, 0x01, 0x00, ++ 0x84, 0x00, 0x00, 0x20, 0x14, 0x7a, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xe0, ++ 0x70, 0xb5, 0xfd, 0x49, 0x00, 0x25, 0x0a, 0x68, 0x11, 0x46, 0x40, 0x31, 0x13, 0x46, 0x60, 0x33, ++ 0xcd, 0x75, 0x4d, 0x77, 0x1d, 0x73, 0xd5, 0x83, 0x1c, 0x46, 0x15, 0x84, 0x00, 0x28, 0x09, 0xd0, ++ 0x0f, 0x24, 0xe4, 0x43, 0x01, 0x28, 0x08, 0xd0, 0x00, 0x23, 0x02, 0x28, 0x1a, 0xd0, 0x03, 0x28, ++ 0x17, 0xd0, 0x05, 0xe0, 0x0f, 0x23, 0xe5, 0x77, 0x02, 0xe0, 0x80, 0x32, 0x23, 0x46, 0x15, 0x70, ++ 0x10, 0x24, 0x0c, 0x57, 0x02, 0x28, 0x0d, 0xd0, 0x03, 0x28, 0x0b, 0xd0, 0x4b, 0x76, 0xcd, 0x76, ++ 0x48, 0x7e, 0x88, 0x76, 0x18, 0x46, 0xfd, 0xf7, 0xe5, 0xfe, 0x20, 0x46, 0xfe, 0xf7, 0x16, 0xf9, ++ 0x70, 0xbd, 0x0f, 0x24, 0x4c, 0x76, 0xf2, 0xe7, 0x70, 0xb5, 0xe3, 0x4c, 0x00, 0x25, 0x21, 0x68, ++ 0x0a, 0x46, 0x40, 0x32, 0x0b, 0x46, 0x60, 0x33, 0xd5, 0x75, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x28, ++ 0x0c, 0xd0, 0xd5, 0x76, 0x02, 0x28, 0x1d, 0xd0, 0x03, 0x28, 0x22, 0xd0, 0x0f, 0xe0, 0xc8, 0x7b, ++ 0xc6, 0x08, 0xd6, 0x76, 0xdb, 0x7f, 0x00, 0x02, 0xc0, 0x18, 0x07, 0xe0, 0x08, 0x7c, 0xc3, 0x08, ++ 0x5b, 0x42, 0xd3, 0x76, 0x03, 0x02, 0x80, 0x20, 0x40, 0x5c, 0x18, 0x18, 0x88, 0x84, 0x95, 0x76, ++ 0x1b, 0x20, 0x10, 0x56, 0xfd, 0xf7, 0xb6, 0xfe, 0x21, 0x68, 0x5a, 0x20, 0x08, 0x56, 0xfe, 0xf7, ++ 0xe5, 0xf8, 0x70, 0xbd, 0x48, 0x7b, 0xc5, 0x08, 0x6d, 0x42, 0x95, 0x76, 0x00, 0x02, 0x5b, 0x7f, ++ 0x04, 0xe0, 0x88, 0x7b, 0xc5, 0x08, 0x95, 0x76, 0x9b, 0x7f, 0x00, 0x02, 0xc0, 0x18, 0x88, 0x84, ++ 0xe6, 0xe7, 0xf0, 0xb5, 0xc4, 0x4c, 0x94, 0x46, 0x24, 0x68, 0x08, 0x9a, 0x01, 0x25, 0x05, 0x9f, ++ 0x06, 0x9e, 0x60, 0x34, 0x01, 0x2a, 0x03, 0xd0, 0x00, 0x29, 0x16, 0xdb, 0x01, 0x21, 0x0a, 0xe0, ++ 0x00, 0x29, 0x06, 0xd0, 0x02, 0xda, 0x00, 0x2b, 0x03, 0xdc, 0x0e, 0xe0, 0x00, 0x2b, 0xf5, 0xda, ++ 0x60, 0x46, 0x25, 0x73, 0x05, 0xe0, 0x07, 0x9a, 0x51, 0x43, 0x40, 0x1a, 0x00, 0x21, 0x40, 0xb2, ++ 0x21, 0x73, 0xb0, 0x42, 0x04, 0xdd, 0x30, 0x46, 0x05, 0xe0, 0x00, 0x21, 0xc9, 0x43, 0xf2, 0xe7, ++ 0xb8, 0x42, 0x01, 0xda, 0x38, 0x46, 0x25, 0x73, 0xf0, 0xbd, 0xf0, 0xb5, 0x85, 0xb0, 0x05, 0x00, ++ 0x4c, 0xd0, 0x1e, 0x20, 0xc0, 0x43, 0x01, 0x2d, 0x01, 0xd0, 0x03, 0x2d, 0x46, 0xd0, 0x00, 0x22, ++ 0xa9, 0x49, 0x1e, 0x23, 0x09, 0x68, 0x20, 0x24, 0xcb, 0x5e, 0x0c, 0x5f, 0x9b, 0x02, 0x23, 0x43, ++ 0x0c, 0x46, 0x40, 0x34, 0xe6, 0x7c, 0x0f, 0x3b, 0x01, 0x2e, 0xa4, 0x4e, 0x36, 0x68, 0xa4, 0x4f, ++ 0x37, 0xd0, 0xf6, 0x19, 0x36, 0x8e, 0xce, 0x83, 0xa0, 0x4e, 0x36, 0x68, 0xf6, 0x19, 0x76, 0x8e, ++ 0xb6, 0x05, 0xb6, 0x0d, 0x0e, 0x84, 0x1e, 0x26, 0x8e, 0x5f, 0x20, 0x27, 0xcf, 0x5f, 0xb6, 0x02, ++ 0x3e, 0x43, 0x19, 0x21, 0x0f, 0x3e, 0x61, 0x56, 0xb4, 0x46, 0x4e, 0x1c, 0x02, 0x2e, 0x01, 0xd9, ++ 0x49, 0x10, 0x61, 0x76, 0x61, 0x7f, 0x5a, 0x27, 0x49, 0x1c, 0xce, 0xb2, 0x92, 0x49, 0x66, 0x77, ++ 0x09, 0x68, 0x05, 0x2e, 0xcf, 0x57, 0x1d, 0xd8, 0x19, 0x21, 0x61, 0x56, 0x00, 0x26, 0x01, 0x92, ++ 0x02, 0x91, 0x00, 0x90, 0x03, 0x96, 0x1b, 0x22, 0xa2, 0x56, 0x38, 0x46, 0x61, 0x46, 0xff, 0xf7, ++ 0x88, 0xff, 0x89, 0x49, 0x09, 0x68, 0x40, 0x31, 0xce, 0x75, 0x23, 0xe0, 0x1f, 0x22, 0x00, 0x20, ++ 0xb6, 0xe7, 0xf6, 0x19, 0x36, 0x8d, 0xce, 0x83, 0x84, 0x4e, 0x36, 0x68, 0xf6, 0x19, 0x76, 0x8d, ++ 0xf6, 0xb2, 0xc7, 0xe7, 0x01, 0x21, 0x07, 0x2e, 0x12, 0xd8, 0x19, 0x26, 0xa6, 0x57, 0x01, 0x92, ++ 0x03, 0x91, 0x00, 0x90, 0x02, 0x96, 0x1b, 0x22, 0xa2, 0x56, 0x38, 0x46, 0x61, 0x46, 0xff, 0xf7, ++ 0x68, 0xff, 0x79, 0x49, 0x6c, 0x22, 0x09, 0x68, 0x52, 0x5c, 0x40, 0x31, 0xca, 0x75, 0x01, 0xe0, ++ 0x38, 0x46, 0xe1, 0x75, 0x74, 0x4c, 0x21, 0x68, 0x40, 0x31, 0x8a, 0x7e, 0xca, 0x76, 0x88, 0x76, ++ 0x00, 0x2d, 0x0a, 0xd0, 0x01, 0x2d, 0x08, 0xd0, 0xfe, 0xf7, 0x28, 0xf8, 0x20, 0x68, 0x01, 0x46, ++ 0x40, 0x30, 0xc2, 0x7d, 0x01, 0x2a, 0x03, 0xd0, 0x0f, 0xe0, 0xfd, 0xf7, 0xeb, 0xfd, 0xf5, 0xe7, ++ 0x00, 0x2d, 0x0d, 0xd0, 0x01, 0x2d, 0x13, 0xd0, 0x6a, 0x4a, 0x02, 0x2d, 0x82, 0x56, 0x17, 0xd0, ++ 0x00, 0x2a, 0x00, 0xda, 0x52, 0x42, 0xd0, 0x00, 0x88, 0x73, 0x00, 0x20, 0x05, 0xb0, 0xf0, 0xbd, ++ 0x1a, 0x22, 0x82, 0x56, 0x00, 0x2a, 0x00, 0xda, 0x52, 0x42, 0xd0, 0x00, 0xc8, 0x73, 0xf4, 0xe7, ++ 0x1a, 0x22, 0x82, 0x56, 0x00, 0x2a, 0x00, 0xda, 0x52, 0x42, 0xd0, 0x00, 0x08, 0x74, 0xec, 0xe7, ++ 0x00, 0x2a, 0x00, 0xda, 0x52, 0x42, 0xd0, 0x00, 0x48, 0x73, 0xe6, 0xe7, 0xf8, 0xb5, 0x56, 0x4e, ++ 0x04, 0x46, 0x30, 0x68, 0x53, 0x21, 0x0b, 0x5c, 0x00, 0x25, 0x54, 0x49, 0x01, 0x2b, 0x54, 0x4a, ++ 0x0b, 0x68, 0x17, 0xd0, 0x9b, 0x18, 0x1b, 0x8e, 0xc3, 0x83, 0x09, 0x68, 0x89, 0x18, 0x49, 0x8e, ++ 0x89, 0x05, 0x89, 0x0d, 0x01, 0x84, 0xfd, 0xf7, 0xa4, 0xfd, 0x31, 0x68, 0x0b, 0x46, 0x40, 0x33, ++ 0xd8, 0x76, 0x02, 0x2c, 0x0e, 0xd0, 0x03, 0x2c, 0x0f, 0xd0, 0x01, 0x2c, 0x10, 0xd0, 0x00, 0x2c, ++ 0x11, 0xd0, 0x12, 0xe0, 0x9b, 0x18, 0x1b, 0x8d, 0xc3, 0x83, 0x09, 0x68, 0x89, 0x18, 0x49, 0x8d, ++ 0xc9, 0xb2, 0xe7, 0xe7, 0x79, 0x20, 0x45, 0x5c, 0x07, 0xe0, 0x7a, 0x20, 0x45, 0x5c, 0x04, 0xe0, ++ 0x7b, 0x20, 0x45, 0x5c, 0x01, 0xe0, 0x7c, 0x20, 0x45, 0x5c, 0xca, 0x8b, 0x00, 0x20, 0x00, 0x2a, ++ 0x05, 0xd0, 0x0a, 0x20, 0x0c, 0xe0, 0x52, 0x10, 0x40, 0x1c, 0x0a, 0x84, 0x40, 0xb2, 0x20, 0x22, ++ 0x8a, 0x5e, 0x00, 0x2a, 0xf7, 0xdc, 0x07, 0xe0, 0x52, 0x10, 0x40, 0x1c, 0xca, 0x83, 0x40, 0xb2, ++ 0x1e, 0x22, 0x8a, 0x5e, 0x00, 0x2a, 0xf7, 0xdc, 0x00, 0x1f, 0x40, 0xb2, 0x8a, 0x8c, 0xc0, 0x01, ++ 0xd2, 0x08, 0xc0, 0x10, 0x1f, 0x27, 0x10, 0x1a, 0x3f, 0x02, 0x02, 0x2c, 0x05, 0xd0, 0x03, 0x2c, ++ 0x03, 0xd0, 0x01, 0x2c, 0x01, 0xd0, 0x00, 0x2c, 0x02, 0xd1, 0xb8, 0x42, 0x00, 0xdd, 0x38, 0x46, ++ 0xc2, 0x04, 0x16, 0x0c, 0xea, 0x00, 0x12, 0x18, 0x8e, 0x84, 0x02, 0x2c, 0x05, 0xd0, 0x03, 0x2c, ++ 0x03, 0xd0, 0x01, 0x2c, 0x01, 0xd0, 0x00, 0x2c, 0x02, 0xd1, 0xba, 0x42, 0x00, 0xdd, 0x3a, 0x46, ++ 0xd0, 0x04, 0x00, 0x0c, 0x42, 0x05, 0x1f, 0x27, 0x12, 0x0e, 0x7d, 0x42, 0x00, 0x2c, 0x0a, 0xd0, ++ 0x03, 0x2c, 0x08, 0xd0, 0xc0, 0x0a, 0x40, 0x42, 0x01, 0x2c, 0x07, 0xd0, 0x02, 0x2c, 0x11, 0xd0, ++ 0x03, 0x2c, 0x0f, 0xd0, 0x19, 0xe0, 0xc0, 0x0a, 0x00, 0x2c, 0xf5, 0xd1, 0x1f, 0x28, 0x01, 0xdd, ++ 0xdf, 0x76, 0x12, 0xe0, 0xa8, 0x42, 0x01, 0xda, 0xdd, 0x76, 0x0e, 0xe0, 0x00, 0x28, 0x0c, 0xd0, ++ 0xd8, 0x76, 0x0a, 0xe0, 0x1f, 0x28, 0x01, 0xdd, 0x9f, 0x76, 0x06, 0xe0, 0xa8, 0x42, 0x01, 0xda, ++ 0x9d, 0x76, 0x02, 0xe0, 0x00, 0x28, 0x00, 0xd0, 0x98, 0x76, 0x01, 0x20, 0xd8, 0x75, 0x00, 0x2c, ++ 0x12, 0xd0, 0x01, 0x2c, 0x16, 0xd0, 0x02, 0x2c, 0x1b, 0xd0, 0x30, 0x0a, 0x88, 0x73, 0x60, 0x31, ++ 0x8e, 0x77, 0x8a, 0x76, 0x00, 0x20, 0xf8, 0xbd, 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, ++ 0x40, 0xa0, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x30, 0x0a, 0xc8, 0x73, 0x60, 0x31, 0xce, 0x77, ++ 0x0a, 0x77, 0xef, 0xe7, 0x30, 0x0a, 0x08, 0x74, 0x80, 0x20, 0x46, 0x54, 0x60, 0x31, 0xca, 0x76, ++ 0xe8, 0xe7, 0x30, 0x0a, 0x48, 0x73, 0x60, 0x31, 0x4e, 0x77, 0x4a, 0x76, 0xe2, 0xe7, 0x30, 0xb5, ++ 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x80, 0x22, 0xd2, 0x43, 0x8a, 0x82, 0xfe, 0x4a, 0xc4, 0x01, ++ 0x15, 0x68, 0xfe, 0x4b, 0xed, 0x18, 0xec, 0x81, 0x8c, 0x8a, 0x40, 0x24, 0xe4, 0x43, 0x8c, 0x82, ++ 0x11, 0x68, 0x80, 0x01, 0xc9, 0x18, 0xc8, 0x81, 0x30, 0xbd, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, ++ 0x8a, 0x8a, 0x8a, 0x13, 0x8a, 0x82, 0xc0, 0x05, 0x15, 0x22, 0xc0, 0x0d, 0x52, 0x02, 0x83, 0x18, ++ 0xf1, 0x4a, 0x14, 0x68, 0xf1, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0xf0, 0x4b, 0x8b, 0x82, ++ 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, 0x10, 0xbd, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, ++ 0x8a, 0x8a, 0x8a, 0x13, 0x8a, 0x82, 0xc0, 0x05, 0x0b, 0x22, 0xc0, 0x0d, 0x92, 0x02, 0x83, 0x18, ++ 0xe5, 0x4a, 0x14, 0x68, 0xe5, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0xe4, 0x4b, 0x8b, 0x82, ++ 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, 0x10, 0xbd, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, ++ 0x8a, 0x8a, 0x8a, 0x13, 0x8a, 0x82, 0xc0, 0x05, 0x13, 0x22, 0xc0, 0x0d, 0x52, 0x02, 0x83, 0x18, ++ 0xd9, 0x4a, 0x14, 0x68, 0xd9, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0xd8, 0x4b, 0x8b, 0x82, ++ 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, 0x10, 0xbd, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, ++ 0x8a, 0x8a, 0x8a, 0x13, 0x8a, 0x82, 0xc0, 0x05, 0x05, 0x22, 0xc0, 0x0d, 0xd2, 0x02, 0x83, 0x18, ++ 0xcd, 0x4a, 0x14, 0x68, 0xcd, 0x48, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0xcc, 0x4b, 0x8b, 0x82, ++ 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x24, 0x00, 0x28, ++ 0x06, 0xdd, 0x20, 0x46, 0xff, 0xf7, 0xe1, 0xff, 0x20, 0x46, 0xff, 0xf7, 0xc6, 0xff, 0x10, 0xbd, ++ 0x00, 0x28, 0x20, 0x46, 0x05, 0xda, 0xff, 0xf7, 0xa8, 0xff, 0x20, 0x46, 0xff, 0xf7, 0x8d, 0xff, ++ 0x10, 0xbd, 0xfd, 0xf7, 0x60, 0xff, 0x20, 0x46, 0xfd, 0xf7, 0x45, 0xff, 0x10, 0xbd, 0x10, 0xb5, ++ 0xbc, 0x4b, 0x8a, 0x40, 0x1b, 0x68, 0x02, 0x40, 0x1c, 0x8e, 0x84, 0x43, 0x14, 0x43, 0x1c, 0x86, ++ 0x10, 0xbd, 0x10, 0xb5, 0xb7, 0x4b, 0x8a, 0x40, 0x1b, 0x68, 0x02, 0x40, 0x5c, 0x8e, 0x84, 0x43, ++ 0x14, 0x43, 0x5c, 0x86, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfd, 0xf7, 0xc7, 0xfd, 0x03, 0x21, ++ 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0xab, 0x48, 0xe2, 0x06, 0x03, 0x68, ++ 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0xaa, 0x4a, 0x8a, 0x82, ++ 0xaa, 0x4b, 0x04, 0x68, 0xa5, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, ++ 0x01, 0x21, 0x00, 0x68, 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, ++ 0xfd, 0xf7, 0xa4, 0xfd, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, ++ 0x99, 0x48, 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, ++ 0x8a, 0x8a, 0x99, 0x4a, 0x8a, 0x82, 0x09, 0x23, 0x04, 0x68, 0x1b, 0x03, 0x93, 0x4a, 0xa4, 0x18, ++ 0x23, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, 0x01, 0x21, 0x00, 0x68, 0x89, 0x02, 0x80, 0x18, ++ 0x81, 0x84, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfd, 0xf7, 0x80, 0xfd, 0x03, 0x21, 0x09, 0x07, ++ 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0x87, 0x48, 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, ++ 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0x87, 0x4a, 0x20, 0x3a, 0x8a, 0x82, ++ 0x86, 0x4b, 0x04, 0x68, 0x14, 0x33, 0x81, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0x00, 0x23, ++ 0x8b, 0x82, 0x83, 0x4b, 0x04, 0x68, 0xa4, 0x18, 0x63, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, ++ 0x01, 0x21, 0x00, 0x68, 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x10, 0xbd, 0x00, 0x28, 0x00, 0xda, ++ 0xc0, 0x43, 0x80, 0xb2, 0x70, 0x47, 0xff, 0xb5, 0x76, 0x4c, 0x07, 0x46, 0x20, 0x68, 0x00, 0x22, ++ 0x09, 0x9e, 0x0a, 0x9d, 0x60, 0x30, 0x94, 0x46, 0x00, 0x29, 0x03, 0xd0, 0x04, 0xda, 0x00, 0x2b, ++ 0x04, 0xdc, 0x14, 0xe0, 0x01, 0x21, 0x19, 0xe0, 0x00, 0x2b, 0x0e, 0xda, 0x08, 0x46, 0xff, 0xf7, ++ 0xe5, 0xff, 0x01, 0x46, 0x18, 0x46, 0xff, 0xf7, 0xe1, 0xff, 0x81, 0x42, 0x00, 0xd3, 0x02, 0x9f, ++ 0x21, 0x68, 0x01, 0x20, 0x60, 0x31, 0x08, 0x73, 0x09, 0xe0, 0x01, 0x21, 0x01, 0xe0, 0x00, 0x21, ++ 0xc9, 0x43, 0x0b, 0x9b, 0x59, 0x43, 0x79, 0x1a, 0x4f, 0xb2, 0x00, 0x21, 0x01, 0x73, 0xaf, 0x42, ++ 0x01, 0xdd, 0x2f, 0x46, 0x02, 0xe0, 0xb7, 0x42, 0x04, 0xda, 0x37, 0x46, 0x21, 0x68, 0x01, 0x22, ++ 0x60, 0x31, 0x0a, 0x73, 0xaf, 0x42, 0x01, 0xd0, 0xb7, 0x42, 0x01, 0xd1, 0x01, 0x20, 0x84, 0x46, ++ 0x20, 0x68, 0x61, 0x46, 0x60, 0x30, 0x82, 0x72, 0xc1, 0x72, 0x38, 0x46, 0x04, 0xb0, 0xf0, 0xbd, ++ 0xf0, 0xb5, 0x04, 0x24, 0xa6, 0x46, 0x01, 0x27, 0x06, 0x9d, 0x00, 0x24, 0x05, 0x9e, 0xbc, 0x46, ++ 0xa8, 0x42, 0x36, 0xdc, 0xaa, 0x42, 0x34, 0xdc, 0xb0, 0x42, 0x32, 0xdb, 0xb2, 0x42, 0x30, 0xdb, ++ 0x07, 0x9f, 0x4d, 0x42, 0x5e, 0x42, 0x87, 0x42, 0x0e, 0xd1, 0x00, 0x29, 0x29, 0xd0, 0x90, 0x42, ++ 0x01, 0xdd, 0x60, 0x1e, 0x84, 0x46, 0x00, 0x29, 0x00, 0xda, 0x29, 0x46, 0x08, 0xb2, 0x00, 0x2b, ++ 0x00, 0xda, 0x33, 0x46, 0x19, 0xb2, 0x10, 0xe0, 0x97, 0x42, 0x1a, 0xd1, 0x00, 0x2b, 0x18, 0xd0, ++ 0x82, 0x42, 0x02, 0xdd, 0x00, 0x20, 0xc0, 0x43, 0x84, 0x46, 0x00, 0x2b, 0x00, 0xda, 0x33, 0x46, ++ 0x18, 0xb2, 0x00, 0x29, 0x00, 0xda, 0x29, 0x46, 0x09, 0xb2, 0x00, 0x22, 0x01, 0x23, 0xdb, 0x03, ++ 0x88, 0x42, 0x08, 0xda, 0x09, 0x1a, 0x64, 0x00, 0xc9, 0x03, 0xc9, 0x18, 0x64, 0xb2, 0x09, 0x14, ++ 0x08, 0xe0, 0x00, 0x20, 0xf0, 0xbd, 0x64, 0x00, 0x64, 0x1c, 0x40, 0x1a, 0xc0, 0x03, 0xc0, 0x18, ++ 0x64, 0xb2, 0x00, 0x14, 0x52, 0x1c, 0xd2, 0xb2, 0x72, 0x45, 0xe9, 0xd9, 0x64, 0x1c, 0x60, 0x10, ++ 0x61, 0x46, 0x49, 0x1c, 0xee, 0xd1, 0x40, 0x42, 0x40, 0xb2, 0xf0, 0xbd, 0xf0, 0xb5, 0x04, 0x46, ++ 0x87, 0xb0, 0x01, 0x20, 0x05, 0x90, 0x2b, 0x48, 0x23, 0x4f, 0x00, 0x2c, 0x08, 0xdd, 0x39, 0x68, ++ 0x09, 0x18, 0x09, 0x89, 0x89, 0x06, 0x8e, 0x16, 0x39, 0x68, 0x08, 0x18, 0xc0, 0x88, 0x11, 0xe0, ++ 0x39, 0x68, 0x00, 0x2c, 0x07, 0xda, 0x09, 0x18, 0x89, 0x89, 0x89, 0x06, 0x8e, 0x16, 0x39, 0x68, ++ 0x08, 0x18, 0x40, 0x89, 0x06, 0xe0, 0x09, 0x18, 0x89, 0x88, 0x89, 0x06, 0x8e, 0x16, 0x39, 0x68, ++ 0x08, 0x18, 0x40, 0x88, 0x80, 0x06, 0x85, 0x16, 0x16, 0x48, 0x00, 0x68, 0x01, 0x46, 0x40, 0x31, ++ 0x8c, 0x46, 0x49, 0x7f, 0x00, 0x29, 0x76, 0xd1, 0x3a, 0x68, 0x10, 0x49, 0x52, 0x18, 0x28, 0x21, ++ 0x51, 0x5e, 0x1f, 0x22, 0x03, 0x91, 0x05, 0x9b, 0x51, 0x42, 0x02, 0x93, 0x01, 0x92, 0x00, 0x91, ++ 0x1e, 0x23, 0xc3, 0x5e, 0x60, 0x46, 0x18, 0x22, 0x82, 0x56, 0x30, 0x46, 0x03, 0x99, 0xff, 0xf7, ++ 0x22, 0xff, 0x04, 0x90, 0x07, 0x48, 0x6c, 0x21, 0x00, 0x68, 0x09, 0x5c, 0x00, 0x29, 0x2f, 0xd0, ++ 0x1f, 0x22, 0x51, 0x42, 0x04, 0x9b, 0x0f, 0xe0, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, ++ 0xff, 0x7f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, 0xf3, 0x0f, 0x00, 0x00, 0x0c, 0xa0, 0x00, 0x00, ++ 0x20, 0x20, 0x00, 0x00, 0x80, 0xa2, 0x01, 0x00, 0x02, 0x93, 0x01, 0x92, 0x00, 0x91, 0x1e, 0x23, ++ 0x58, 0x22, 0xc3, 0x5e, 0x82, 0x56, 0x30, 0x46, 0x03, 0x99, 0xff, 0xf7, 0x41, 0xff, 0x01, 0x46, ++ 0xfe, 0x48, 0x5b, 0x22, 0x00, 0x68, 0x00, 0x2c, 0x11, 0x54, 0x02, 0xdd, 0x60, 0x30, 0x41, 0x74, ++ 0x06, 0xe0, 0x00, 0x2c, 0x02, 0xda, 0x60, 0x30, 0xc1, 0x73, 0x01, 0xe0, 0x60, 0x30, 0x41, 0x73, ++ 0xf6, 0x48, 0x00, 0x68, 0x01, 0x46, 0x40, 0x31, 0x0e, 0x76, 0x03, 0x9a, 0xc2, 0x83, 0x60, 0x30, ++ 0x00, 0x7b, 0x48, 0x77, 0x00, 0x2c, 0x03, 0xdd, 0x04, 0x98, 0xff, 0xf7, 0x1e, 0xfe, 0x07, 0xe0, ++ 0x04, 0x98, 0x00, 0x2c, 0x02, 0xda, 0xff, 0xf7, 0xe8, 0xfd, 0x01, 0xe0, 0xfd, 0xf7, 0xa3, 0xfd, ++ 0xea, 0x4e, 0x30, 0x68, 0x60, 0x30, 0x01, 0x7b, 0x00, 0x29, 0x25, 0xd0, 0x00, 0x2c, 0x0b, 0xdd, ++ 0x82, 0x7a, 0x05, 0x21, 0x20, 0x20, 0xff, 0xf7, 0x3a, 0xfe, 0x30, 0x68, 0x05, 0x21, 0x60, 0x30, ++ 0xc2, 0x7a, 0x20, 0x20, 0x16, 0xe0, 0x17, 0xe0, 0x82, 0x7a, 0x00, 0x2c, 0x09, 0xda, 0x01, 0x21, ++ 0x02, 0x20, 0xff, 0xf7, 0x2c, 0xfe, 0x30, 0x68, 0x01, 0x21, 0x60, 0x30, 0xc2, 0x7a, 0x02, 0x20, ++ 0x08, 0xe0, 0x03, 0x21, 0x08, 0x20, 0xff, 0xf7, 0x22, 0xfe, 0x30, 0x68, 0x03, 0x21, 0x60, 0x30, ++ 0xc2, 0x7a, 0x08, 0x20, 0xff, 0xf7, 0x25, 0xfe, 0xd4, 0x4e, 0x31, 0x68, 0x08, 0x46, 0x40, 0x30, ++ 0x82, 0x7f, 0x00, 0x2a, 0x77, 0xd1, 0x3b, 0x68, 0xd1, 0x4a, 0x9b, 0x18, 0x2c, 0x22, 0x9a, 0x5e, ++ 0x1f, 0x23, 0x03, 0x92, 0x5a, 0x42, 0x05, 0x9f, 0x01, 0x93, 0x00, 0x92, 0x02, 0x97, 0x20, 0x23, ++ 0x19, 0x22, 0xcb, 0x5e, 0x82, 0x56, 0x28, 0x46, 0x03, 0x99, 0xff, 0xf7, 0x8c, 0xfe, 0x07, 0x46, ++ 0x30, 0x68, 0x6c, 0x21, 0x09, 0x5c, 0x00, 0x29, 0x1c, 0xd0, 0x1f, 0x21, 0x4a, 0x42, 0x00, 0x92, ++ 0x01, 0x91, 0x02, 0x97, 0x20, 0x23, 0x59, 0x22, 0xc3, 0x5e, 0x82, 0x56, 0x28, 0x46, 0x03, 0x99, ++ 0xff, 0xf7, 0xbe, 0xfe, 0x01, 0x46, 0x5a, 0x22, 0x30, 0x68, 0x00, 0x2c, 0x11, 0x54, 0x02, 0xdd, ++ 0x60, 0x30, 0x81, 0x74, 0x06, 0xe0, 0x00, 0x2c, 0x02, 0xda, 0x60, 0x30, 0x01, 0x74, 0x01, 0xe0, ++ 0x60, 0x30, 0x81, 0x73, 0x30, 0x68, 0x01, 0x46, 0x40, 0x31, 0x4d, 0x76, 0x03, 0x9a, 0x02, 0x84, ++ 0x60, 0x30, 0x00, 0x7b, 0x88, 0x77, 0x00, 0x2c, 0x03, 0xdd, 0x38, 0x46, 0xff, 0xf7, 0x85, 0xfd, ++ 0x07, 0xe0, 0x00, 0x2c, 0x38, 0x46, 0x02, 0xda, 0xff, 0xf7, 0x4f, 0xfd, 0x01, 0xe0, 0xfd, 0xf7, ++ 0x0a, 0xfd, 0x30, 0x68, 0x60, 0x30, 0x01, 0x7b, 0x00, 0x29, 0x24, 0xd0, 0x00, 0x2c, 0x0a, 0xdd, ++ 0x82, 0x7a, 0x04, 0x21, 0x10, 0x20, 0xff, 0xf7, 0xba, 0xfd, 0x30, 0x68, 0x04, 0x21, 0x60, 0x30, ++ 0xc2, 0x7a, 0x10, 0x20, 0x15, 0xe0, 0x82, 0x7a, 0x00, 0x2c, 0x09, 0xda, 0x00, 0x21, 0x01, 0x20, ++ 0xff, 0xf7, 0xad, 0xfd, 0x30, 0x68, 0x00, 0x21, 0x60, 0x30, 0xc2, 0x7a, 0x01, 0x20, 0x08, 0xe0, ++ 0x02, 0x21, 0x04, 0x20, 0xff, 0xf7, 0xa3, 0xfd, 0x30, 0x68, 0x02, 0x21, 0x60, 0x30, 0xc2, 0x7a, ++ 0x04, 0x20, 0xff, 0xf7, 0xa6, 0xfd, 0x30, 0x68, 0x40, 0x30, 0x41, 0x7f, 0x00, 0x29, 0x04, 0xd0, ++ 0x81, 0x7f, 0x00, 0x29, 0x01, 0xd0, 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0xc1, 0x75, 0x07, 0xb0, ++ 0xf0, 0xbd, 0xf0, 0xb5, 0x8d, 0x48, 0x07, 0x27, 0x03, 0x68, 0xff, 0x43, 0x60, 0x33, 0x58, 0x7c, ++ 0x59, 0x7b, 0xfa, 0x10, 0x40, 0x1a, 0x40, 0xb2, 0xb8, 0x42, 0x01, 0xdc, 0x01, 0x21, 0x04, 0xe0, ++ 0x08, 0x28, 0x01, 0xdb, 0x11, 0x46, 0x00, 0xe0, 0x00, 0x21, 0x86, 0x4c, 0x20, 0x68, 0x86, 0x4e, ++ 0x80, 0x19, 0x00, 0x89, 0x1e, 0x25, 0x80, 0x06, 0x80, 0x16, 0x40, 0x18, 0xed, 0x43, 0xa8, 0x42, ++ 0x01, 0xda, 0x28, 0x46, 0x02, 0xe0, 0x1f, 0x28, 0x00, 0xdd, 0x1f, 0x20, 0x99, 0x7c, 0x9b, 0x7b, ++ 0xc9, 0x1a, 0x49, 0xb2, 0xb9, 0x42, 0x01, 0xdc, 0x01, 0x22, 0x02, 0xe0, 0x08, 0x29, 0x00, 0xda, ++ 0x00, 0x22, 0x21, 0x68, 0x89, 0x19, 0xc9, 0x88, 0x89, 0x06, 0x89, 0x16, 0x8c, 0x18, 0xac, 0x42, ++ 0x01, 0xda, 0x2c, 0x46, 0x02, 0xe0, 0x1f, 0x2c, 0x00, 0xdd, 0x1f, 0x24, 0xff, 0xf7, 0x1d, 0xfd, ++ 0x20, 0x46, 0xff, 0xf7, 0x02, 0xfd, 0xf0, 0xbd, 0x6c, 0x48, 0x00, 0x22, 0x00, 0x68, 0xc2, 0x83, ++ 0x01, 0x46, 0x02, 0x84, 0x40, 0x31, 0x4a, 0x75, 0xca, 0x75, 0x0a, 0x76, 0x4a, 0x76, 0x8a, 0x76, ++ 0xca, 0x76, 0x4a, 0x77, 0x8a, 0x77, 0x84, 0x21, 0x09, 0x5c, 0x01, 0x29, 0x01, 0xd0, 0x42, 0x84, ++ 0xc2, 0x84, 0x82, 0x84, 0x02, 0x85, 0x70, 0x47, 0x70, 0xb5, 0x60, 0x4c, 0x20, 0x68, 0x40, 0x30, ++ 0x81, 0x7a, 0x03, 0x29, 0x5a, 0xd0, 0x00, 0x25, 0xed, 0x43, 0x04, 0x29, 0x1f, 0xd0, 0x05, 0x29, ++ 0x37, 0xd0, 0x01, 0x20, 0xff, 0xf7, 0x93, 0xfc, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, 0x10, 0x20, ++ 0xc0, 0x43, 0x88, 0x82, 0x57, 0x49, 0x10, 0x20, 0x09, 0x68, 0x55, 0x4a, 0x40, 0x32, 0x89, 0x18, ++ 0x08, 0x80, 0x28, 0x46, 0xff, 0xf7, 0xf9, 0xfc, 0xff, 0xf7, 0xc6, 0xff, 0x09, 0x20, 0xff, 0xf7, ++ 0x22, 0xfd, 0xfd, 0xf7, 0x4c, 0xf9, 0x20, 0x68, 0x04, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfd, 0xf7, ++ 0x8e, 0xf9, 0x00, 0x28, 0x45, 0xd0, 0x28, 0x46, 0xff, 0xf7, 0x28, 0xfe, 0x20, 0x68, 0x40, 0x30, ++ 0xc0, 0x7d, 0x00, 0x28, 0xed, 0xd0, 0x00, 0x20, 0xff, 0xf7, 0xdf, 0xfc, 0xff, 0xf7, 0xac, 0xff, ++ 0x09, 0x20, 0xff, 0xf7, 0x2b, 0xfd, 0xfd, 0xf7, 0x32, 0xf9, 0x20, 0x68, 0x05, 0x21, 0x40, 0x30, ++ 0x81, 0x72, 0xfd, 0xf7, 0x74, 0xf9, 0x00, 0x28, 0x2b, 0xd0, 0x00, 0x20, 0xff, 0xf7, 0x0e, 0xfe, ++ 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xed, 0xd0, 0x00, 0x20, 0xfd, 0xf7, 0x4a, 0xf9, ++ 0x01, 0x20, 0xff, 0xf7, 0xc2, 0xfc, 0xff, 0xf7, 0x8f, 0xff, 0x09, 0x20, 0xfd, 0xf7, 0x31, 0xfd, ++ 0xfd, 0xf7, 0x15, 0xf9, 0x20, 0x68, 0x03, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfd, 0xf7, 0x57, 0xf9, ++ 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x20, 0xff, 0xf7, 0xf1, 0xfd, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, ++ 0x00, 0x28, 0xed, 0xd0, 0xff, 0xf7, 0x35, 0xff, 0x00, 0x20, 0xff, 0xf7, 0x30, 0xfc, 0x00, 0x20, ++ 0x70, 0xbd, 0x02, 0x20, 0x70, 0xbd, 0xf0, 0xb5, 0x26, 0x4a, 0x1e, 0x27, 0xff, 0x43, 0x1f, 0x26, ++ 0x10, 0x68, 0x85, 0xb0, 0x79, 0x11, 0x22, 0x4b, 0xc4, 0x18, 0x30, 0x20, 0x20, 0x5e, 0x1f, 0x28, ++ 0x01, 0xdd, 0x4c, 0x0c, 0x0c, 0xe0, 0x20, 0x24, 0xe0, 0x42, 0x01, 0xda, 0x0c, 0x46, 0x07, 0xe0, ++ 0x12, 0x68, 0x80, 0x02, 0xd2, 0x18, 0x52, 0x8e, 0x92, 0x05, 0x92, 0x0d, 0x10, 0x43, 0x04, 0xb2, ++ 0x16, 0x48, 0x10, 0x23, 0x02, 0x68, 0x10, 0x46, 0x40, 0x30, 0xc3, 0x56, 0x03, 0x93, 0x02, 0x91, ++ 0x00, 0x97, 0x01, 0x96, 0x20, 0x23, 0xd3, 0x5e, 0x18, 0x22, 0x82, 0x56, 0x21, 0x46, 0x03, 0x98, ++ 0xff, 0xf7, 0x19, 0xfd, 0x05, 0x46, 0x0d, 0x48, 0x6c, 0x21, 0x00, 0x68, 0x09, 0x5c, 0x00, 0x29, ++ 0x12, 0xd0, 0x29, 0x01, 0x81, 0x86, 0x00, 0x97, 0x01, 0x96, 0x02, 0x95, 0x20, 0x23, 0x58, 0x22, ++ 0xc3, 0x5e, 0x82, 0x56, 0x21, 0x46, 0x03, 0x98, 0xff, 0xf7, 0x4a, 0xfd, 0x01, 0x46, 0x03, 0x48, ++ 0x00, 0x68, 0x82, 0x8e, 0x89, 0x18, 0x81, 0x86, 0x00, 0x48, 0x07, 0xe0, 0x90, 0x00, 0x00, 0x20, ++ 0x40, 0xa0, 0x01, 0x00, 0x84, 0x00, 0x00, 0x20, 0x80, 0xa2, 0x01, 0x00, 0x00, 0x68, 0x03, 0x9a, ++ 0x01, 0x46, 0x40, 0x31, 0x0a, 0x76, 0x04, 0x84, 0x60, 0x30, 0x00, 0x7b, 0xc8, 0x75, 0x28, 0x46, ++ 0xfd, 0xf7, 0xfc, 0xfa, 0x05, 0xb0, 0xf0, 0xbd, 0xf8, 0xb5, 0xfe, 0x4c, 0x03, 0x25, 0x20, 0x68, ++ 0x2d, 0x07, 0x40, 0x30, 0x80, 0x7a, 0xfc, 0x4e, 0xfc, 0x4f, 0x0c, 0x28, 0x21, 0xd0, 0xff, 0xf7, ++ 0x03, 0xff, 0x20, 0x68, 0x40, 0x30, 0x01, 0x7c, 0x41, 0x76, 0xfd, 0xf7, 0xaa, 0xf8, 0x21, 0x68, ++ 0x40, 0x31, 0x88, 0x76, 0x00, 0x20, 0xfd, 0xf7, 0xe1, 0xfa, 0x00, 0x20, 0xfd, 0xf7, 0xaa, 0xf8, ++ 0xa8, 0x8a, 0xae, 0x82, 0x3a, 0x68, 0x01, 0x21, 0x0d, 0x20, 0x40, 0x03, 0x10, 0x18, 0xc1, 0x80, ++ 0x09, 0x20, 0xff, 0xf7, 0x8f, 0xfc, 0xfd, 0xf7, 0x72, 0xf8, 0x20, 0x68, 0x0c, 0x21, 0x40, 0x30, ++ 0x81, 0x72, 0xfd, 0xf7, 0xb4, 0xf8, 0x00, 0x28, 0x07, 0xd0, 0xff, 0xf7, 0x6c, 0xff, 0x21, 0x68, ++ 0x40, 0x31, 0xc8, 0x7d, 0x00, 0x28, 0x02, 0xd0, 0x04, 0xe0, 0x02, 0x20, 0xf8, 0xbd, 0x48, 0x7d, ++ 0x20, 0x28, 0xe8, 0xd3, 0xa8, 0x8a, 0xae, 0x82, 0x3b, 0x68, 0x00, 0x22, 0x0d, 0x20, 0x40, 0x03, ++ 0x18, 0x18, 0xc2, 0x80, 0x19, 0x20, 0x08, 0x56, 0xfd, 0xf7, 0xb0, 0xfa, 0x21, 0x68, 0x5a, 0x20, ++ 0x08, 0x56, 0xfd, 0xf7, 0x77, 0xf8, 0x00, 0x20, 0xf8, 0xbd, 0x70, 0xb5, 0x0d, 0x46, 0x03, 0x00, ++ 0x03, 0xf0, 0x4e, 0xfb, 0x06, 0x0e, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x08, 0x24, 0x08, 0xe0, ++ 0x10, 0x24, 0x06, 0xe0, 0x20, 0x24, 0x04, 0xe0, 0x40, 0x24, 0x02, 0xe0, 0x80, 0x24, 0x00, 0xe0, ++ 0x00, 0x24, 0xfd, 0xf7, 0xd3, 0xf9, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x1f, 0x21, 0xc9, 0x43, ++ 0x81, 0x82, 0xca, 0x49, 0xea, 0x06, 0x0b, 0x68, 0xd2, 0x0e, 0x0d, 0x25, 0x6d, 0x03, 0x5b, 0x19, ++ 0x5a, 0x85, 0x82, 0x8a, 0xc6, 0x4a, 0x82, 0x82, 0x0d, 0x68, 0x20, 0x23, 0xc5, 0x4a, 0xad, 0x18, ++ 0x2b, 0x84, 0x83, 0x8a, 0x00, 0x23, 0x83, 0x82, 0xc3, 0x4b, 0x0d, 0x68, 0xad, 0x18, 0x6b, 0x84, ++ 0x83, 0x8a, 0xff, 0x23, 0x83, 0x82, 0x09, 0x68, 0x20, 0x02, 0x89, 0x18, 0x88, 0x84, 0x70, 0xbd, ++ 0xf0, 0xb5, 0x03, 0x22, 0xcf, 0x05, 0x12, 0x07, 0xff, 0x0d, 0x96, 0x13, 0xb7, 0x4c, 0xb9, 0x4d, ++ 0x03, 0x00, 0x03, 0xf0, 0x0d, 0xfb, 0x06, 0x44, 0x04, 0x45, 0xb1, 0xb6, 0xbb, 0x44, 0x46, 0x29, ++ 0x01, 0xdd, 0x46, 0x21, 0x01, 0xe0, 0x3f, 0x29, 0x02, 0xdd, 0x08, 0x46, 0x3f, 0x38, 0x00, 0xe0, ++ 0x00, 0x20, 0x93, 0x8a, 0x40, 0xb2, 0x03, 0x23, 0x9b, 0x03, 0x93, 0x82, 0xc3, 0x05, 0x01, 0x26, ++ 0xdb, 0x0d, 0xb6, 0x02, 0x27, 0x68, 0x9e, 0x19, 0x7f, 0x19, 0xfe, 0x82, 0x96, 0x8a, 0xab, 0x4e, ++ 0x96, 0x82, 0x27, 0x68, 0x76, 0x1c, 0x7f, 0x19, 0xfe, 0x82, 0x97, 0x8a, 0x03, 0x27, 0xbf, 0x03, ++ 0x97, 0x82, 0x7f, 0x11, 0xdb, 0x19, 0x27, 0x68, 0x7f, 0x19, 0xfb, 0x82, 0x93, 0x8a, 0x73, 0x1e, ++ 0x93, 0x82, 0x23, 0x68, 0x5b, 0x19, 0xde, 0x82, 0x93, 0x8a, 0x03, 0x23, 0x9b, 0x03, 0x93, 0x82, ++ 0x08, 0x1a, 0xc0, 0x05, 0x21, 0x68, 0xc0, 0x0d, 0xff, 0x30, 0x49, 0x19, 0xff, 0x30, 0x02, 0x30, ++ 0xc8, 0x82, 0x90, 0x8a, 0x70, 0x1e, 0x90, 0x82, 0x20, 0x68, 0x40, 0x19, 0xc6, 0x82, 0xf0, 0xbd, ++ 0x0b, 0x46, 0x1f, 0x33, 0x48, 0x42, 0x3e, 0x2b, 0x06, 0xd9, 0x00, 0x29, 0x01, 0xdb, 0x0b, 0x46, ++ 0x00, 0xe0, 0x03, 0x46, 0x1f, 0x3b, 0x00, 0xe0, 0x00, 0x23, 0x97, 0x8a, 0x5b, 0xb2, 0x03, 0x26, ++ 0xb6, 0x03, 0x96, 0x82, 0xde, 0x05, 0xf6, 0x0d, 0x05, 0x27, 0x7f, 0x02, 0x87, 0x4c, 0xb4, 0x46, ++ 0xf7, 0x19, 0x26, 0x68, 0x76, 0x19, 0xf7, 0x82, 0x97, 0x8a, 0x88, 0x4f, 0x97, 0x82, 0x26, 0x68, ++ 0x7f, 0x1c, 0x76, 0x19, 0xf7, 0x82, 0x97, 0x8a, 0x03, 0x27, 0xbf, 0x03, 0x97, 0x82, 0x66, 0x46, ++ 0x3f, 0x11, 0xf6, 0x19, 0x27, 0x68, 0x7f, 0x19, 0xfe, 0x82, 0x97, 0x8a, 0x7f, 0x4f, 0x97, 0x82, ++ 0x24, 0x68, 0x7f, 0x1c, 0x64, 0x19, 0xe7, 0x82, 0x94, 0x8a, 0x03, 0x24, 0xa4, 0x03, 0x94, 0x82, ++ 0x00, 0x29, 0x00, 0xdb, 0x08, 0x46, 0xc0, 0x1a, 0xc0, 0x05, 0x01, 0x23, 0xc0, 0x0d, 0xdb, 0x02, ++ 0xc3, 0x18, 0x72, 0x48, 0x04, 0x68, 0x64, 0x19, 0xe3, 0x82, 0x93, 0x8a, 0x73, 0x4b, 0x93, 0x82, ++ 0x07, 0x68, 0x5c, 0x1c, 0x7f, 0x19, 0xfc, 0x82, 0x96, 0x8a, 0x03, 0x26, 0xb6, 0x03, 0x96, 0x82, ++ 0x05, 0x26, 0xc9, 0x0f, 0xb6, 0x02, 0x07, 0x68, 0x8e, 0x19, 0x7f, 0x19, 0xfe, 0x82, 0x96, 0x8a, ++ 0x93, 0x82, 0x06, 0x68, 0x76, 0x19, 0xf4, 0x82, 0x96, 0x8a, 0x03, 0x26, 0xb6, 0x03, 0x96, 0x82, ++ 0x0b, 0x26, 0x76, 0x02, 0x89, 0x19, 0x06, 0x68, 0x76, 0x19, 0xf1, 0x82, 0x91, 0x8a, 0x93, 0x82, ++ 0x00, 0x68, 0x40, 0x19, 0xc4, 0x82, 0xf0, 0xbd, 0x90, 0x8a, 0x96, 0x82, 0x07, 0x20, 0x40, 0x02, ++ 0x08, 0xe0, 0x90, 0x8a, 0x96, 0x82, 0x01, 0x20, 0x00, 0x03, 0x03, 0xe0, 0x90, 0x8a, 0x96, 0x82, ++ 0x09, 0x20, 0x40, 0x02, 0x21, 0x68, 0x38, 0x18, 0x49, 0x19, 0xc8, 0x82, 0x90, 0x8a, 0x57, 0x48, ++ 0x90, 0x82, 0x21, 0x68, 0x40, 0x1c, 0x49, 0x19, 0xc8, 0x82, 0xf0, 0xbd, 0x0f, 0xb4, 0xfe, 0xb5, ++ 0x08, 0xaf, 0xbc, 0x7b, 0xfb, 0x7b, 0x3d, 0x7c, 0x7f, 0x7c, 0x26, 0x46, 0x00, 0x2a, 0x01, 0xd1, ++ 0x1c, 0x46, 0x33, 0x46, 0x01, 0x29, 0x02, 0xd0, 0x49, 0x1c, 0x0c, 0xd0, 0x18, 0xe0, 0x07, 0x2c, ++ 0x01, 0xd2, 0x64, 0x1c, 0x0a, 0xe0, 0x00, 0x2b, 0x01, 0xd0, 0x5b, 0x1e, 0xdb, 0xb2, 0xbd, 0x42, ++ 0x0e, 0xd2, 0x6d, 0x1c, 0x0b, 0xe0, 0x00, 0x2c, 0x02, 0xd0, 0x64, 0x1e, 0xe4, 0xb2, 0x07, 0xe0, ++ 0x07, 0x2b, 0x01, 0xd2, 0x5b, 0x1c, 0xdb, 0xb2, 0x00, 0x2d, 0x01, 0xd0, 0x6d, 0x1e, 0xed, 0xb2, ++ 0x69, 0x46, 0x0d, 0x71, 0x00, 0x2a, 0x11, 0xd0, 0x8c, 0x70, 0xcb, 0x70, 0x08, 0xaa, 0x11, 0x7b, ++ 0x6a, 0x46, 0x11, 0x70, 0x08, 0xaa, 0x51, 0x7b, 0x6a, 0x46, 0x51, 0x70, 0x06, 0x22, 0x69, 0x46, ++ 0x03, 0xf0, 0x69, 0xf9, 0xfe, 0xbc, 0x08, 0xbc, 0x04, 0xb0, 0x18, 0x47, 0xcc, 0x70, 0x8b, 0x70, ++ 0xec, 0xe7, 0xfe, 0xb5, 0xd3, 0x1a, 0x2d, 0x4c, 0x2e, 0x4d, 0x5e, 0xb2, 0x01, 0x28, 0x05, 0xd0, ++ 0x02, 0x28, 0x7c, 0xd0, 0x11, 0x46, 0xff, 0xf7, 0xdb, 0xfe, 0xfe, 0xbd, 0x20, 0x68, 0x40, 0x19, ++ 0xc0, 0x8e, 0x6a, 0x46, 0x80, 0x04, 0x40, 0x0f, 0x90, 0x71, 0x20, 0x68, 0x40, 0x19, 0xc0, 0x8e, ++ 0x40, 0x05, 0x40, 0x0f, 0xd0, 0x71, 0x20, 0x68, 0x40, 0x19, 0xc0, 0x8e, 0x80, 0x06, 0x80, 0x0e, ++ 0x10, 0x72, 0x3f, 0x20, 0x50, 0x72, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x29, 0x1d, 0xd1, 0x14, 0xe0, ++ 0x10, 0x89, 0x10, 0x80, 0x01, 0x22, 0x31, 0x46, 0x01, 0xa8, 0x01, 0x9b, 0xff, 0xf7, 0x8e, 0xff, ++ 0x14, 0x48, 0x00, 0x68, 0x80, 0x30, 0x01, 0x7a, 0xc9, 0x06, 0x02, 0xd5, 0x80, 0x7b, 0x80, 0x06, ++ 0x0b, 0xd5, 0x69, 0x46, 0x88, 0x79, 0xc8, 0x71, 0x07, 0xe0, 0x10, 0x89, 0x10, 0x80, 0x00, 0x22, ++ 0x31, 0x46, 0x01, 0xa8, 0x01, 0x9b, 0xff, 0xf7, 0x79, 0xff, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x81, 0x13, 0x81, 0x82, 0x6b, 0x46, 0xda, 0x79, 0x01, 0x23, 0x9b, 0x02, 0xd2, 0x18, 0x23, 0x68, ++ 0x5b, 0x19, 0xda, 0x82, 0x82, 0x8a, 0x09, 0x4a, 0x82, 0x82, 0x23, 0x68, 0x56, 0x1c, 0x5b, 0x19, ++ 0xde, 0x82, 0x0d, 0xe0, 0x90, 0x00, 0x00, 0x20, 0xfe, 0xff, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0xd3, 0x8b, 0x00, 0x00, 0x40, 0xa0, 0x01, 0x00, 0x20, 0x20, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, ++ 0x83, 0x8a, 0x81, 0x82, 0x6b, 0x46, 0x9b, 0x79, 0xc7, 0x14, 0xdb, 0x19, 0x27, 0x68, 0x7f, 0x19, ++ 0xfb, 0x82, 0x83, 0x8a, 0x82, 0x82, 0x23, 0x68, 0x5b, 0x19, 0xde, 0x82, 0x83, 0x8a, 0x81, 0x82, ++ 0x6b, 0x46, 0x19, 0x7a, 0x23, 0x68, 0xff, 0x31, 0x5b, 0x19, 0xff, 0x31, 0x02, 0x31, 0xd9, 0x82, ++ 0x81, 0x8a, 0x82, 0x82, 0x20, 0x68, 0x40, 0x19, 0xc6, 0x82, 0xfe, 0xbd, 0xff, 0xe7, 0x22, 0x68, ++ 0xfe, 0x48, 0x12, 0x18, 0x12, 0x8f, 0x6d, 0x46, 0x52, 0x06, 0xd2, 0x0f, 0x2a, 0x71, 0x22, 0x68, ++ 0x12, 0x18, 0x12, 0x8f, 0x92, 0x06, 0xd2, 0x0f, 0x6a, 0x71, 0x22, 0x68, 0x12, 0x18, 0x12, 0x8f, ++ 0x92, 0x04, 0x53, 0x0f, 0xab, 0x71, 0x22, 0x68, 0x12, 0x18, 0x12, 0x8f, 0x52, 0x05, 0x52, 0x0f, ++ 0xea, 0x71, 0x25, 0x68, 0x28, 0x18, 0x00, 0x8f, 0x6d, 0x46, 0xc0, 0x06, 0xc0, 0x0e, 0x28, 0x72, ++ 0x1f, 0x27, 0x6f, 0x72, 0x00, 0x25, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x29, 0x44, 0xd1, 0x28, 0xe0, ++ 0xc3, 0x42, 0x04, 0xd1, 0x70, 0x1c, 0x02, 0xd1, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x6a, 0x46, ++ 0x10, 0x79, 0x40, 0x00, 0x40, 0x42, 0x40, 0x1c, 0x70, 0x43, 0x41, 0xb2, 0x10, 0x89, 0x10, 0x80, ++ 0x01, 0x22, 0x01, 0xa8, 0x01, 0x9b, 0xff, 0xf7, 0xf9, 0xfe, 0x6a, 0x46, 0x91, 0x79, 0x10, 0x7a, ++ 0xc1, 0x42, 0x00, 0xd1, 0x15, 0x71, 0xde, 0x48, 0x00, 0x68, 0x80, 0x30, 0x02, 0x7a, 0xd2, 0x06, ++ 0x02, 0xd5, 0x80, 0x7b, 0x40, 0x06, 0x1f, 0xd5, 0x6a, 0x46, 0xd1, 0x71, 0x10, 0x79, 0x50, 0x71, ++ 0x1a, 0xe0, 0xc2, 0x42, 0x04, 0xd1, 0x70, 0x1c, 0x02, 0xd1, 0x01, 0x20, 0x69, 0x46, 0x48, 0x71, ++ 0x6a, 0x46, 0x50, 0x79, 0x40, 0x00, 0x40, 0x42, 0x40, 0x1c, 0x70, 0x43, 0x41, 0xb2, 0x10, 0x89, ++ 0x10, 0x80, 0x00, 0x22, 0x01, 0xa8, 0x01, 0x9b, 0xff, 0xf7, 0xd0, 0xfe, 0x6a, 0x46, 0xd0, 0x79, ++ 0x11, 0x7a, 0xc8, 0x42, 0x00, 0xd1, 0x55, 0x71, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x82, 0x13, ++ 0x82, 0x82, 0x6e, 0x46, 0xf1, 0x79, 0x05, 0x23, 0x5b, 0x02, 0x25, 0x68, 0xcb, 0x18, 0xc3, 0x49, ++ 0x6d, 0x18, 0xeb, 0x82, 0x83, 0x8a, 0xc3, 0x4b, 0x83, 0x82, 0x26, 0x68, 0x5d, 0x1c, 0x76, 0x18, ++ 0xf5, 0x82, 0x86, 0x8a, 0x82, 0x82, 0x6e, 0x46, 0xb6, 0x79, 0x87, 0x14, 0xf6, 0x19, 0x27, 0x68, ++ 0x7f, 0x18, 0xfe, 0x82, 0x86, 0x8a, 0x83, 0x82, 0x26, 0x68, 0x76, 0x18, 0xf5, 0x82, 0x86, 0x8a, ++ 0x82, 0x82, 0x6e, 0x46, 0x36, 0x7a, 0x2f, 0x11, 0xf6, 0x19, 0x27, 0x68, 0x7f, 0x18, 0xfe, 0x82, ++ 0x86, 0x8a, 0x83, 0x82, 0x26, 0x68, 0x76, 0x18, 0xf5, 0x82, 0x86, 0x8a, 0x82, 0x82, 0x6e, 0x46, ++ 0x36, 0x79, 0x05, 0x27, 0xbf, 0x02, 0xf6, 0x19, 0x27, 0x68, 0x7f, 0x18, 0xfe, 0x82, 0x86, 0x8a, ++ 0x83, 0x82, 0x26, 0x68, 0x76, 0x18, 0xf5, 0x82, 0x86, 0x8a, 0x82, 0x82, 0x6e, 0x46, 0x72, 0x79, ++ 0x0b, 0x26, 0x76, 0x02, 0x92, 0x19, 0x26, 0x68, 0x76, 0x18, 0xf2, 0x82, 0x82, 0x8a, 0x83, 0x82, ++ 0x20, 0x68, 0x40, 0x18, 0xc5, 0x82, 0x40, 0xe7, 0xa3, 0x48, 0x00, 0x68, 0x9f, 0x49, 0x40, 0x18, ++ 0x80, 0x8e, 0x80, 0x06, 0x80, 0x0e, 0x70, 0x47, 0xf3, 0xb5, 0x9d, 0x48, 0x87, 0xb0, 0x00, 0x68, ++ 0x05, 0x90, 0x40, 0x30, 0x04, 0x90, 0xc0, 0x7c, 0x98, 0x4e, 0x01, 0x28, 0x1a, 0xd0, 0x05, 0x98, ++ 0x80, 0x30, 0x01, 0x7a, 0xc9, 0x06, 0x1b, 0xd5, 0x07, 0x99, 0x01, 0x29, 0x02, 0xd0, 0x02, 0x29, ++ 0x03, 0xd0, 0x15, 0xe0, 0x80, 0x7b, 0x80, 0x06, 0x01, 0xe0, 0x80, 0x7b, 0x40, 0x06, 0x00, 0x28, ++ 0x0e, 0xdb, 0x08, 0x98, 0x00, 0x28, 0x05, 0xd0, 0x8f, 0x48, 0x00, 0x68, 0x81, 0x19, 0x2c, 0x20, ++ 0x08, 0x5e, 0x0a, 0xe0, 0x8c, 0x48, 0x00, 0x68, 0x81, 0x19, 0x28, 0x20, 0x08, 0x5e, 0x04, 0xe0, ++ 0x89, 0x48, 0x00, 0x68, 0x81, 0x19, 0x30, 0x20, 0x08, 0x5e, 0x07, 0x99, 0x0e, 0x22, 0xd2, 0x43, ++ 0x0b, 0x00, 0x03, 0xf0, 0x7d, 0xf8, 0x06, 0x6c, 0x04, 0x1b, 0x52, 0x5c, 0x63, 0x6c, 0x08, 0x99, ++ 0x81, 0x4a, 0x00, 0x29, 0x11, 0x68, 0x0d, 0xd0, 0x89, 0x19, 0xc9, 0x8e, 0x09, 0x0a, 0x49, 0x07, ++ 0x12, 0x68, 0x49, 0x0f, 0x92, 0x19, 0xd2, 0x8e, 0x00, 0x24, 0x92, 0x06, 0x92, 0x0e, 0x8f, 0x18, ++ 0x46, 0x25, 0x55, 0xe0, 0x89, 0x19, 0xc9, 0x8e, 0xc9, 0x0a, 0xf0, 0xe7, 0x08, 0x99, 0x00, 0x29, ++ 0x75, 0x49, 0x0a, 0x68, 0x13, 0xd0, 0x92, 0x19, 0x12, 0x8f, 0x52, 0x09, 0xd2, 0x07, 0xd2, 0x0f, ++ 0x0a, 0x68, 0x1b, 0xd0, 0x92, 0x19, 0x12, 0x8f, 0x12, 0x0a, 0x52, 0x07, 0x09, 0x68, 0x52, 0x0f, ++ 0x89, 0x19, 0x09, 0x8f, 0xc9, 0x06, 0xc9, 0x0e, 0x51, 0x18, 0x4f, 0x42, 0x19, 0xe0, 0x92, 0x19, ++ 0x12, 0x8f, 0x92, 0x09, 0xd2, 0x07, 0xd2, 0x0f, 0x0a, 0x68, 0x03, 0xd0, 0x92, 0x19, 0x12, 0x8f, ++ 0xd2, 0x0a, 0xea, 0xe7, 0x92, 0x19, 0x12, 0x8f, 0xd2, 0x0a, 0x02, 0xe0, 0x92, 0x19, 0x12, 0x8f, ++ 0x12, 0x0a, 0x52, 0x07, 0x09, 0x68, 0x52, 0x0f, 0x89, 0x19, 0x09, 0x8f, 0xc9, 0x06, 0xc9, 0x0e, ++ 0x57, 0x18, 0x25, 0x24, 0xe4, 0x43, 0x26, 0x25, 0x1a, 0xe0, 0x5b, 0x49, 0x09, 0x68, 0x89, 0x19, ++ 0x49, 0x8f, 0x1e, 0x24, 0x89, 0x06, 0x8f, 0x16, 0xe4, 0x43, 0x1f, 0x25, 0x10, 0xe0, 0x56, 0x49, ++ 0x09, 0x68, 0x89, 0x19, 0x49, 0x8f, 0x49, 0x05, 0xcf, 0x16, 0x05, 0xe0, 0x52, 0x49, 0x09, 0x68, ++ 0x8b, 0x19, 0x3a, 0x21, 0x59, 0x5e, 0xcf, 0x12, 0x14, 0x46, 0x0f, 0x25, 0x00, 0xe0, 0x00, 0x27, ++ 0x04, 0x99, 0x00, 0x2f, 0x4f, 0x76, 0x02, 0xd0, 0x03, 0xdb, 0x01, 0x21, 0x03, 0xe0, 0x00, 0x21, ++ 0x01, 0xe0, 0x00, 0x21, 0xc9, 0x43, 0x40, 0x1a, 0x00, 0xb2, 0x03, 0x90, 0x04, 0x98, 0x40, 0x7d, ++ 0x00, 0x28, 0x15, 0xd0, 0x00, 0x20, 0xc0, 0x43, 0x00, 0x94, 0x02, 0x90, 0x05, 0x98, 0x01, 0x95, ++ 0x20, 0x23, 0xc3, 0x5e, 0x04, 0x98, 0x18, 0x22, 0x82, 0x56, 0x38, 0x46, 0x03, 0x99, 0xff, 0xf7, ++ 0x32, 0xf9, 0x07, 0x46, 0x3a, 0x48, 0x6c, 0x21, 0x00, 0x68, 0x09, 0x5c, 0x40, 0x30, 0xc1, 0x75, ++ 0x07, 0x98, 0x01, 0x28, 0x0b, 0xd1, 0xa7, 0x42, 0x04, 0xd1, 0x03, 0x99, 0x48, 0x1c, 0x01, 0xda, ++ 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x32, 0x48, 0x00, 0x68, 0x80, 0x30, 0x41, 0x71, 0x30, 0x48, ++ 0x00, 0x68, 0x40, 0x30, 0x81, 0x7d, 0x01, 0x29, 0x02, 0xd0, 0x00, 0x7d, 0x03, 0x28, 0x06, 0xd1, ++ 0x07, 0x98, 0x01, 0x28, 0x04, 0xd0, 0x02, 0x28, 0x05, 0xd0, 0x03, 0x28, 0x03, 0xd0, 0x96, 0xe0, ++ 0xaf, 0x42, 0x04, 0xd0, 0x93, 0xe0, 0xaf, 0x42, 0x01, 0xd0, 0xa7, 0x42, 0x7e, 0xd1, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0x01, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x23, 0x4c, 0x01, 0x20, 0x21, 0x68, ++ 0x0d, 0x22, 0x52, 0x03, 0x89, 0x18, 0x48, 0x86, 0x01, 0x46, 0x1c, 0x20, 0x02, 0xf0, 0xda, 0xfe, ++ 0x08, 0x98, 0x00, 0x28, 0x20, 0x68, 0x1e, 0xd0, 0x80, 0x19, 0xc0, 0x8e, 0x21, 0x68, 0x40, 0x05, ++ 0x40, 0x0f, 0x89, 0x19, 0xc9, 0x8e, 0x89, 0x06, 0x89, 0x0e, 0x41, 0x18, 0x20, 0x68, 0x80, 0x19, ++ 0x00, 0x8f, 0x40, 0x09, 0xc0, 0x07, 0xc0, 0x0f, 0x20, 0x68, 0x2f, 0xd0, 0x80, 0x19, 0x00, 0x8f, ++ 0x00, 0x0a, 0x40, 0x07, 0x22, 0x68, 0x40, 0x0f, 0x92, 0x19, 0x12, 0x8f, 0xd2, 0x06, 0xd2, 0x0e, ++ 0x80, 0x18, 0x40, 0x42, 0x2d, 0xe0, 0x80, 0x19, 0xc0, 0x8e, 0x21, 0x68, 0x80, 0x04, 0x40, 0x0f, ++ 0x89, 0x19, 0xc9, 0x8e, 0x89, 0x06, 0x89, 0x0e, 0x41, 0x18, 0x20, 0x68, 0x80, 0x19, 0x00, 0x8f, ++ 0x80, 0x09, 0xc0, 0x07, 0xc0, 0x0f, 0x20, 0x68, 0x0c, 0xd0, 0x07, 0xe0, 0x40, 0xa0, 0x01, 0x00, ++ 0x90, 0x00, 0x00, 0x20, 0xff, 0x7f, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, 0x80, 0x19, 0x00, 0x8f, ++ 0xc0, 0x0a, 0xd6, 0xe7, 0x80, 0x19, 0x00, 0x8f, 0xc0, 0x0a, 0x02, 0xe0, 0x80, 0x19, 0x00, 0x8f, ++ 0x00, 0x0a, 0x40, 0x07, 0x22, 0x68, 0x40, 0x0f, 0x92, 0x19, 0x12, 0x8f, 0xd2, 0x06, 0xd2, 0x0e, ++ 0x80, 0x18, 0x00, 0x06, 0x00, 0x0c, 0x01, 0x43, 0x20, 0x68, 0x80, 0x19, 0x40, 0x8f, 0x03, 0x25, ++ 0x80, 0x06, 0x80, 0x16, 0x00, 0x06, 0x00, 0x0a, 0x01, 0x43, 0x01, 0x91, 0x00, 0x23, 0x2a, 0x46, ++ 0x00, 0x95, 0x12, 0x21, 0x01, 0x20, 0x02, 0xf0, 0xff, 0xfd, 0xff, 0xf7, 0x8d, 0xfe, 0x21, 0x68, ++ 0x00, 0x02, 0xfe, 0x4a, 0x89, 0x18, 0x49, 0x88, 0x09, 0x07, 0x00, 0xe0, 0x0f, 0xe0, 0x09, 0x0f, ++ 0x08, 0x43, 0xfb, 0x49, 0x00, 0x23, 0x09, 0x68, 0x03, 0x22, 0x40, 0x31, 0xc9, 0x7b, 0x00, 0x95, ++ 0x09, 0x04, 0x08, 0x43, 0x01, 0x90, 0x13, 0x21, 0x01, 0x20, 0x02, 0xf0, 0xe5, 0xfd, 0xf4, 0x4c, ++ 0x20, 0x68, 0x40, 0x30, 0xc1, 0x7c, 0x01, 0x29, 0x11, 0xd0, 0x19, 0x23, 0xc3, 0x56, 0x3a, 0x46, ++ 0x08, 0x99, 0x07, 0x98, 0xff, 0xf7, 0x25, 0xfd, 0x20, 0x68, 0x03, 0x99, 0x01, 0x84, 0x40, 0x30, ++ 0x41, 0x7e, 0x01, 0x76, 0x41, 0x7d, 0x49, 0x1c, 0x41, 0x75, 0x09, 0xb0, 0xf0, 0xbd, 0x39, 0x46, ++ 0x07, 0x98, 0xff, 0xf7, 0xfd, 0xfb, 0xef, 0xe7, 0x10, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, ++ 0x8a, 0x13, 0x8a, 0x82, 0xc0, 0x05, 0x17, 0x22, 0xc0, 0x0d, 0x52, 0x02, 0x83, 0x18, 0xe1, 0x4a, ++ 0x14, 0x68, 0xde, 0x48, 0x40, 0x38, 0x24, 0x18, 0xe3, 0x82, 0x8b, 0x8a, 0xde, 0x4b, 0x8b, 0x82, ++ 0x12, 0x68, 0x59, 0x1c, 0x10, 0x18, 0xc1, 0x82, 0x10, 0xbd, 0xfe, 0xb5, 0xd8, 0x48, 0xd7, 0x4f, ++ 0x01, 0x68, 0x3e, 0x23, 0x08, 0x46, 0x40, 0x30, 0xc4, 0x7c, 0xdb, 0x43, 0x3f, 0x22, 0x01, 0x25, ++ 0x40, 0x3f, 0xd4, 0x4e, 0x00, 0x2c, 0x01, 0xd0, 0x01, 0x2c, 0x21, 0xd0, 0x34, 0x68, 0xe7, 0x19, ++ 0x30, 0x24, 0x3c, 0x5f, 0x36, 0x68, 0xd1, 0x4f, 0xf6, 0x19, 0xf6, 0x89, 0x02, 0x95, 0x00, 0x93, ++ 0x01, 0x92, 0x76, 0x06, 0x20, 0x23, 0x18, 0x22, 0x77, 0x16, 0xcb, 0x5e, 0x82, 0x56, 0xc8, 0x4d, ++ 0x21, 0x46, 0x38, 0x46, 0xff, 0xf7, 0x17, 0xf8, 0x06, 0x46, 0x28, 0x68, 0x01, 0x46, 0x40, 0x31, ++ 0x0f, 0x76, 0x04, 0x84, 0x60, 0x30, 0x02, 0x7b, 0xca, 0x75, 0x01, 0x2a, 0x05, 0xd0, 0x10, 0xe0, ++ 0x34, 0x68, 0xe7, 0x19, 0x2c, 0x24, 0x3c, 0x5f, 0xdc, 0xe7, 0x82, 0x7a, 0x06, 0x21, 0x40, 0x20, ++ 0xfe, 0xf7, 0x75, 0xff, 0x28, 0x68, 0x06, 0x21, 0x60, 0x30, 0xc2, 0x7a, 0x40, 0x20, 0xfe, 0xf7, ++ 0x78, 0xff, 0x30, 0x46, 0xff, 0xf7, 0xa0, 0xff, 0x3e, 0x36, 0x28, 0x68, 0x7c, 0x2e, 0x04, 0xd9, ++ 0x40, 0x30, 0xc1, 0x79, 0x02, 0x22, 0x11, 0x43, 0x03, 0xe0, 0x40, 0x30, 0xc1, 0x79, 0xfd, 0x22, ++ 0x11, 0x40, 0xc1, 0x71, 0x29, 0xe5, 0x10, 0xb5, 0xad, 0x4c, 0x4a, 0x21, 0x20, 0x68, 0x09, 0x5c, ++ 0x0a, 0x29, 0x16, 0xd0, 0x80, 0x30, 0x40, 0x7b, 0x80, 0x07, 0x1d, 0xd4, 0x00, 0x20, 0xff, 0xf7, ++ 0x83, 0xff, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7c, 0x01, 0x28, 0x15, 0xd8, 0xff, 0xf7, 0xfc, 0xf9, ++ 0x10, 0x20, 0xfe, 0xf7, 0x58, 0xff, 0xfc, 0xf7, 0x82, 0xfb, 0x20, 0x68, 0x0a, 0x21, 0x40, 0x30, ++ 0x81, 0x72, 0xfc, 0xf7, 0xc4, 0xfb, 0x00, 0x28, 0x08, 0xd0, 0xff, 0xf7, 0x86, 0xff, 0x20, 0x68, ++ 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xee, 0xd0, 0x00, 0x20, 0x10, 0xbd, 0x02, 0x20, 0x10, 0xbd, ++ 0x10, 0xb5, 0x97, 0x4c, 0x20, 0x68, 0x01, 0x46, 0x40, 0x30, 0x82, 0x7a, 0x0e, 0x2a, 0x11, 0xd0, ++ 0x80, 0x31, 0x49, 0x7b, 0x89, 0x07, 0x18, 0xd4, 0xc0, 0x7c, 0x01, 0x28, 0x15, 0xd8, 0xff, 0xf7, ++ 0xd3, 0xf9, 0x10, 0x20, 0xfe, 0xf7, 0x2f, 0xff, 0xfc, 0xf7, 0x59, 0xfb, 0x20, 0x68, 0x0e, 0x21, ++ 0x40, 0x30, 0x81, 0x72, 0xfc, 0xf7, 0x9b, 0xfb, 0x00, 0x28, 0x0c, 0xd0, 0xff, 0xf7, 0x5d, 0xff, ++ 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xee, 0xd0, 0x20, 0x68, 0x2f, 0x21, 0x40, 0x30, ++ 0x81, 0x72, 0x00, 0x20, 0x10, 0xbd, 0x02, 0x20, 0x10, 0xbd, 0x10, 0xb5, 0x1f, 0x28, 0x01, 0xd9, ++ 0x1f, 0x20, 0x03, 0xe0, 0x41, 0xb2, 0x00, 0x29, 0x00, 0xda, 0x00, 0x20, 0xfe, 0xf7, 0x1c, 0xfc, ++ 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfc, 0xf7, 0xd1, 0xfc, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, ++ 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0x77, 0x48, 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, ++ 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0x75, 0x4a, 0x8a, 0x82, 0x75, 0x4b, 0x04, 0x68, ++ 0x6e, 0x4a, 0x40, 0x3a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0x00, 0x23, 0x8b, 0x82, 0x72, 0x4b, ++ 0x04, 0x68, 0xa4, 0x18, 0x63, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, 0x01, 0x21, 0x00, 0x68, ++ 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfc, 0xf7, 0xa6, 0xfc, ++ 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0x61, 0x48, 0xe2, 0x06, ++ 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0x63, 0x4a, ++ 0x8a, 0x82, 0x09, 0x23, 0x04, 0x68, 0x9b, 0x02, 0x58, 0x4a, 0x40, 0x3a, 0xa4, 0x18, 0x23, 0x84, ++ 0x8b, 0x8a, 0x00, 0x23, 0x8b, 0x82, 0x5c, 0x4b, 0x04, 0x68, 0x40, 0x33, 0xa4, 0x18, 0x63, 0x84, ++ 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, 0x07, 0x21, 0x00, 0x68, 0xc9, 0x02, 0x80, 0x18, 0x81, 0x84, ++ 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0xfc, 0xf7, 0x79, 0xfc, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, ++ 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0x4b, 0x48, 0xe3, 0x06, 0x04, 0x68, 0xdb, 0x0e, 0x0d, 0x22, ++ 0x52, 0x03, 0xa4, 0x18, 0x63, 0x85, 0x8b, 0x8a, 0x47, 0x4b, 0x8b, 0x82, 0x04, 0x68, 0x5b, 0x1c, ++ 0x42, 0x4d, 0x40, 0x3d, 0x64, 0x19, 0x23, 0x84, 0x8b, 0x8a, 0x80, 0x23, 0xdb, 0x43, 0x8b, 0x82, ++ 0x00, 0x68, 0x80, 0x21, 0x80, 0x18, 0x01, 0x84, 0x70, 0xbd, 0x10, 0xb5, 0x3d, 0x4a, 0x10, 0x68, ++ 0x3a, 0x4b, 0x40, 0x3b, 0xc0, 0x18, 0x00, 0x8f, 0x11, 0x68, 0x80, 0x04, 0x40, 0x0f, 0xc9, 0x18, ++ 0x09, 0x8f, 0xc9, 0x06, 0xc9, 0x0e, 0x41, 0x18, 0x10, 0x68, 0xc0, 0x18, 0x00, 0x8f, 0x80, 0x09, ++ 0xc0, 0x07, 0xc0, 0x0f, 0x00, 0xd0, 0x49, 0x42, 0x10, 0x68, 0xc0, 0x18, 0x00, 0x8f, 0x14, 0x68, ++ 0x40, 0x05, 0x40, 0x0f, 0xe4, 0x18, 0x24, 0x8f, 0x12, 0x68, 0xe4, 0x06, 0xe4, 0x0e, 0x00, 0x19, ++ 0xd2, 0x18, 0x12, 0x8f, 0x52, 0x09, 0xd2, 0x07, 0xd2, 0x0f, 0x00, 0xd0, 0x40, 0x42, 0x08, 0x18, ++ 0x40, 0x10, 0x11, 0x38, 0x10, 0xbd, 0xf0, 0xb5, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0x2c, 0x49, ++ 0x81, 0x82, 0x24, 0x4a, 0x81, 0x13, 0x14, 0x68, 0x20, 0x4b, 0x40, 0x3b, 0xe4, 0x18, 0x21, 0x80, ++ 0x81, 0x8a, 0x28, 0x4e, 0x86, 0x82, 0x1e, 0x49, 0x09, 0x68, 0x80, 0x31, 0x0c, 0x7a, 0xe4, 0x06, ++ 0x02, 0xd5, 0x8c, 0x7b, 0xa4, 0x06, 0x01, 0xd5, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, 0x01, 0x25, ++ 0x64, 0x00, 0xad, 0x02, 0x17, 0x68, 0x64, 0x19, 0xff, 0x18, 0x7c, 0x80, 0x84, 0x8a, 0x86, 0x82, ++ 0x0c, 0x7a, 0xe4, 0x06, 0x02, 0xd5, 0x89, 0x7b, 0x49, 0x06, 0x01, 0xd5, 0x01, 0x21, 0x00, 0xe0, ++ 0x00, 0x21, 0x49, 0x00, 0x14, 0x68, 0x49, 0x19, 0xe4, 0x18, 0xa1, 0x80, 0x81, 0x8a, 0x15, 0x49, ++ 0x89, 0x1c, 0x81, 0x82, 0x14, 0x68, 0xe4, 0x18, 0xe5, 0x80, 0x84, 0x8a, 0x81, 0x82, 0x14, 0x68, ++ 0xe4, 0x18, 0x25, 0x81, 0x84, 0x8a, 0x81, 0x82, 0x11, 0x68, 0xc9, 0x18, 0x4d, 0x81, 0x81, 0x8a, ++ 0x0d, 0x49, 0x81, 0x82, 0x08, 0x48, 0x11, 0x68, 0xc9, 0x18, 0x17, 0xe0, 0x80, 0xa0, 0x01, 0x00, ++ 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0xff, 0x7f, 0x00, 0x00, 0x80, 0xa2, 0x01, 0x00, ++ 0xf3, 0x8f, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0xf3, 0x8b, 0x00, 0x00, ++ 0xff, 0x3f, 0x00, 0x00, 0xfd, 0x93, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x88, 0x81, 0xf0, 0xbd, ++ 0x70, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0xfb, 0x4a, 0x8a, 0x82, 0x82, 0x02, 0xfb, 0x48, ++ 0x04, 0x68, 0x0d, 0x23, 0x5b, 0x03, 0xe4, 0x18, 0x22, 0x85, 0x8a, 0x8a, 0xf8, 0x4a, 0x8a, 0x82, ++ 0x06, 0x68, 0x00, 0x25, 0xf7, 0x4c, 0x36, 0x19, 0x75, 0x80, 0xf7, 0x4d, 0x2d, 0x68, 0x80, 0x35, ++ 0xad, 0x7b, 0xed, 0x07, 0x0d, 0xd1, 0x8d, 0x8a, 0x8a, 0x82, 0x05, 0x68, 0x52, 0x1c, 0x2c, 0x19, ++ 0x62, 0x80, 0x8a, 0x8a, 0x40, 0x22, 0xd2, 0x43, 0x8a, 0x82, 0x00, 0x68, 0x40, 0x21, 0xc0, 0x18, ++ 0x01, 0x84, 0x70, 0xbd, 0xf0, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0xe6, 0x4a, 0x8a, 0x82, ++ 0x82, 0x02, 0xe6, 0x48, 0x03, 0x68, 0x0d, 0x27, 0x7f, 0x03, 0xdb, 0x19, 0x1a, 0x85, 0x8a, 0x8a, ++ 0xe3, 0x4a, 0x8a, 0x82, 0x05, 0x68, 0x00, 0x24, 0xe2, 0x4b, 0xed, 0x18, 0x6c, 0x80, 0x8d, 0x8a, ++ 0x8a, 0x82, 0x05, 0x68, 0xed, 0x18, 0xac, 0x80, 0x8d, 0x8a, 0x8a, 0x82, 0x05, 0x68, 0xed, 0x18, ++ 0xec, 0x80, 0x8d, 0x8a, 0x8a, 0x82, 0x05, 0x68, 0xed, 0x18, 0x2c, 0x81, 0x8d, 0x8a, 0x8a, 0x82, ++ 0x05, 0x68, 0xed, 0x18, 0x6c, 0x81, 0xd8, 0x4c, 0x24, 0x68, 0x80, 0x34, 0xa5, 0x7b, 0xee, 0x07, ++ 0xd6, 0x4d, 0x04, 0xd1, 0x8e, 0x8a, 0x8a, 0x82, 0x06, 0x68, 0xf6, 0x18, 0x75, 0x80, 0xa6, 0x7b, ++ 0xb6, 0x07, 0x04, 0xd4, 0x8e, 0x8a, 0x8a, 0x82, 0x06, 0x68, 0xf6, 0x18, 0xb5, 0x80, 0xa4, 0x7b, ++ 0x64, 0x07, 0x04, 0xd4, 0x8c, 0x8a, 0x8a, 0x82, 0x02, 0x68, 0xd2, 0x18, 0xd5, 0x80, 0x8a, 0x8a, ++ 0x40, 0x22, 0xd2, 0x43, 0x8a, 0x82, 0x00, 0x68, 0x40, 0x21, 0xc0, 0x19, 0x01, 0x84, 0xf0, 0xbd, ++ 0xfe, 0xb5, 0xc5, 0x4e, 0xc1, 0x4a, 0x30, 0x68, 0xc2, 0x49, 0x04, 0x46, 0x40, 0x30, 0xc3, 0x7c, ++ 0x12, 0x68, 0x01, 0x2b, 0x28, 0xd0, 0x51, 0x18, 0x09, 0x8e, 0x25, 0x46, 0xe1, 0x83, 0x60, 0x35, ++ 0x29, 0x78, 0xa1, 0x84, 0x61, 0x8c, 0x01, 0x22, 0x1f, 0x23, 0x49, 0xb2, 0x01, 0x93, 0x02, 0x92, ++ 0x00, 0x91, 0x18, 0x22, 0x82, 0x56, 0x20, 0x23, 0x1e, 0x21, 0x00, 0x20, 0xe3, 0x5e, 0x61, 0x5e, ++ 0x28, 0x56, 0xfe, 0xf7, 0xd8, 0xfd, 0x31, 0x68, 0xc0, 0xb2, 0x0a, 0x46, 0x60, 0x32, 0x10, 0x70, ++ 0x13, 0x46, 0x20, 0x3a, 0x8d, 0x8c, 0x14, 0x46, 0x15, 0x76, 0x1a, 0x7b, 0xe2, 0x75, 0xca, 0x8b, ++ 0x0a, 0x84, 0xff, 0xf7, 0x3a, 0xfe, 0xdd, 0xe5, 0x51, 0x18, 0x09, 0x8d, 0xd5, 0xe7, 0xfe, 0xb5, ++ 0xa9, 0x4e, 0xa6, 0x4a, 0x31, 0x68, 0xa7, 0x4b, 0x0c, 0x46, 0x40, 0x31, 0xcd, 0x7c, 0x12, 0x68, ++ 0x01, 0x2d, 0x2d, 0xd0, 0xd2, 0x18, 0x12, 0x8e, 0x1f, 0x23, 0x10, 0x18, 0xe0, 0x83, 0x61, 0x22, ++ 0x10, 0x57, 0x20, 0x85, 0x00, 0x22, 0xd2, 0x43, 0x00, 0x25, 0x01, 0x93, 0x02, 0x92, 0x00, 0x95, ++ 0x18, 0x22, 0x8a, 0x56, 0x20, 0x23, 0x1e, 0x21, 0xe3, 0x5e, 0x61, 0x5e, 0xfe, 0xf7, 0xa3, 0xfd, ++ 0x31, 0x68, 0x0a, 0x46, 0x60, 0x32, 0x50, 0x70, 0x13, 0x46, 0x20, 0x3a, 0x0c, 0x8d, 0x17, 0x46, ++ 0x14, 0x76, 0x1a, 0x7b, 0xfa, 0x75, 0xca, 0x8b, 0x0a, 0x84, 0xfc, 0xf7, 0x73, 0xf9, 0x30, 0x68, ++ 0x6a, 0x21, 0x09, 0x5c, 0x00, 0x29, 0x06, 0xd0, 0x01, 0x21, 0x80, 0x30, 0x41, 0x72, 0xa1, 0xe5, ++ 0xd2, 0x18, 0x12, 0x8d, 0xd0, 0xe7, 0x80, 0x30, 0x45, 0x72, 0x9b, 0xe5, 0xfe, 0xb5, 0x87, 0x48, ++ 0x01, 0x68, 0x88, 0x48, 0x40, 0x30, 0x08, 0x18, 0x40, 0x88, 0x87, 0x4c, 0x02, 0x07, 0x20, 0x68, ++ 0x12, 0x0f, 0x07, 0x46, 0x60, 0x37, 0xba, 0x70, 0x82, 0x84, 0x2a, 0x21, 0x41, 0x5e, 0x01, 0x25, ++ 0x0b, 0x1d, 0x08, 0x2b, 0x03, 0xd8, 0x56, 0x23, 0x1b, 0x5c, 0x01, 0x2b, 0x22, 0xd0, 0x00, 0x22, ++ 0xd2, 0x43, 0x0f, 0x23, 0x00, 0x26, 0x01, 0x93, 0x02, 0x92, 0x00, 0x96, 0x2c, 0x23, 0xc3, 0x5e, ++ 0x04, 0x22, 0x02, 0x20, 0xba, 0x56, 0x38, 0x56, 0xfe, 0xf7, 0x5d, 0xfd, 0x22, 0x68, 0xc1, 0xb2, ++ 0x10, 0x46, 0x60, 0x30, 0x81, 0x70, 0x92, 0x8c, 0xd2, 0xb2, 0x02, 0x71, 0x03, 0x7b, 0x01, 0x2b, ++ 0x01, 0xd0, 0x86, 0x71, 0x08, 0xe0, 0x91, 0x42, 0x01, 0xd1, 0x85, 0x71, 0x04, 0xe0, 0x02, 0x21, ++ 0x81, 0x71, 0x01, 0xe0, 0x3a, 0x71, 0xbd, 0x71, 0x20, 0x68, 0x41, 0x8d, 0x81, 0x85, 0x56, 0x21, ++ 0x09, 0x5c, 0x01, 0x29, 0x06, 0xd1, 0x01, 0x46, 0x60, 0x31, 0x8a, 0x79, 0x01, 0x2a, 0x01, 0xd0, ++ 0x02, 0x22, 0x8a, 0x71, 0x03, 0x21, 0x09, 0x07, 0x8a, 0x8a, 0x0f, 0x22, 0xd2, 0x43, 0x8a, 0x82, ++ 0x60, 0x30, 0x81, 0x78, 0x5d, 0x48, 0x02, 0x68, 0x5e, 0x48, 0x40, 0x30, 0x10, 0x18, 0x41, 0x80, ++ 0x40, 0xe5, 0xf8, 0xb5, 0x5c, 0x4c, 0x01, 0x25, 0x20, 0x68, 0x01, 0x46, 0x40, 0x31, 0xcb, 0x7c, ++ 0x02, 0x46, 0x60, 0x32, 0x00, 0x2b, 0x04, 0xd0, 0x01, 0x2b, 0x06, 0xd1, 0x03, 0x78, 0x5b, 0x07, ++ 0x03, 0xd5, 0x8d, 0x23, 0x1b, 0x5c, 0x5b, 0x07, 0x01, 0xd5, 0x15, 0x72, 0x66, 0xe0, 0x00, 0x78, ++ 0x42, 0x07, 0x05, 0x20, 0x00, 0x2a, 0x48, 0x77, 0x03, 0xda, 0xfe, 0xf7, 0x7f, 0xf9, 0x21, 0x68, ++ 0x48, 0x84, 0xfe, 0xf7, 0x83, 0xf9, 0x4c, 0x4a, 0x11, 0x68, 0xc8, 0x84, 0xff, 0xf7, 0x04, 0xfb, ++ 0x12, 0x68, 0x04, 0x46, 0x11, 0x46, 0x60, 0x31, 0x08, 0x70, 0x10, 0x78, 0x40, 0x07, 0x40, 0xd5, ++ 0x13, 0x46, 0x80, 0x33, 0x58, 0x79, 0x00, 0x28, 0x05, 0xd0, 0x00, 0x20, 0x08, 0x56, 0x00, 0x28, ++ 0x01, 0xda, 0x60, 0x1c, 0x1a, 0xe0, 0x26, 0x20, 0x56, 0x8c, 0x10, 0x5e, 0xb4, 0x46, 0x40, 0x4f, ++ 0x86, 0x19, 0x38, 0x8c, 0xb6, 0x46, 0x86, 0x42, 0x08, 0xda, 0x58, 0x7a, 0x00, 0x28, 0x05, 0xd1, ++ 0xff, 0x26, 0x76, 0x36, 0xb4, 0x45, 0x01, 0xd2, 0x1f, 0x2c, 0xea, 0xd3, 0x7e, 0x8c, 0xb6, 0x45, ++ 0x23, 0xdc, 0x58, 0x7a, 0x00, 0x28, 0x20, 0xd1, 0x01, 0xe0, 0x60, 0x1e, 0x08, 0x70, 0x32, 0x4e, ++ 0x08, 0x78, 0xff, 0xf7, 0x42, 0xfd, 0x30, 0x68, 0x02, 0x46, 0x60, 0x30, 0x01, 0x78, 0xa1, 0x42, ++ 0x1b, 0xd0, 0x03, 0x7a, 0x01, 0x2b, 0x18, 0xd0, 0x02, 0x25, 0xa1, 0x42, 0x1a, 0xd9, 0x04, 0x2b, ++ 0x16, 0xd0, 0x40, 0x32, 0x92, 0x7d, 0x01, 0x2a, 0x12, 0xd0, 0x03, 0x22, 0x02, 0x72, 0x08, 0x1b, ++ 0x1a, 0xe0, 0x89, 0x20, 0x80, 0x5c, 0x00, 0x28, 0x04, 0xd0, 0x40, 0x32, 0x52, 0x7f, 0x94, 0x42, ++ 0xdb, 0xd8, 0xdc, 0xe7, 0x1f, 0x2c, 0xbc, 0xd3, 0xd9, 0xe7, 0x05, 0x72, 0x00, 0x20, 0xf8, 0xbd, ++ 0x05, 0x72, 0xec, 0xe7, 0x03, 0x2b, 0x09, 0xd0, 0x40, 0x32, 0x92, 0x7d, 0x01, 0x2a, 0x05, 0xd0, ++ 0x04, 0x22, 0x02, 0x72, 0x60, 0x1a, 0x40, 0x42, 0x40, 0xb2, 0xf8, 0xbd, 0x05, 0x72, 0xf9, 0xe7, ++ 0x10, 0xb5, 0x04, 0x46, 0xfc, 0xf7, 0xea, 0xf9, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, ++ 0xc0, 0x43, 0x88, 0x82, 0x0d, 0x48, 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, ++ 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0x0f, 0x4a, 0x8a, 0x82, 0x09, 0x23, 0x04, 0x68, 0x9b, 0x02, ++ 0x08, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0x00, 0x23, 0x8b, 0x82, 0x0a, 0x49, 0x00, 0x68, ++ 0x80, 0x18, 0x41, 0x84, 0x10, 0xbd, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, ++ 0xff, 0x7f, 0x00, 0x00, 0x40, 0xa0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x20, 0xff, 0x8b, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0xf0, 0xb5, 0x03, 0x21, ++ 0x09, 0x07, 0xff, 0x25, 0x01, 0x26, 0xf7, 0x4a, 0xf7, 0x4b, 0xf8, 0x4c, 0x8f, 0x8a, 0x0d, 0x28, ++ 0x8d, 0x82, 0x09, 0xd8, 0x80, 0x1f, 0x86, 0x40, 0x15, 0x68, 0x30, 0x02, 0xed, 0x18, 0xa8, 0x84, ++ 0x88, 0x8a, 0x8c, 0x82, 0x04, 0x20, 0x08, 0xe0, 0x0e, 0x38, 0x86, 0x40, 0x15, 0x68, 0x30, 0x02, ++ 0xed, 0x18, 0xa8, 0x84, 0x88, 0x8a, 0x8c, 0x82, 0x08, 0x20, 0x11, 0x68, 0xc9, 0x18, 0x08, 0x84, ++ 0xf0, 0xbd, 0xfe, 0xb5, 0xe7, 0x4d, 0x28, 0x68, 0xe7, 0x4e, 0x40, 0x36, 0x80, 0x19, 0x80, 0x88, ++ 0xe7, 0x4f, 0x41, 0x07, 0x3c, 0x68, 0x49, 0x0f, 0x20, 0x46, 0x60, 0x30, 0xc1, 0x70, 0xa1, 0x84, ++ 0x00, 0x23, 0xdb, 0x43, 0x07, 0x22, 0x00, 0x21, 0x02, 0x93, 0x01, 0x92, 0x00, 0x91, 0x2e, 0x23, ++ 0x26, 0x21, 0xe3, 0x5e, 0x05, 0x22, 0x61, 0x5e, 0x82, 0x56, 0x04, 0x46, 0x03, 0x20, 0x20, 0x56, ++ 0xfe, 0xf7, 0x21, 0xfc, 0x3a, 0x68, 0x11, 0x46, 0x60, 0x31, 0xc8, 0x70, 0x90, 0x8c, 0x48, 0x71, ++ 0x08, 0x7b, 0xc8, 0x71, 0xd0, 0x8c, 0xd0, 0x85, 0x03, 0x20, 0x00, 0x07, 0x82, 0x8a, 0x07, 0x22, ++ 0xd2, 0x43, 0x82, 0x82, 0xc8, 0x78, 0x29, 0x68, 0x89, 0x19, 0x88, 0x80, 0x22, 0xe4, 0x70, 0xb5, ++ 0xcf, 0x4c, 0xff, 0x25, 0x20, 0x68, 0x01, 0x46, 0x40, 0x31, 0x8a, 0x7a, 0x17, 0x2a, 0x17, 0xd0, ++ 0x18, 0x2a, 0x22, 0xd0, 0xc9, 0x7c, 0x00, 0x29, 0x23, 0xd1, 0x01, 0x78, 0x49, 0x07, 0x20, 0xd5, ++ 0x60, 0x30, 0x40, 0x7a, 0x00, 0x28, 0x0f, 0xd1, 0x09, 0x20, 0xff, 0xf7, 0x81, 0xfd, 0x20, 0x68, ++ 0x01, 0x22, 0x69, 0x21, 0x0a, 0x54, 0x17, 0x22, 0x4a, 0x21, 0x0a, 0x54, 0x80, 0x30, 0x85, 0x72, ++ 0xfb, 0xf7, 0xe5, 0xff, 0x00, 0x28, 0x12, 0xd0, 0x09, 0x20, 0xff, 0xf7, 0x9b, 0xfd, 0x20, 0x68, ++ 0x18, 0x22, 0x4a, 0x21, 0x0a, 0x54, 0x80, 0x30, 0x85, 0x72, 0xfb, 0xf7, 0xd8, 0xff, 0x00, 0x28, ++ 0x05, 0xd0, 0x20, 0x68, 0x19, 0x21, 0x40, 0x30, 0x81, 0x72, 0x00, 0x20, 0x70, 0xbd, 0x02, 0x20, ++ 0x70, 0xbd, 0x00, 0xb5, 0xb2, 0x49, 0x03, 0x00, 0x09, 0x68, 0x80, 0x31, 0x02, 0xf0, 0x88, 0xfa, ++ 0x06, 0x14, 0x04, 0x07, 0x0a, 0x0d, 0x10, 0x14, 0x88, 0x7b, 0xc0, 0x07, 0x0a, 0xe0, 0x88, 0x7b, ++ 0x80, 0x07, 0x07, 0xe0, 0x88, 0x7b, 0x40, 0x07, 0x04, 0xe0, 0x88, 0x7b, 0x00, 0x07, 0x01, 0xe0, ++ 0x88, 0x7b, 0xc0, 0x06, 0xc0, 0x17, 0x40, 0x1c, 0x00, 0xbd, 0xf8, 0xb5, 0xa4, 0x4c, 0x01, 0x26, ++ 0x20, 0x68, 0x00, 0x25, 0x40, 0x30, 0x80, 0x7a, 0x20, 0x28, 0x28, 0xd0, 0x21, 0x28, 0x76, 0xd0, ++ 0xfe, 0xf7, 0xd2, 0xfd, 0x20, 0x68, 0x01, 0x46, 0x40, 0x30, 0xc2, 0x7c, 0x00, 0x2a, 0x02, 0xd0, ++ 0x01, 0x2a, 0x4f, 0xd0, 0x82, 0xe0, 0x09, 0x78, 0x49, 0x07, 0x7f, 0xd5, 0x86, 0x76, 0xc5, 0x76, ++ 0x20, 0x68, 0x40, 0x30, 0x80, 0x7e, 0xff, 0xf7, 0xc4, 0xff, 0x00, 0x28, 0x1e, 0xd0, 0x20, 0x68, ++ 0x06, 0x21, 0x40, 0x30, 0x80, 0x7e, 0xfe, 0xf7, 0xf8, 0xfe, 0x20, 0x68, 0x40, 0x30, 0xc5, 0x75, ++ 0x45, 0x75, 0xfb, 0xf7, 0x3c, 0xff, 0x20, 0x68, 0x20, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, ++ 0x7e, 0xff, 0x00, 0x28, 0x67, 0xd0, 0x20, 0x68, 0x40, 0x30, 0xc1, 0x7e, 0x80, 0x7e, 0xff, 0xf7, ++ 0x83, 0xf9, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xea, 0xd0, 0x20, 0x68, 0x02, 0x46, ++ 0x80, 0x32, 0x11, 0x7a, 0xc9, 0x06, 0x10, 0xd5, 0x01, 0x46, 0x40, 0x31, 0x1a, 0x23, 0xcb, 0x56, ++ 0x01, 0x2b, 0x02, 0xd1, 0x97, 0x7b, 0xbf, 0x06, 0x04, 0xd5, 0x02, 0x2b, 0x05, 0xd1, 0x92, 0x7b, ++ 0x52, 0x06, 0x02, 0xd4, 0xca, 0x7e, 0x00, 0x2a, 0x0a, 0xd0, 0x01, 0x46, 0x40, 0x31, 0xcd, 0x76, ++ 0x8a, 0x7e, 0x52, 0x1c, 0x8a, 0x76, 0x5a, 0x21, 0x41, 0x56, 0x06, 0x29, 0xb8, 0xdb, 0x35, 0xe0, ++ 0xce, 0x76, 0xf8, 0xe7, 0x09, 0x78, 0x49, 0x07, 0x30, 0xd5, 0x02, 0x21, 0x81, 0x76, 0xc5, 0x76, ++ 0x20, 0x68, 0x40, 0x30, 0x80, 0x7e, 0xff, 0xf7, 0x74, 0xff, 0x00, 0x28, 0x1e, 0xd0, 0x20, 0x68, ++ 0x06, 0x21, 0x40, 0x30, 0x80, 0x7e, 0xfe, 0xf7, 0xa8, 0xfe, 0x20, 0x68, 0x40, 0x30, 0xc5, 0x75, ++ 0x45, 0x75, 0xfb, 0xf7, 0xec, 0xfe, 0x20, 0x68, 0x21, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, ++ 0x2e, 0xff, 0x00, 0x28, 0x17, 0xd0, 0x20, 0x68, 0x40, 0x30, 0xc1, 0x7e, 0x80, 0x7e, 0xff, 0xf7, ++ 0x33, 0xf9, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0xea, 0xd0, 0x20, 0x68, 0x40, 0x30, ++ 0x81, 0x7e, 0x89, 0x1c, 0x49, 0xb2, 0x81, 0x76, 0x05, 0x29, 0xd1, 0xdb, 0x20, 0x68, 0x40, 0x30, ++ 0x85, 0x72, 0x00, 0x20, 0xf8, 0xbd, 0x02, 0x20, 0xf8, 0xbd, 0xf8, 0xb5, 0x54, 0x4d, 0x00, 0x24, ++ 0x28, 0x68, 0x02, 0x46, 0x40, 0x30, 0x81, 0x7a, 0x10, 0x29, 0x4d, 0xd0, 0xc1, 0x7c, 0x28, 0x46, ++ 0x00, 0x68, 0x80, 0x30, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x29, 0x77, 0xd0, 0x79, 0xe0, 0x40, 0x7b, ++ 0xc0, 0x07, 0x76, 0xd1, 0xfe, 0xf7, 0x28, 0xfd, 0x28, 0x68, 0x00, 0x78, 0x40, 0x07, 0x06, 0xd4, ++ 0x0c, 0x20, 0xff, 0xf7, 0xa1, 0xfb, 0x28, 0x68, 0x00, 0x78, 0x40, 0x07, 0x2e, 0xd5, 0x28, 0x68, ++ 0x01, 0x46, 0x40, 0x31, 0x8a, 0x7d, 0x01, 0x2a, 0x0d, 0xd0, 0x85, 0x21, 0x09, 0x5c, 0x00, 0x29, ++ 0x02, 0xd0, 0x00, 0x21, 0xc9, 0x43, 0x36, 0xe0, 0xfd, 0xf7, 0xd2, 0xfe, 0x29, 0x68, 0x48, 0x85, ++ 0xff, 0xf7, 0x5c, 0xfd, 0x47, 0xe0, 0xc9, 0x7f, 0x00, 0x29, 0x00, 0xd1, 0x44, 0x85, 0x85, 0x21, ++ 0x09, 0x5c, 0x00, 0x29, 0x03, 0xd0, 0x41, 0x8d, 0x49, 0x1e, 0x41, 0x85, 0x05, 0xe0, 0xfd, 0xf7, ++ 0xbf, 0xfe, 0x29, 0x68, 0x4a, 0x8d, 0x80, 0x18, 0x48, 0x85, 0x28, 0x68, 0x40, 0x30, 0xc1, 0x7f, ++ 0x49, 0x1c, 0xc9, 0xb2, 0xc1, 0x77, 0x08, 0x29, 0x28, 0xd0, 0x2c, 0xe0, 0xfb, 0xf7, 0x77, 0xfe, ++ 0x28, 0x68, 0x10, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, 0xb9, 0xfe, 0x00, 0x28, 0x0c, 0xd0, ++ 0x28, 0x68, 0x24, 0x4b, 0x01, 0x46, 0x40, 0x31, 0x8a, 0x7d, 0x23, 0x4e, 0x01, 0x2a, 0x06, 0xd0, ++ 0x19, 0x68, 0x89, 0x19, 0x09, 0x8e, 0x41, 0x85, 0xca, 0xe7, 0x02, 0x20, 0xf8, 0xbd, 0xca, 0x7f, ++ 0x00, 0x2a, 0x00, 0xd1, 0x44, 0x85, 0x47, 0x8d, 0x1b, 0x68, 0x9b, 0x19, 0x1b, 0x8e, 0x52, 0x1c, ++ 0xfb, 0x18, 0x43, 0x85, 0xd0, 0xb2, 0xc8, 0x77, 0x08, 0x28, 0x04, 0xd1, 0xff, 0xf7, 0x16, 0xfd, ++ 0x28, 0x68, 0x40, 0x30, 0xc4, 0x77, 0x28, 0x68, 0x01, 0x78, 0x49, 0x07, 0x0c, 0xd4, 0x60, 0x30, ++ 0x80, 0x79, 0x00, 0x28, 0x97, 0xd0, 0x07, 0xe0, 0x00, 0xe0, 0x02, 0xe0, 0x40, 0x7b, 0xc0, 0x07, ++ 0x08, 0xd0, 0x01, 0x20, 0x60, 0x32, 0x90, 0x71, 0x28, 0x68, 0x33, 0x21, 0x40, 0x30, 0x81, 0x72, ++ 0x00, 0x20, 0xf8, 0xbd, 0xfe, 0xf7, 0xa8, 0xfc, 0x28, 0x68, 0x01, 0x46, 0x40, 0x30, 0x82, 0x7d, ++ 0x01, 0x2a, 0x0f, 0xd0, 0xff, 0xf7, 0x71, 0xfb, 0x29, 0x68, 0x48, 0x85, 0xff, 0xf7, 0xee, 0xfc, ++ 0x1e, 0xe0, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, 0xf3, 0xff, 0x00, 0x00, ++ 0x90, 0x00, 0x00, 0x20, 0xc0, 0x7f, 0x00, 0x28, 0x00, 0xd1, 0x4c, 0x85, 0xff, 0xf7, 0x5d, 0xfb, ++ 0x29, 0x68, 0x4a, 0x8d, 0x80, 0x18, 0x48, 0x85, 0x40, 0x31, 0xc8, 0x7f, 0x40, 0x1c, 0xc0, 0xb2, ++ 0xc8, 0x77, 0x08, 0x28, 0x04, 0xd1, 0xff, 0xf7, 0xd1, 0xfc, 0x28, 0x68, 0x40, 0x30, 0xc4, 0x77, ++ 0x28, 0x68, 0x01, 0x78, 0x49, 0x07, 0xc7, 0xd4, 0x60, 0x30, 0x80, 0x79, 0x00, 0x28, 0xcb, 0xd0, ++ 0xc2, 0xe7, 0x10, 0xb5, 0xfb, 0x4c, 0x20, 0x68, 0x01, 0x46, 0x40, 0x31, 0xca, 0x7c, 0x00, 0x2a, ++ 0x06, 0xd0, 0x01, 0x2a, 0x02, 0xd1, 0x02, 0x78, 0x52, 0x07, 0x01, 0xd4, 0x00, 0x20, 0xc1, 0xe5, ++ 0x89, 0x7a, 0x0f, 0x29, 0x22, 0xd0, 0x80, 0x30, 0x40, 0x7b, 0x80, 0x06, 0x2a, 0xd4, 0xfe, 0xf7, ++ 0x5b, 0xfc, 0x00, 0x20, 0xfc, 0xf7, 0x42, 0xf8, 0x09, 0x20, 0xff, 0xf7, 0xaa, 0xfa, 0x03, 0x20, ++ 0x00, 0x07, 0x81, 0x8a, 0x20, 0x21, 0xc9, 0x43, 0x81, 0x82, 0xeb, 0x49, 0x20, 0x20, 0x09, 0x68, ++ 0xea, 0x4a, 0x89, 0x18, 0x08, 0x84, 0xfb, 0xf7, 0xf4, 0xfd, 0x21, 0x68, 0x60, 0x31, 0x48, 0x70, ++ 0xfb, 0xf7, 0xcd, 0xfd, 0x20, 0x68, 0x0f, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, 0x0f, 0xfe, ++ 0x00, 0x28, 0x0c, 0xd0, 0x3c, 0x20, 0xff, 0xf7, 0x4a, 0xfc, 0x20, 0x68, 0x40, 0x30, 0xc0, 0x7d, ++ 0x00, 0x28, 0xed, 0xd0, 0x20, 0x68, 0x32, 0x21, 0x40, 0x30, 0x81, 0x72, 0xc6, 0xe7, 0x02, 0x20, ++ 0x88, 0xe5, 0x10, 0xb5, 0xd7, 0x4c, 0x20, 0x68, 0x01, 0x46, 0x40, 0x31, 0x8a, 0x7a, 0x11, 0x2a, ++ 0x21, 0xd0, 0xc9, 0x7c, 0x00, 0x29, 0x45, 0xd1, 0x88, 0x21, 0x09, 0x5c, 0xc9, 0x09, 0x41, 0xd1, ++ 0x01, 0x78, 0x89, 0x06, 0x89, 0x0f, 0x02, 0x29, 0x3c, 0xd0, 0xfe, 0xf7, 0x15, 0xfc, 0x0c, 0x20, ++ 0xff, 0xf7, 0x4e, 0xfd, 0x20, 0x68, 0x00, 0x21, 0xc1, 0x84, 0x06, 0x21, 0x40, 0x30, 0x41, 0x75, ++ 0x20, 0x68, 0x40, 0x30, 0x40, 0x7d, 0xff, 0xf7, 0x79, 0xfd, 0xfb, 0xf7, 0x90, 0xfd, 0x20, 0x68, ++ 0x11, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, 0xd2, 0xfd, 0x00, 0x28, 0x11, 0xd0, 0xc2, 0x49, ++ 0x08, 0x68, 0xc2, 0x4a, 0x80, 0x18, 0x00, 0x8e, 0x00, 0x28, 0x10, 0xd0, 0x20, 0x68, 0x26, 0x23, ++ 0xc3, 0x5e, 0x09, 0x68, 0x8a, 0x18, 0x30, 0x21, 0x51, 0x5e, 0x00, 0x29, 0x03, 0xdd, 0x01, 0x21, ++ 0x03, 0xe0, 0x02, 0x20, 0x46, 0xe5, 0x00, 0x21, 0xc9, 0x43, 0x59, 0x18, 0xc1, 0x84, 0x20, 0x68, ++ 0x40, 0x30, 0x41, 0x7d, 0x49, 0x1c, 0xc9, 0xb2, 0x41, 0x75, 0x16, 0x29, 0xd0, 0xd3, 0xff, 0xf7, ++ 0x70, 0xfd, 0x02, 0xe0, 0x01, 0x21, 0x60, 0x30, 0xc1, 0x71, 0x20, 0x68, 0x31, 0x21, 0x40, 0x30, ++ 0x81, 0x72, 0x00, 0x20, 0x2e, 0xe5, 0xf8, 0xb5, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xac, 0x49, ++ 0x81, 0x82, 0xa9, 0x4e, 0x01, 0x20, 0x31, 0x68, 0x40, 0x02, 0x0d, 0x27, 0x7f, 0x03, 0xc9, 0x19, ++ 0x48, 0x80, 0x30, 0x68, 0xc0, 0x19, 0x80, 0x8f, 0x01, 0xf0, 0xff, 0xfc, 0x05, 0x46, 0x01, 0xe0, ++ 0x00, 0x2c, 0x08, 0xd0, 0x30, 0x68, 0xc0, 0x19, 0x80, 0x8f, 0x80, 0x09, 0xc0, 0x07, 0xc0, 0x0f, ++ 0x01, 0xd0, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, 0x00, 0x2c, 0x05, 0xd0, 0x01, 0xf0, 0xed, 0xfc, ++ 0x40, 0x1b, 0x80, 0xb2, 0x0b, 0x28, 0xeb, 0xd3, 0x30, 0x68, 0xc1, 0x19, 0x0a, 0x20, 0x08, 0x5e, ++ 0x00, 0x2c, 0x03, 0xd0, 0x00, 0x28, 0x01, 0xda, 0x00, 0x24, 0xe4, 0x43, 0x20, 0x46, 0xf8, 0xbd, ++ 0x10, 0xb5, 0x90, 0x48, 0x00, 0x68, 0x80, 0x30, 0x00, 0x7a, 0x80, 0x07, 0x01, 0xd5, 0x00, 0x20, ++ 0xf0, 0xe4, 0xff, 0xf7, 0xc0, 0xff, 0x00, 0x28, 0xfa, 0xd0, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, ++ 0x01, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x88, 0x49, 0x01, 0x20, 0x09, 0x68, 0x0d, 0x22, 0x52, 0x03, ++ 0x89, 0x18, 0x48, 0x86, 0x01, 0x46, 0x17, 0x20, 0x01, 0xf0, 0x3c, 0xff, 0x01, 0x20, 0xd9, 0xe4, ++ 0xf0, 0xb5, 0x80, 0x4c, 0x00, 0x21, 0x20, 0x68, 0x03, 0x25, 0x02, 0x78, 0x2d, 0x07, 0x52, 0x07, ++ 0x7d, 0x4e, 0x0f, 0x46, 0x00, 0x2a, 0x2c, 0xda, 0x58, 0x22, 0x82, 0x56, 0x20, 0x46, 0x00, 0x68, ++ 0xd3, 0x1d, 0x60, 0x30, 0x0e, 0x2b, 0x01, 0xd8, 0x87, 0x70, 0x13, 0xe0, 0x13, 0x46, 0x0f, 0x33, ++ 0x1e, 0x2b, 0x02, 0xd8, 0x10, 0x21, 0x04, 0x22, 0x0b, 0xe0, 0x13, 0x46, 0x17, 0x33, 0x2e, 0x2b, ++ 0x02, 0xd8, 0x20, 0x21, 0x08, 0x22, 0x04, 0xe0, 0x1f, 0x32, 0x3e, 0x2a, 0x02, 0xd8, 0x30, 0x21, ++ 0x0c, 0x22, 0x82, 0x70, 0x01, 0x20, 0xfe, 0xf7, 0xcb, 0xfc, 0xa8, 0x8a, 0x0f, 0x20, 0xc0, 0x43, ++ 0xa8, 0x82, 0x20, 0x68, 0x31, 0x68, 0x60, 0x30, 0x80, 0x78, 0x68, 0x4a, 0x40, 0x32, 0x89, 0x18, ++ 0x48, 0x80, 0x20, 0x68, 0x58, 0x21, 0x41, 0x56, 0x00, 0x29, 0x01, 0xda, 0x65, 0x48, 0x01, 0xe0, ++ 0x03, 0x20, 0x80, 0x03, 0xa9, 0x8a, 0x01, 0x21, 0xa9, 0x82, 0x32, 0x68, 0x41, 0x00, 0x0d, 0x20, ++ 0x40, 0x03, 0x12, 0x18, 0x91, 0x80, 0xa9, 0x8a, 0x5f, 0x49, 0xa9, 0x82, 0x33, 0x68, 0x80, 0x22, ++ 0x1b, 0x18, 0x5a, 0x80, 0xaa, 0x8a, 0xa9, 0x82, 0x31, 0x68, 0x08, 0x18, 0x47, 0x80, 0x00, 0x20, ++ 0xf0, 0xbd, 0x70, 0xb5, 0x53, 0x4c, 0x88, 0x21, 0x20, 0x68, 0x00, 0x25, 0x09, 0x5c, 0x40, 0x30, ++ 0xc9, 0x07, 0x00, 0x29, 0x03, 0xd0, 0x05, 0x76, 0x45, 0x76, 0x00, 0x20, 0x70, 0xbd, 0x81, 0x7a, ++ 0x07, 0x29, 0x01, 0xd0, 0x05, 0x76, 0x45, 0x76, 0xff, 0xf7, 0x3d, 0xff, 0x00, 0x28, 0x28, 0xd0, ++ 0x21, 0x68, 0x40, 0x31, 0x0a, 0x7e, 0x10, 0x18, 0x40, 0xb2, 0x08, 0x76, 0x4a, 0x7e, 0x52, 0x1c, ++ 0x52, 0xb2, 0x4a, 0x76, 0x20, 0x28, 0x09, 0xda, 0x30, 0x2a, 0x07, 0xda, 0xff, 0xf7, 0x80, 0xff, ++ 0x20, 0x68, 0x07, 0x21, 0x40, 0x30, 0x81, 0x72, 0x02, 0x20, 0x70, 0xbd, 0x03, 0x20, 0x00, 0x07, ++ 0x81, 0x8a, 0x01, 0x21, 0xc9, 0x43, 0x81, 0x82, 0x3b, 0x49, 0x01, 0x20, 0x09, 0x68, 0x0d, 0x22, ++ 0x52, 0x03, 0x89, 0x18, 0x48, 0x86, 0x01, 0x46, 0x17, 0x20, 0x01, 0xf0, 0xa3, 0xfe, 0x01, 0x20, ++ 0x70, 0xbd, 0x20, 0x68, 0x40, 0x30, 0xc6, 0xe7, 0x32, 0x48, 0x53, 0x21, 0x00, 0x68, 0x0a, 0x5c, ++ 0xc1, 0x7b, 0xc9, 0x08, 0x00, 0x2a, 0x07, 0xd0, 0x01, 0x29, 0x11, 0xd9, 0x00, 0x7c, 0xc0, 0x08, ++ 0x01, 0x28, 0x0d, 0xd9, 0x00, 0x20, 0x70, 0x47, 0x01, 0x29, 0x09, 0xd9, 0x01, 0x7c, 0xc9, 0x08, ++ 0x01, 0x29, 0x05, 0xd9, 0x41, 0x7b, 0xc9, 0x08, 0x01, 0x29, 0x01, 0xd9, 0x80, 0x7b, 0xee, 0xe7, ++ 0x01, 0x20, 0x70, 0x47, 0xf8, 0xb5, 0x23, 0x4d, 0x0f, 0x23, 0x2a, 0x68, 0x11, 0x46, 0x40, 0x31, ++ 0xcb, 0x56, 0x4b, 0x76, 0x90, 0x7b, 0x54, 0x7b, 0x00, 0x1b, 0x40, 0x10, 0xd0, 0x84, 0x8e, 0x7d, ++ 0x00, 0x24, 0x01, 0x2e, 0x06, 0xd0, 0x01, 0x26, 0x40, 0x05, 0xf6, 0x05, 0x80, 0x19, 0x00, 0x16, ++ 0x18, 0x1a, 0x0d, 0xe0, 0x16, 0x46, 0x80, 0x36, 0xb7, 0x79, 0x07, 0x2f, 0x09, 0xd3, 0xb4, 0x71, ++ 0x0c, 0x28, 0x01, 0xdd, 0x58, 0x1e, 0x03, 0xe0, 0x0c, 0x26, 0xf0, 0x42, 0x01, 0xda, 0x58, 0x1c, ++ 0x48, 0x76, 0x19, 0x20, 0x08, 0x56, 0x18, 0x28, 0x01, 0xda, 0x18, 0x20, 0x02, 0xe0, 0x2c, 0x28, ++ 0x01, 0xdd, 0x2c, 0x20, 0x48, 0x76, 0x19, 0x20, 0x08, 0x56, 0x83, 0x42, 0x30, 0xd0, 0xc3, 0x1a, ++ 0xdb, 0x00, 0xd3, 0x84, 0xc8, 0x73, 0xfb, 0xf7, 0xb7, 0xfe, 0x28, 0x68, 0x26, 0x22, 0x81, 0x7b, ++ 0x82, 0x5e, 0xf8, 0x23, 0x89, 0x18, 0x09, 0xb2, 0x01, 0x85, 0x00, 0x29, 0x0e, 0xda, 0x04, 0x85, ++ 0x0f, 0xe0, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0x40, 0xa0, 0x01, 0x00, ++ 0xff, 0xf8, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xf8, 0x29, 0x00, 0xdd, ++ 0x03, 0x85, 0x01, 0x8d, 0x81, 0x73, 0x41, 0x7b, 0x89, 0x1a, 0x09, 0xb2, 0x01, 0x85, 0x00, 0x29, ++ 0x01, 0xda, 0x04, 0x85, 0x02, 0xe0, 0xf8, 0x29, 0x00, 0xdd, 0x03, 0x85, 0x01, 0x8d, 0x41, 0x73, ++ 0x00, 0x20, 0xf8, 0xbd, 0x10, 0xb5, 0xfa, 0x4c, 0x20, 0x68, 0x01, 0x46, 0x40, 0x30, 0x82, 0x7a, ++ 0x12, 0x2a, 0x23, 0xd0, 0xc0, 0x7c, 0x00, 0x28, 0x01, 0xd0, 0x01, 0x28, 0x70, 0xd1, 0x80, 0x31, ++ 0x48, 0x7b, 0x40, 0x06, 0x6c, 0xd4, 0xfe, 0xf7, 0x47, 0xfa, 0xfb, 0xf7, 0xf2, 0xfb, 0x21, 0x68, ++ 0x40, 0x31, 0x08, 0x76, 0x08, 0x7c, 0x08, 0x77, 0x0f, 0x20, 0xfb, 0xf7, 0x84, 0xfd, 0x20, 0x68, ++ 0x00, 0x21, 0x40, 0x30, 0x1d, 0xe0, 0x89, 0x7d, 0x01, 0x29, 0x32, 0xd0, 0xfd, 0xf7, 0xd8, 0xfc, ++ 0xfb, 0xf7, 0xbd, 0xfb, 0x20, 0x68, 0x12, 0x21, 0x40, 0x30, 0x81, 0x72, 0xfb, 0xf7, 0xff, 0xfb, ++ 0x00, 0x28, 0x29, 0xd0, 0x20, 0x68, 0x40, 0x30, 0x81, 0x7d, 0x40, 0x7d, 0x01, 0x29, 0x25, 0xd0, ++ 0xfd, 0xf7, 0x63, 0xfd, 0x20, 0x68, 0x40, 0x30, 0xc1, 0x7d, 0x00, 0x29, 0xe8, 0xd0, 0x41, 0x7d, ++ 0x49, 0x1c, 0x41, 0x75, 0x21, 0x68, 0x40, 0x31, 0xca, 0x7c, 0x48, 0x7d, 0x00, 0x2a, 0x18, 0xd0, ++ 0x02, 0x22, 0x90, 0x42, 0xd7, 0xd3, 0x1c, 0x20, 0x08, 0x56, 0xfb, 0xf7, 0xf7, 0xfd, 0x21, 0x68, ++ 0x58, 0x20, 0x08, 0x56, 0xfb, 0xf7, 0xbe, 0xfb, 0xff, 0xf7, 0x26, 0xff, 0x01, 0x28, 0x0a, 0xd0, ++ 0x26, 0xe0, 0xfd, 0xf7, 0xd9, 0xfc, 0xcb, 0xe7, 0x02, 0x20, 0x98, 0xe5, 0xfd, 0xf7, 0xee, 0xfd, ++ 0xd8, 0xe7, 0x04, 0x22, 0xe5, 0xe7, 0x20, 0x68, 0x80, 0x79, 0x40, 0x06, 0x18, 0xd4, 0x01, 0x21, ++ 0x1b, 0x20, 0x01, 0xf0, 0xaf, 0xfd, 0x20, 0x68, 0x80, 0x30, 0x01, 0x7a, 0x0a, 0x07, 0x01, 0x21, ++ 0x00, 0x2a, 0x0c, 0xdb, 0x03, 0x20, 0x00, 0x07, 0x82, 0x8a, 0xca, 0x1e, 0x82, 0x82, 0xc1, 0x48, ++ 0x00, 0x68, 0x0d, 0x22, 0x52, 0x03, 0x80, 0x18, 0x41, 0x86, 0x01, 0x20, 0x77, 0xe5, 0x01, 0x74, ++ 0x20, 0x68, 0x30, 0x23, 0x01, 0x46, 0x02, 0x46, 0x40, 0x31, 0x8b, 0x72, 0x80, 0x30, 0x84, 0x79, ++ 0x03, 0x46, 0x64, 0x1c, 0x84, 0x71, 0xc8, 0x7c, 0x00, 0x28, 0x0a, 0xd1, 0x10, 0x88, 0x41, 0x07, ++ 0x07, 0xd4, 0x00, 0x06, 0x05, 0xd4, 0x58, 0x7b, 0xc0, 0x06, 0x02, 0xd4, 0xff, 0xf7, 0x02, 0xff, ++ 0x5d, 0xe5, 0x00, 0x20, 0x5b, 0xe5, 0x10, 0xb5, 0x04, 0x46, 0xfb, 0xf7, 0xe7, 0xfc, 0x03, 0x21, ++ 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0xaa, 0x48, 0xe2, 0x06, 0x03, 0x68, ++ 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, 0xa6, 0x4a, 0x8a, 0x82, ++ 0xa6, 0x4b, 0x04, 0x68, 0xa6, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, 0x00, 0x23, 0x8b, 0x82, ++ 0xa4, 0x4b, 0x04, 0x68, 0xa4, 0x18, 0x63, 0x84, 0x8b, 0x8a, 0xff, 0x23, 0x8b, 0x82, 0x01, 0x21, ++ 0x00, 0x68, 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x31, 0xe5, 0x10, 0xb5, 0x04, 0x46, 0xfb, 0xf7, ++ 0xbd, 0xfc, 0x03, 0x21, 0x09, 0x07, 0x88, 0x8a, 0x1f, 0x20, 0xc0, 0x43, 0x88, 0x82, 0x95, 0x48, ++ 0xe2, 0x06, 0x03, 0x68, 0xd2, 0x0e, 0x0d, 0x24, 0x64, 0x03, 0x1b, 0x19, 0x5a, 0x85, 0x8a, 0x8a, ++ 0x91, 0x4a, 0x8a, 0x82, 0x91, 0x4b, 0x04, 0x68, 0x91, 0x4a, 0xa4, 0x18, 0x23, 0x84, 0x8b, 0x8a, ++ 0x00, 0x23, 0x8b, 0x82, 0x90, 0x4b, 0x04, 0x68, 0xa4, 0x18, 0x63, 0x84, 0x8b, 0x8a, 0xff, 0x23, ++ 0x8b, 0x82, 0x01, 0x21, 0x00, 0x68, 0x89, 0x02, 0x80, 0x18, 0x81, 0x84, 0x07, 0xe5, 0x70, 0xb5, ++ 0x83, 0x4c, 0x4d, 0x22, 0x20, 0x68, 0x00, 0x25, 0x11, 0x56, 0x2d, 0x29, 0x2b, 0xd0, 0x2e, 0x29, ++ 0x0e, 0xd0, 0x61, 0x21, 0x09, 0x5c, 0x80, 0x30, 0x41, 0x74, 0x14, 0x20, 0xff, 0xf7, 0x9b, 0xff, ++ 0x20, 0x68, 0x05, 0x84, 0xfb, 0xf7, 0xe3, 0xfa, 0x20, 0x68, 0x2e, 0x21, 0x40, 0x30, 0x41, 0x73, ++ 0xfb, 0xf7, 0x25, 0xfb, 0x00, 0x28, 0x31, 0xd0, 0x00, 0x20, 0xff, 0xf7, 0x60, 0xf9, 0x20, 0x68, ++ 0x01, 0x46, 0x40, 0x30, 0xc2, 0x7d, 0x00, 0x2a, 0xec, 0xd0, 0x60, 0x31, 0x49, 0x78, 0x41, 0x77, ++ 0x14, 0x20, 0xff, 0xf7, 0xaa, 0xff, 0x20, 0x68, 0x05, 0x84, 0xfb, 0xf7, 0xc8, 0xfa, 0x20, 0x68, ++ 0x2d, 0x21, 0x40, 0x30, 0x41, 0x73, 0xfb, 0xf7, 0x0a, 0xfb, 0x00, 0x28, 0x16, 0xd0, 0x00, 0x20, ++ 0xff, 0xf7, 0x45, 0xf9, 0x22, 0x68, 0x11, 0x46, 0x40, 0x31, 0xc8, 0x7d, 0x00, 0x28, 0xec, 0xd0, ++ 0x4d, 0x73, 0x61, 0x24, 0x48, 0x7f, 0xa3, 0x56, 0x98, 0x42, 0x00, 0xdd, 0x18, 0x46, 0x48, 0x77, ++ 0x91, 0x20, 0x10, 0x56, 0xfb, 0xf7, 0xd6, 0xfa, 0x00, 0x20, 0x70, 0xbd, 0x02, 0x20, 0x70, 0xbd, ++ 0xf8, 0xb5, 0x62, 0x48, 0x5a, 0x4c, 0x82, 0x7f, 0x20, 0x68, 0x01, 0x46, 0x40, 0x30, 0x83, 0x7a, ++ 0x23, 0x2b, 0x2c, 0xd0, 0x24, 0x2b, 0x39, 0xd0, 0xc3, 0x7c, 0x00, 0x2b, 0x02, 0xd1, 0x0b, 0x78, ++ 0x5b, 0x07, 0x01, 0xd4, 0x00, 0x20, 0xf8, 0xbd, 0x00, 0x25, 0x0b, 0x46, 0x4d, 0x84, 0x80, 0x33, ++ 0x1e, 0x79, 0x01, 0x2e, 0x00, 0xd0, 0x45, 0x75, 0x5b, 0x79, 0x00, 0x2b, 0x0f, 0xd0, 0x0f, 0x23, ++ 0xc3, 0x56, 0x9d, 0x1a, 0x00, 0x2d, 0x01, 0xdd, 0x5b, 0x1e, 0xc3, 0x73, 0x0f, 0x23, 0xc3, 0x56, ++ 0x9a, 0x1a, 0x01, 0xd5, 0x5b, 0x1c, 0xc3, 0x73, 0x01, 0x20, 0x48, 0x84, 0x53, 0xe0, 0x07, 0x20, ++ 0xc0, 0x43, 0xfb, 0xf7, 0xd3, 0xfc, 0x20, 0x68, 0x23, 0x21, 0x40, 0x30, 0x81, 0x72, 0xff, 0xf7, ++ 0x76, 0xff, 0x02, 0x28, 0xd7, 0xd0, 0x20, 0x68, 0x5d, 0x21, 0x09, 0x5c, 0xc1, 0x84, 0x08, 0x20, ++ 0xfb, 0xf7, 0xc4, 0xfc, 0x20, 0x68, 0x24, 0x21, 0x40, 0x30, 0x81, 0x72, 0xff, 0xf7, 0x67, 0xff, ++ 0x02, 0x28, 0xc8, 0xd0, 0x22, 0x68, 0x00, 0x26, 0x10, 0x46, 0x40, 0x30, 0x41, 0x7f, 0xd3, 0x8c, ++ 0xf6, 0x43, 0xc9, 0x1a, 0x09, 0xb2, 0xd1, 0x84, 0x00, 0x29, 0x10, 0xd0, 0x43, 0x7d, 0x00, 0x2b, ++ 0x31, 0xd0, 0x00, 0x29, 0x01, 0xdb, 0x01, 0x23, 0x00, 0xe0, 0x33, 0x46, 0x1c, 0x25, 0x45, 0x57, ++ 0x00, 0x2d, 0x01, 0xdb, 0x01, 0x25, 0x00, 0xe0, 0x35, 0x46, 0xab, 0x42, 0x23, 0xd0, 0x01, 0x23, ++ 0x53, 0x84, 0x00, 0x29, 0x01, 0xdb, 0x0d, 0x46, 0x00, 0xe0, 0x4d, 0x42, 0x1c, 0x23, 0xc3, 0x56, ++ 0x00, 0x2b, 0x01, 0xdb, 0x1f, 0x46, 0x00, 0xe0, 0x5f, 0x42, 0xbd, 0x42, 0x0a, 0xdd, 0x80, 0x32, ++ 0xd2, 0x78, 0x01, 0x2a, 0x1a, 0xd0, 0x0f, 0x22, 0x82, 0x56, 0x00, 0x2b, 0x00, 0xdb, 0x01, 0x26, ++ 0x92, 0x19, 0xc2, 0x73, 0x01, 0x77, 0x21, 0x68, 0x0f, 0x20, 0x40, 0x31, 0x08, 0x56, 0x18, 0x28, ++ 0x0f, 0xda, 0x18, 0x20, 0x10, 0xe0, 0x80, 0x32, 0xd2, 0x78, 0x01, 0x2a, 0x06, 0xd0, 0x0f, 0x22, ++ 0x82, 0x56, 0x00, 0x29, 0x00, 0xdb, 0x01, 0x26, 0x92, 0x1b, 0xea, 0xe7, 0x0f, 0x22, 0x82, 0x56, ++ 0xe7, 0xe7, 0x2c, 0x28, 0x01, 0xdd, 0x2c, 0x20, 0xc8, 0x73, 0x0f, 0x20, 0x08, 0x56, 0xfb, 0xf7, ++ 0xab, 0xfc, 0x20, 0x68, 0x01, 0x46, 0x40, 0x30, 0x42, 0x7d, 0x03, 0x46, 0x52, 0x1c, 0xd2, 0xb2, ++ 0x42, 0x75, 0x48, 0x8c, 0x01, 0x28, 0x03, 0xd0, 0x10, 0x2a, 0x01, 0xd2, 0x01, 0x20, 0x00, 0xe0, ++ 0x00, 0x20, 0x80, 0x31, 0x08, 0x71, 0x00, 0x20, 0x98, 0x72, 0xfb, 0xf7, 0x4f, 0xfc, 0x59, 0xe7, ++ 0x90, 0x00, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0xf3, 0x8f, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, ++ 0x40, 0xa0, 0x01, 0x00, 0x60, 0x60, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, ++ 0xfe, 0xb5, 0xfe, 0x4e, 0x30, 0x68, 0xff, 0x30, 0x01, 0x30, 0x45, 0x8e, 0x68, 0x46, 0x05, 0x80, ++ 0xac, 0x06, 0x30, 0x68, 0xa4, 0x0e, 0xfa, 0x4f, 0xc0, 0x19, 0x80, 0x88, 0x40, 0x07, 0xc0, 0x0f, ++ 0x0e, 0xd1, 0xe8, 0x0b, 0x0c, 0xd0, 0xb8, 0x05, 0x81, 0x8a, 0x04, 0x21, 0xc9, 0x43, 0x81, 0x82, ++ 0x31, 0x68, 0x04, 0x20, 0xc9, 0x19, 0x88, 0x80, 0x01, 0x21, 0x10, 0x20, 0x01, 0xf0, 0xf2, 0xfb, ++ 0xf0, 0x48, 0x01, 0x68, 0x08, 0x46, 0x80, 0x30, 0xc2, 0x7e, 0xa2, 0x42, 0x1b, 0xd0, 0x00, 0x23, ++ 0x01, 0x22, 0x00, 0x2c, 0x0e, 0xd0, 0x42, 0x31, 0x0d, 0x80, 0x02, 0x76, 0x03, 0x20, 0x00, 0x07, ++ 0x81, 0x8a, 0x83, 0x82, 0x30, 0x68, 0xc0, 0x19, 0x03, 0x80, 0x01, 0x23, 0x00, 0x92, 0x01, 0x94, ++ 0x03, 0x22, 0x04, 0xe0, 0xc2, 0x75, 0x01, 0x93, 0x00, 0x92, 0x01, 0x23, 0x04, 0x22, 0x09, 0x21, ++ 0x01, 0x20, 0x01, 0xf0, 0x59, 0xfb, 0xdf, 0x48, 0x00, 0x68, 0x80, 0x30, 0xc4, 0x76, 0xfe, 0xbd, ++ 0x7c, 0xb5, 0xda, 0x4c, 0x20, 0x68, 0xda, 0x49, 0x40, 0x39, 0x40, 0x18, 0xc0, 0x8c, 0x03, 0x23, ++ 0xc6, 0x07, 0xd8, 0x48, 0x1b, 0x07, 0x00, 0x68, 0x00, 0x21, 0x80, 0x30, 0x00, 0x2e, 0xd6, 0x4a, ++ 0xd3, 0x4d, 0x9e, 0x8a, 0x9a, 0x82, 0x0b, 0xd0, 0x23, 0x68, 0x02, 0x22, 0x5b, 0x19, 0x9a, 0x80, ++ 0x01, 0x22, 0x82, 0x75, 0xc2, 0x75, 0x00, 0x91, 0x01, 0x91, 0x13, 0x46, 0x0b, 0x21, 0x19, 0xe0, ++ 0x22, 0x68, 0x52, 0x19, 0x91, 0x80, 0x22, 0x68, 0x52, 0x19, 0x92, 0x88, 0x52, 0x07, 0xd2, 0x0f, ++ 0x0b, 0xd1, 0x9a, 0x8a, 0x99, 0x82, 0x22, 0x68, 0x52, 0x19, 0x52, 0x88, 0x23, 0x68, 0x52, 0x04, ++ 0x52, 0x0c, 0x5b, 0x19, 0x5a, 0x80, 0x81, 0x75, 0x41, 0x76, 0x00, 0x91, 0x01, 0x23, 0x04, 0x22, ++ 0x01, 0x91, 0x21, 0x21, 0x01, 0x20, 0x01, 0xf0, 0x17, 0xfb, 0x7c, 0xbd, 0x10, 0xb5, 0xbb, 0x48, ++ 0x00, 0x68, 0xbb, 0x49, 0x40, 0x39, 0x40, 0x18, 0x84, 0x8d, 0x60, 0x08, 0xc0, 0x07, 0x01, 0xd0, ++ 0xff, 0xf7, 0xb6, 0xff, 0xe0, 0x07, 0x01, 0xd0, 0xff, 0xf7, 0x6a, 0xff, 0x10, 0xbd, 0x7c, 0xb5, ++ 0xb4, 0x4e, 0x05, 0x46, 0x30, 0x68, 0x01, 0x24, 0x80, 0x30, 0xc0, 0x7d, 0x00, 0x28, 0x08, 0xd1, ++ 0x05, 0x20, 0x01, 0x90, 0x00, 0x23, 0x02, 0x22, 0x15, 0x21, 0x00, 0x94, 0x01, 0x20, 0x01, 0xf0, ++ 0xf3, 0xfa, 0x31, 0x68, 0x00, 0x20, 0x80, 0x31, 0x08, 0x76, 0x03, 0x22, 0xc8, 0x75, 0x12, 0x07, ++ 0x93, 0x8a, 0x90, 0x82, 0xa5, 0x48, 0x00, 0x68, 0xa5, 0x4a, 0x80, 0x18, 0x05, 0x80, 0x88, 0x7e, ++ 0x40, 0x1c, 0xc2, 0xb2, 0x8a, 0x76, 0xe8, 0xb2, 0x01, 0x2a, 0x00, 0x94, 0x01, 0x90, 0x06, 0xd0, ++ 0x00, 0x23, 0x02, 0x22, 0x0a, 0x21, 0x01, 0x20, 0x01, 0xf0, 0xd6, 0xfa, 0x7c, 0xbd, 0x00, 0x23, ++ 0x01, 0x22, 0x20, 0x21, 0xf7, 0xe7, 0x70, 0xb5, 0x98, 0x49, 0x08, 0x68, 0x98, 0x4a, 0x80, 0x18, ++ 0x43, 0x88, 0x01, 0x20, 0xc0, 0x03, 0x03, 0x43, 0x90, 0x05, 0x84, 0x8a, 0x01, 0x24, 0xe4, 0x43, ++ 0x84, 0x82, 0x0d, 0x68, 0x01, 0x24, 0xad, 0x18, 0xac, 0x80, 0x84, 0x8a, 0x00, 0x24, 0x84, 0x82, ++ 0x08, 0x68, 0x80, 0x18, 0x43, 0x80, 0x01, 0x21, 0x0c, 0x20, 0x01, 0xf0, 0x2b, 0xfb, 0x70, 0xbd, ++ 0x0f, 0xb4, 0x10, 0xb5, 0x03, 0x20, 0x00, 0x07, 0x81, 0x8a, 0xff, 0x21, 0x09, 0x02, 0x81, 0x82, ++ 0x6c, 0x46, 0xe1, 0x8e, 0xc9, 0x07, 0x0b, 0x0e, 0xa1, 0x8e, 0xc9, 0x07, 0x49, 0x0e, 0x0b, 0x43, ++ 0x61, 0x8e, 0xc9, 0x07, 0x89, 0x0e, 0x0b, 0x43, 0x21, 0x8e, 0xc9, 0x07, 0xc9, 0x0e, 0x0b, 0x43, ++ 0xe1, 0x8d, 0xc9, 0x07, 0x09, 0x0f, 0x0b, 0x43, 0xa1, 0x8d, 0xc9, 0x07, 0x49, 0x0f, 0x0b, 0x43, ++ 0x61, 0x8d, 0xc9, 0x07, 0x89, 0x0f, 0x0b, 0x43, 0x21, 0x8d, 0xc9, 0x07, 0xc9, 0x0f, 0x0b, 0x43, ++ 0x76, 0x49, 0x0c, 0x68, 0xd1, 0x22, 0x52, 0x02, 0xa4, 0x18, 0xe3, 0x86, 0x83, 0x8a, 0x23, 0x23, ++ 0x9b, 0x02, 0x83, 0x82, 0x6c, 0x46, 0x63, 0x8c, 0x24, 0x8c, 0xdb, 0x07, 0xe4, 0x07, 0x5b, 0x0c, ++ 0xa4, 0x0c, 0x23, 0x43, 0x6c, 0x46, 0xe4, 0x8b, 0xe4, 0x07, 0xe4, 0x0c, 0x23, 0x43, 0x6c, 0x46, ++ 0x64, 0x8b, 0xe4, 0x07, 0xa4, 0x0d, 0x23, 0x43, 0x6c, 0x46, 0x24, 0x8b, 0xe4, 0x07, 0xe4, 0x0d, ++ 0x23, 0x43, 0x6c, 0x46, 0xe4, 0x8a, 0xe4, 0x07, 0x24, 0x0e, 0x23, 0x43, 0x6c, 0x46, 0xa4, 0x8a, ++ 0xe4, 0x07, 0x64, 0x0e, 0x23, 0x43, 0x6c, 0x46, 0x64, 0x8a, 0xe4, 0x07, 0xa4, 0x0e, 0x23, 0x43, ++ 0x6c, 0x46, 0x24, 0x8a, 0xe4, 0x07, 0xe4, 0x0e, 0x23, 0x43, 0x6c, 0x46, 0xe4, 0x89, 0xe4, 0x07, ++ 0x24, 0x0f, 0x23, 0x43, 0x6c, 0x46, 0xa4, 0x89, 0xe4, 0x07, 0x64, 0x0f, 0x23, 0x43, 0x6c, 0x46, ++ 0x64, 0x89, 0xe4, 0x07, 0xa4, 0x0f, 0x23, 0x43, 0x6c, 0x46, 0x24, 0x89, 0xe4, 0x07, 0xe4, 0x0f, ++ 0x23, 0x43, 0x0c, 0x68, 0xa4, 0x18, 0x23, 0x87, 0x83, 0x8a, 0x01, 0x23, 0xdb, 0x03, 0x83, 0x82, ++ 0x10, 0xac, 0xa3, 0x8c, 0x64, 0x8c, 0xdb, 0x07, 0xe4, 0x07, 0x5b, 0x0c, 0xa4, 0x0c, 0x23, 0x43, ++ 0x10, 0xac, 0x24, 0x8c, 0xe4, 0x07, 0xe4, 0x0c, 0x23, 0x43, 0x10, 0xac, 0xe4, 0x8b, 0xe4, 0x07, ++ 0x24, 0x0d, 0x23, 0x43, 0x10, 0xac, 0xa4, 0x8b, 0xe4, 0x07, 0x64, 0x0d, 0x23, 0x43, 0x10, 0xac, ++ 0x64, 0x8b, 0xe4, 0x07, 0xa4, 0x0d, 0x23, 0x43, 0x10, 0xac, 0x24, 0x8b, 0xe4, 0x07, 0xe4, 0x0d, ++ 0x23, 0x43, 0x10, 0xac, 0xe4, 0x8a, 0xe4, 0x07, 0x24, 0x0e, 0x23, 0x43, 0x10, 0xac, 0xa4, 0x8a, ++ 0xe4, 0x07, 0x64, 0x0e, 0x23, 0x43, 0x10, 0xac, 0x64, 0x8a, 0xe4, 0x07, 0xa4, 0x0e, 0x23, 0x43, ++ 0x10, 0xac, 0x24, 0x8a, 0xe4, 0x07, 0xe4, 0x0e, 0x23, 0x43, 0x10, 0xac, 0xe4, 0x89, 0xe4, 0x07, ++ 0x24, 0x0f, 0x23, 0x43, 0x10, 0xac, 0xa4, 0x89, 0xe4, 0x07, 0x64, 0x0f, 0x23, 0x43, 0x10, 0xac, ++ 0x64, 0x89, 0xe4, 0x07, 0xa4, 0x0f, 0x23, 0x43, 0x10, 0xac, 0x24, 0x89, 0xe4, 0x07, 0xe4, 0x0f, ++ 0x23, 0x43, 0x0c, 0x68, 0xa4, 0x18, 0x63, 0x87, 0x83, 0x8a, 0x0f, 0x23, 0xdb, 0x43, 0x83, 0x82, ++ 0x10, 0xac, 0x60, 0x88, 0x23, 0x88, 0xc0, 0x07, 0xdb, 0x07, 0x00, 0x0f, 0x5b, 0x0f, 0x18, 0x43, ++ 0x6c, 0x46, 0xe3, 0x8f, 0x09, 0x68, 0xdb, 0x07, 0x9b, 0x0f, 0x18, 0x43, 0xa3, 0x8f, 0xdb, 0x07, ++ 0xdb, 0x0f, 0x18, 0x43, 0x89, 0x18, 0x88, 0x87, 0x10, 0xbc, 0x08, 0xbc, 0x00, 0x20, 0x04, 0xb0, ++ 0x18, 0x47, 0xff, 0xb5, 0xab, 0xb0, 0x1e, 0x00, 0x15, 0x46, 0x04, 0x46, 0x18, 0xd0, 0x00, 0x27, ++ 0x20, 0x21, 0x15, 0xa8, 0x01, 0xf0, 0xd6, 0xfa, 0x14, 0x21, 0x26, 0xa8, 0x01, 0xf0, 0xd2, 0xfa, ++ 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x24, 0x21, 0x1d, 0xa8, 0x01, 0xf0, 0xca, 0xfa, ++ 0x00, 0x2f, 0x0a, 0xd0, 0x12, 0x2d, 0x05, 0xdd, 0x06, 0x20, 0xad, 0x1f, 0xe9, 0xb2, 0x06, 0xe0, ++ 0x01, 0x27, 0xe5, 0xe7, 0xe9, 0xb2, 0x00, 0x20, 0x01, 0xe0, 0xe9, 0xb2, 0xf0, 0xb2, 0x2c, 0x9a, ++ 0xc3, 0x07, 0x12, 0x1b, 0x52, 0x1a, 0x12, 0x1a, 0xd5, 0xb2, 0x01, 0x22, 0x00, 0x2b, 0x01, 0xd1, ++ 0x06, 0x28, 0x01, 0xd3, 0x20, 0xab, 0x1a, 0x83, 0x02, 0x28, 0x07, 0xe0, 0x84, 0x00, 0x00, 0x20, ++ 0xc0, 0xa0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x20, 0xfd, 0xff, 0x00, 0x00, 0x01, 0xd3, 0x20, 0xab, ++ 0x1a, 0x84, 0x04, 0x28, 0x04, 0xd3, 0x20, 0xab, 0x9a, 0x84, 0x06, 0x28, 0x00, 0xd3, 0x9a, 0x83, ++ 0xfe, 0x48, 0x20, 0x40, 0x01, 0x28, 0x01, 0xd0, 0x0a, 0x2c, 0x01, 0xdb, 0x10, 0xa8, 0x82, 0x86, ++ 0x02, 0x2c, 0x01, 0xdb, 0x20, 0xa8, 0x82, 0x81, 0x04, 0x2c, 0x01, 0xdb, 0x20, 0xa8, 0xc2, 0x80, ++ 0x06, 0x2c, 0x01, 0xdb, 0x20, 0xa8, 0x02, 0x80, 0x08, 0x2c, 0x04, 0xdb, 0x10, 0xa8, 0x42, 0x87, ++ 0x0a, 0x2c, 0x00, 0xdb, 0x42, 0x85, 0xc8, 0x07, 0x01, 0xd1, 0x08, 0x29, 0x01, 0xd3, 0x10, 0xa8, ++ 0x82, 0x82, 0x02, 0x29, 0x01, 0xd3, 0x10, 0xa8, 0x82, 0x83, 0x04, 0x29, 0x01, 0xd3, 0x10, 0xa8, ++ 0x02, 0x84, 0x06, 0x29, 0x04, 0xd3, 0x10, 0xa8, 0x82, 0x84, 0x08, 0x29, 0x00, 0xd3, 0x02, 0x83, ++ 0x10, 0xa8, 0x44, 0x8d, 0x00, 0x2c, 0x1f, 0xd1, 0xc8, 0x07, 0x01, 0xd0, 0x08, 0x29, 0x19, 0xd2, ++ 0x12, 0x29, 0x17, 0xd2, 0x10, 0xa8, 0x40, 0x8f, 0x01, 0x28, 0x01, 0xd1, 0x0a, 0x29, 0x11, 0xd2, ++ 0x20, 0xa8, 0x00, 0x88, 0x01, 0x28, 0x01, 0xd1, 0x0c, 0x29, 0x0b, 0xd2, 0x20, 0xa8, 0xc0, 0x88, ++ 0x01, 0x28, 0x01, 0xd1, 0x0e, 0x29, 0x05, 0xd2, 0x20, 0xa8, 0x80, 0x89, 0x01, 0x28, 0x03, 0xd1, ++ 0x10, 0x29, 0x01, 0xd3, 0x10, 0xa8, 0x82, 0x85, 0x10, 0xab, 0x58, 0x8f, 0x03, 0x90, 0x00, 0x28, ++ 0x02, 0xd1, 0x0a, 0x29, 0x00, 0xd3, 0x9a, 0x87, 0x20, 0xa8, 0x00, 0x88, 0x84, 0x46, 0x00, 0x28, ++ 0x03, 0xd1, 0x0c, 0x29, 0x01, 0xd3, 0x20, 0xa8, 0x42, 0x80, 0x20, 0xa8, 0xc7, 0x88, 0x00, 0x2f, ++ 0x02, 0xd1, 0x0e, 0x29, 0x00, 0xd3, 0x02, 0x81, 0x86, 0x89, 0x00, 0x2e, 0x02, 0xd1, 0x10, 0x29, ++ 0x00, 0xd3, 0xc2, 0x81, 0x9b, 0x8e, 0x00, 0x2b, 0x15, 0xd1, 0x12, 0x29, 0x11, 0xd2, 0x03, 0x98, ++ 0x01, 0x28, 0x01, 0xd1, 0x0a, 0x29, 0x0c, 0xd2, 0x60, 0x46, 0x01, 0x28, 0x01, 0xd1, 0x0c, 0x29, ++ 0x07, 0xd2, 0x01, 0x2f, 0x01, 0xd1, 0x0e, 0x29, 0x03, 0xd2, 0x01, 0x2e, 0x03, 0xd1, 0x10, 0x29, ++ 0x01, 0xd3, 0x10, 0xa8, 0xc2, 0x86, 0x00, 0x2d, 0x7e, 0xd0, 0x6d, 0x1e, 0xe8, 0xb2, 0xc1, 0x07, ++ 0x01, 0xd0, 0x69, 0x46, 0x0a, 0x80, 0x40, 0x08, 0xf6, 0xd0, 0xc1, 0x07, 0x05, 0xd0, 0x40, 0x1e, ++ 0x69, 0x46, 0x00, 0x06, 0x4a, 0x80, 0x00, 0x0e, 0xee, 0xd0, 0x69, 0x46, 0x89, 0x88, 0x00, 0x29, ++ 0x05, 0xd1, 0x80, 0x1e, 0x69, 0x46, 0x00, 0x06, 0x8a, 0x80, 0x00, 0x0e, 0xe4, 0xd0, 0x69, 0x46, ++ 0xc9, 0x88, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x69, 0x46, 0x00, 0x06, 0xca, 0x80, 0x00, 0x0e, ++ 0xda, 0xd0, 0x69, 0x46, 0x49, 0x88, 0x00, 0x29, 0x6f, 0xd1, 0x20, 0xa9, 0xc9, 0x8b, 0x00, 0x29, ++ 0x0d, 0xd1, 0x20, 0xa9, 0x89, 0x8b, 0x00, 0x29, 0x09, 0xd1, 0x69, 0x46, 0x4a, 0x80, 0x80, 0x1e, ++ 0x20, 0xa9, 0x00, 0x06, 0xca, 0x83, 0x00, 0x0e, 0xc6, 0xd0, 0x00, 0x2a, 0x5d, 0xd1, 0x20, 0xa9, ++ 0x49, 0x8b, 0x00, 0x29, 0x0d, 0xd1, 0x20, 0xa9, 0x09, 0x8b, 0x00, 0x29, 0x09, 0xd1, 0x69, 0x46, ++ 0x4a, 0x80, 0x80, 0x1e, 0x20, 0xa9, 0x00, 0x06, 0x4a, 0x83, 0x00, 0x0e, 0xb4, 0xd0, 0x00, 0x2a, ++ 0x4b, 0xd1, 0x10, 0xa9, 0x49, 0x8b, 0x00, 0x29, 0x0d, 0xd1, 0x10, 0xa9, 0x09, 0x8b, 0x00, 0x29, ++ 0x09, 0xd1, 0x69, 0x46, 0x4a, 0x80, 0x80, 0x1e, 0x10, 0xa9, 0x00, 0x06, 0x4a, 0x83, 0x00, 0x0e, ++ 0xa2, 0xd0, 0x00, 0x2a, 0x39, 0xd1, 0x10, 0xa9, 0xc9, 0x8a, 0x00, 0x29, 0x0d, 0xd1, 0x10, 0xa9, ++ 0x89, 0x8a, 0x00, 0x29, 0x09, 0xd1, 0x69, 0x46, 0x4a, 0x80, 0x80, 0x1e, 0x10, 0xa9, 0x00, 0x06, ++ 0xca, 0x82, 0x00, 0x0e, 0x90, 0xd0, 0x00, 0x2a, 0x27, 0xd1, 0x10, 0xa9, 0x09, 0x8f, 0x00, 0x29, ++ 0x11, 0xd1, 0x00, 0x2b, 0x0f, 0xd1, 0x10, 0xa9, 0xc9, 0x8e, 0x00, 0x29, 0x0b, 0xd1, 0x69, 0x46, ++ 0x4a, 0x80, 0x10, 0xa9, 0x0a, 0x87, 0x00, 0xe0, 0x1e, 0xe1, 0x80, 0x1e, 0x00, 0x06, 0x00, 0x0e, ++ 0x8a, 0xd0, 0x00, 0x2a, 0x11, 0xd1, 0x10, 0xa9, 0xc9, 0x8d, 0x00, 0x29, 0x0d, 0xd1, 0x00, 0x2c, ++ 0x0b, 0xd1, 0x10, 0xa9, 0x89, 0x8d, 0x00, 0x29, 0x07, 0xd1, 0x69, 0x46, 0x4a, 0x80, 0x80, 0x1e, ++ 0x10, 0xa9, 0x00, 0x06, 0xca, 0x85, 0x00, 0x0e, 0x8a, 0xd0, 0x20, 0xa9, 0xc9, 0x8c, 0x00, 0x29, ++ 0x09, 0xd1, 0x20, 0xa9, 0x89, 0x8c, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x20, 0xa9, 0x00, 0x06, ++ 0xca, 0x84, 0x00, 0x0e, 0x90, 0xd0, 0x20, 0xa9, 0x49, 0x8c, 0x00, 0x29, 0x09, 0xd1, 0x20, 0xa9, ++ 0x09, 0x8c, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x20, 0xa9, 0x00, 0x06, 0x4a, 0x84, 0x00, 0x0e, ++ 0x94, 0xd0, 0x10, 0xa9, 0xc9, 0x8c, 0x00, 0x29, 0x09, 0xd1, 0x10, 0xa9, 0x89, 0x8c, 0x00, 0x29, ++ 0x05, 0xd1, 0x80, 0x1e, 0x10, 0xa9, 0x00, 0x06, 0xca, 0x84, 0x00, 0x0e, 0x86, 0xd0, 0x10, 0xa9, ++ 0x49, 0x8c, 0x00, 0x29, 0x09, 0xd1, 0x10, 0xa9, 0x09, 0x8c, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, ++ 0x10, 0xa9, 0x00, 0x06, 0x4a, 0x84, 0x00, 0x0e, 0x8a, 0xd0, 0x10, 0xa9, 0xc9, 0x8b, 0x00, 0x29, ++ 0x09, 0xd1, 0x10, 0xa9, 0x89, 0x8b, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x10, 0xa9, 0x00, 0x06, ++ 0xca, 0x83, 0x00, 0x0e, 0x8e, 0xd0, 0x20, 0xa9, 0x09, 0x8a, 0x00, 0x29, 0x0b, 0xd1, 0x00, 0x2e, ++ 0x09, 0xd1, 0x20, 0xa9, 0xc9, 0x89, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x20, 0xa9, 0x00, 0x06, ++ 0x0a, 0x82, 0x00, 0x0e, 0x94, 0xd0, 0x20, 0xa9, 0x49, 0x89, 0x00, 0x29, 0x0b, 0xd1, 0x00, 0x2f, ++ 0x09, 0xd1, 0x20, 0xa9, 0x09, 0x89, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x20, 0xa9, 0x00, 0x06, ++ 0x4a, 0x81, 0x00, 0x0e, 0x84, 0xd0, 0x20, 0xa9, 0x89, 0x88, 0x00, 0x29, 0x0c, 0xd1, 0x61, 0x46, ++ 0x00, 0x29, 0x09, 0xd1, 0x20, 0xa9, 0x49, 0x88, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, 0x20, 0xa9, ++ 0x00, 0x06, 0x8a, 0x80, 0x00, 0x0e, 0x87, 0xd0, 0x10, 0xa9, 0xc9, 0x8f, 0x00, 0x29, 0x0c, 0xd1, ++ 0x03, 0x99, 0x00, 0x29, 0x09, 0xd1, 0x10, 0xa9, 0x89, 0x8f, 0x00, 0x29, 0x05, 0xd1, 0x80, 0x1e, ++ 0x10, 0xa9, 0x00, 0x06, 0xca, 0x87, 0x00, 0x0e, 0x7e, 0xd0, 0x20, 0xa9, 0xc9, 0x8b, 0x00, 0x29, ++ 0x3a, 0xd1, 0x20, 0xa9, 0x89, 0x8b, 0x00, 0x29, 0x36, 0xd1, 0x20, 0xad, 0x6d, 0x8b, 0x00, 0x2d, ++ 0x0e, 0xd1, 0x20, 0xad, 0x2d, 0x8b, 0x00, 0x2d, 0x0a, 0xd1, 0x20, 0xad, 0x80, 0x1e, 0xea, 0x83, ++ 0x00, 0x06, 0x6a, 0x83, 0x00, 0x0e, 0x67, 0xd0, 0x00, 0x2a, 0x25, 0xd1, 0x00, 0x29, 0x23, 0xd1, ++ 0x10, 0xad, 0x6d, 0x8b, 0x00, 0x2d, 0x0f, 0xd1, 0x10, 0xad, 0x2d, 0x8b, 0x00, 0x2d, 0x0b, 0xd1, ++ 0x20, 0xad, 0xea, 0x83, 0x80, 0x1e, 0x10, 0xad, 0x00, 0x06, 0x6a, 0x83, 0x00, 0x0e, 0x53, 0xd0, ++ 0x00, 0x2a, 0x11, 0xd1, 0x00, 0x29, 0x0f, 0xd1, 0x10, 0xa9, 0xc9, 0x8a, 0x00, 0x29, 0x0b, 0xd1, ++ 0x10, 0xa9, 0x89, 0x8a, 0x00, 0x29, 0x07, 0xd1, 0x20, 0xa9, 0xca, 0x83, 0x80, 0x1e, 0x10, 0xa9, ++ 0x00, 0x06, 0xca, 0x82, 0x00, 0x0e, 0x3f, 0xd0, 0x20, 0xa9, 0x49, 0x8b, 0x00, 0x29, 0x2a, 0xd1, ++ 0x20, 0xa9, 0x09, 0x8b, 0x00, 0x29, 0x26, 0xd1, 0x10, 0xad, 0x6d, 0x8b, 0x00, 0x2d, 0x12, 0xd1, ++ 0x10, 0xad, 0x2d, 0x8b, 0x00, 0x2d, 0x0e, 0xd1, 0x20, 0xad, 0x01, 0xe0, 0x01, 0x00, 0x00, 0x80, ++ 0x6a, 0x83, 0x80, 0x1e, 0x10, 0xad, 0x00, 0x06, 0x6a, 0x83, 0x00, 0x0e, 0x24, 0xd0, 0x00, 0x2a, ++ 0x11, 0xd1, 0x00, 0x29, 0x0f, 0xd1, 0x10, 0xa9, 0xc9, 0x8a, 0x00, 0x29, 0x0b, 0xd1, 0x10, 0xa9, ++ 0x89, 0x8a, 0x00, 0x29, 0x07, 0xd1, 0x20, 0xa9, 0x4a, 0x83, 0x80, 0x1e, 0x10, 0xa9, 0x00, 0x06, ++ 0xca, 0x82, 0x00, 0x0e, 0x10, 0xd0, 0x10, 0xa9, 0x49, 0x8b, 0x00, 0x29, 0x14, 0xd1, 0x10, 0xa9, ++ 0x09, 0x8b, 0x00, 0x29, 0x10, 0xd1, 0x10, 0xa9, 0xc9, 0x8a, 0x00, 0x29, 0x0c, 0xd1, 0x10, 0xa9, ++ 0x89, 0x8a, 0x00, 0x29, 0x08, 0xd1, 0x00, 0xe0, 0x84, 0xe0, 0x10, 0xa9, 0x80, 0x1e, 0x4a, 0x83, ++ 0x00, 0x06, 0xca, 0x82, 0x00, 0x0e, 0x7d, 0xd0, 0x20, 0xa9, 0xc9, 0x8b, 0x00, 0x29, 0x2b, 0xd1, ++ 0x20, 0xa9, 0x89, 0x8b, 0x00, 0x29, 0x27, 0xd1, 0x10, 0xad, 0x2d, 0x8f, 0x00, 0x2d, 0x11, 0xd1, ++ 0x00, 0x2b, 0x0f, 0xd1, 0x10, 0xad, 0xed, 0x8e, 0x00, 0x2d, 0x0b, 0xd1, 0x20, 0xad, 0xea, 0x83, ++ 0x80, 0x1e, 0x10, 0xad, 0x00, 0x06, 0x2a, 0x87, 0x00, 0x0e, 0x63, 0xd0, 0x00, 0x2a, 0x13, 0xd1, ++ 0x00, 0x29, 0x11, 0xd1, 0x10, 0xa9, 0xc9, 0x8d, 0x00, 0x29, 0x0d, 0xd1, 0x00, 0x2c, 0x0b, 0xd1, ++ 0x10, 0xa9, 0x89, 0x8d, 0x00, 0x29, 0x07, 0xd1, 0x20, 0xa9, 0xca, 0x83, 0x80, 0x1e, 0x10, 0xa9, ++ 0x00, 0x06, 0xca, 0x85, 0x00, 0x0e, 0x4d, 0xd0, 0x20, 0xa9, 0x49, 0x8b, 0x00, 0x29, 0x2b, 0xd1, ++ 0x20, 0xa9, 0x09, 0x8b, 0x00, 0x29, 0x27, 0xd1, 0x10, 0xad, 0x2d, 0x8f, 0x00, 0x2d, 0x11, 0xd1, ++ 0x00, 0x2b, 0x0f, 0xd1, 0x10, 0xad, 0xed, 0x8e, 0x00, 0x2d, 0x0b, 0xd1, 0x20, 0xad, 0x6a, 0x83, ++ 0x80, 0x1e, 0x10, 0xad, 0x00, 0x06, 0x2a, 0x87, 0x00, 0x0e, 0x33, 0xd0, 0x00, 0x2a, 0x13, 0xd1, ++ 0x00, 0x29, 0x11, 0xd1, 0x10, 0xa9, 0xc9, 0x8d, 0x00, 0x29, 0x0d, 0xd1, 0x00, 0x2c, 0x0b, 0xd1, ++ 0x10, 0xa9, 0x89, 0x8d, 0x00, 0x29, 0x07, 0xd1, 0x20, 0xa9, 0x4a, 0x83, 0x80, 0x1e, 0x10, 0xa9, ++ 0x00, 0x06, 0xca, 0x85, 0x00, 0x0e, 0x74, 0xd0, 0x10, 0xa9, 0x49, 0x8b, 0x00, 0x29, 0x2b, 0xd1, ++ 0x10, 0xa9, 0x09, 0x8b, 0x00, 0x29, 0x27, 0xd1, 0x10, 0xad, 0x2d, 0x8f, 0x00, 0x2d, 0x10, 0xd1, ++ 0x00, 0x2b, 0x0e, 0xd1, 0x10, 0xad, 0xed, 0x8e, 0x00, 0x2d, 0x0a, 0xd1, 0x10, 0xad, 0x80, 0x1e, ++ 0x6a, 0x83, 0x00, 0x06, 0x2a, 0x87, 0x00, 0x0e, 0x5b, 0xd0, 0x00, 0x2a, 0x14, 0xd1, 0x00, 0x29, ++ 0x12, 0xd1, 0x00, 0xe0, 0x55, 0xe0, 0x10, 0xa9, 0xc9, 0x8d, 0x00, 0x29, 0x0c, 0xd1, 0x00, 0x2c, ++ 0x0a, 0xd1, 0x10, 0xa9, 0x89, 0x8d, 0x00, 0x29, 0x06, 0xd1, 0x10, 0xa9, 0x80, 0x1e, 0x4a, 0x83, ++ 0x00, 0x06, 0xca, 0x85, 0x00, 0x0e, 0x44, 0xd0, 0x10, 0xa9, 0xc9, 0x8a, 0x00, 0x29, 0x29, 0xd1, ++ 0x10, 0xa9, 0x89, 0x8a, 0x00, 0x29, 0x25, 0xd1, 0x10, 0xad, 0x2d, 0x8f, 0x00, 0x2d, 0x10, 0xd1, ++ 0x00, 0x2b, 0x0e, 0xd1, 0x10, 0xad, 0xed, 0x8e, 0x00, 0x2d, 0x0a, 0xd1, 0x10, 0xad, 0x80, 0x1e, ++ 0xea, 0x82, 0x00, 0x06, 0x2a, 0x87, 0x00, 0x0e, 0x2b, 0xd0, 0x00, 0x2a, 0x12, 0xd1, 0x00, 0x29, ++ 0x10, 0xd1, 0x10, 0xa9, 0xc9, 0x8d, 0x00, 0x29, 0x0c, 0xd1, 0x00, 0x2c, 0x0a, 0xd1, 0x10, 0xa9, ++ 0x89, 0x8d, 0x00, 0x29, 0x06, 0xd1, 0x10, 0xa9, 0x80, 0x1e, 0xca, 0x82, 0x00, 0x06, 0xca, 0x85, ++ 0x00, 0x0e, 0x16, 0xd0, 0x10, 0xa8, 0x00, 0x8f, 0x00, 0x28, 0x12, 0xd1, 0x00, 0x2b, 0x10, 0xd1, ++ 0x10, 0xa8, 0xc0, 0x8e, 0x00, 0x28, 0x0c, 0xd1, 0x10, 0xa8, 0xc0, 0x8d, 0x00, 0x28, 0x08, 0xd1, ++ 0x00, 0x2c, 0x06, 0xd1, 0x10, 0xa8, 0x80, 0x8d, 0x00, 0x28, 0x02, 0xd1, 0x10, 0xa8, 0x02, 0x87, ++ 0xc2, 0x85, 0x22, 0x22, 0x1d, 0xa9, 0x0c, 0xa8, 0xf9, 0xf7, 0x1c, 0xfc, 0x6b, 0x46, 0x07, 0xcb, ++ 0x09, 0xab, 0x07, 0xc3, 0x14, 0x22, 0x26, 0xa9, 0x04, 0xa8, 0xf9, 0xf7, 0x13, 0xfc, 0x19, 0xac, ++ 0x0f, 0xcc, 0x6c, 0x46, 0x0f, 0xc4, 0x15, 0xac, 0x0f, 0xcc, 0xff, 0xf7, 0xb9, 0xfb, 0x2f, 0xb0, ++ 0xf0, 0xbd, 0xf8, 0xb5, 0x03, 0x24, 0x24, 0x07, 0xa5, 0x8a, 0xca, 0x4d, 0xa5, 0x82, 0x06, 0x07, ++ 0x36, 0x0f, 0xd5, 0x06, 0xed, 0x0c, 0x2e, 0x43, 0xc7, 0x4d, 0x2f, 0x68, 0xc7, 0x4d, 0x7f, 0x19, ++ 0x3e, 0x81, 0xa6, 0x8a, 0x3f, 0x26, 0xf6, 0x43, 0xa6, 0x82, 0xc3, 0x4f, 0x8e, 0x06, 0x3f, 0x68, ++ 0xb6, 0x0e, 0x7d, 0x19, 0x6e, 0x81, 0xa5, 0x8a, 0xc1, 0x4d, 0xa5, 0x82, 0x00, 0x2b, 0x05, 0xd0, ++ 0x00, 0x24, 0x65, 0x03, 0x00, 0x28, 0x03, 0xdd, 0x01, 0x24, 0x02, 0xe0, 0x01, 0x24, 0xf8, 0xe7, ++ 0x00, 0x24, 0x24, 0x03, 0x25, 0x43, 0x00, 0x2a, 0x01, 0xdd, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, ++ 0xe4, 0x02, 0x25, 0x43, 0x00, 0x2b, 0x01, 0xdd, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, 0xa4, 0x02, ++ 0x25, 0x43, 0xb1, 0x4c, 0x26, 0x68, 0xb1, 0x4f, 0x80, 0x37, 0xf6, 0x19, 0x75, 0x81, 0x03, 0x25, ++ 0x2d, 0x07, 0xae, 0x8a, 0x0f, 0x26, 0xf6, 0x43, 0xae, 0x82, 0x1d, 0x07, 0x24, 0x68, 0x2d, 0x0f, ++ 0xd1, 0x26, 0x76, 0x02, 0xa4, 0x19, 0x25, 0x84, 0xff, 0xf7, 0x4b, 0xfc, 0xf8, 0xbd, 0xfe, 0xb5, ++ 0x00, 0x20, 0x69, 0x46, 0x08, 0x81, 0xa4, 0x48, 0x01, 0x68, 0xa4, 0x4a, 0x40, 0x3a, 0x89, 0x18, ++ 0x49, 0x8d, 0x00, 0x68, 0xff, 0x30, 0x01, 0x30, 0x00, 0x8e, 0x69, 0x46, 0x08, 0x80, 0x00, 0x20, ++ 0x0d, 0x88, 0x84, 0x46, 0xa8, 0x04, 0x0c, 0x27, 0x30, 0x26, 0x00, 0x28, 0x0a, 0xda, 0x00, 0x20, ++ 0x02, 0x46, 0x3c, 0x21, 0x63, 0x46, 0xff, 0xf7, 0x94, 0xff, 0xb7, 0x43, 0x10, 0x37, 0xb8, 0x08, ++ 0x80, 0x00, 0x10, 0xe0, 0xe8, 0x04, 0x12, 0xd5, 0x96, 0x4b, 0x17, 0x20, 0x18, 0x22, 0x16, 0x21, ++ 0x18, 0x56, 0x9a, 0x56, 0x59, 0x56, 0x63, 0x46, 0xff, 0xf7, 0x83, 0xff, 0x04, 0x20, 0xb0, 0x43, ++ 0x10, 0x30, 0x80, 0x08, 0x80, 0x00, 0x69, 0x46, 0x40, 0x1c, 0x08, 0x81, 0xfe, 0xe0, 0xa8, 0x06, ++ 0xfc, 0xd0, 0x89, 0x4a, 0x10, 0x68, 0x89, 0x4b, 0xc0, 0x18, 0x40, 0x89, 0x81, 0x06, 0x10, 0x68, ++ 0x89, 0x0e, 0xc0, 0x18, 0x00, 0x89, 0x12, 0x68, 0x00, 0x07, 0x00, 0x0f, 0xd2, 0x18, 0x12, 0x89, ++ 0x2b, 0x07, 0xd2, 0x04, 0xd2, 0x0e, 0x00, 0x24, 0x9b, 0x0f, 0x01, 0x2b, 0x02, 0xd0, 0x02, 0x2b, ++ 0x18, 0xd0, 0x31, 0xe0, 0x49, 0x1c, 0x21, 0x29, 0x07, 0xdb, 0x3c, 0x29, 0x03, 0xdc, 0x43, 0x18, ++ 0x9b, 0x18, 0x3c, 0x2b, 0x01, 0xdd, 0x49, 0x1e, 0x17, 0xe0, 0x01, 0x24, 0x4b, 0x1c, 0x21, 0x2b, ++ 0x06, 0xdb, 0x3c, 0x2b, 0x1e, 0xdc, 0x43, 0x18, 0x9b, 0x18, 0x5b, 0x1c, 0x3c, 0x2b, 0x19, 0xdc, ++ 0x04, 0x27, 0x17, 0xe0, 0x08, 0x27, 0x49, 0x1e, 0x3c, 0x29, 0x08, 0xdc, 0x21, 0x29, 0x03, 0xdb, ++ 0x0b, 0x1a, 0x9b, 0x1a, 0x06, 0x2b, 0x02, 0xda, 0x49, 0x1c, 0x49, 0xb2, 0x0a, 0xe0, 0x01, 0x24, ++ 0x4b, 0x1e, 0x3c, 0x2b, 0xec, 0xdc, 0x21, 0x2b, 0x04, 0xdb, 0x0b, 0x1a, 0x9b, 0x1a, 0x5b, 0x1e, ++ 0x06, 0x2b, 0xe5, 0xda, 0x6b, 0x46, 0x1f, 0x81, 0xab, 0x06, 0x9b, 0x0f, 0x01, 0x2b, 0x02, 0xd0, ++ 0x02, 0x2b, 0x1a, 0xd0, 0x47, 0xe0, 0x52, 0x1e, 0x18, 0x2a, 0x07, 0xdc, 0x00, 0x2a, 0x05, 0xda, ++ 0x6f, 0x46, 0x3b, 0x89, 0x33, 0x43, 0x3b, 0x81, 0x52, 0x1c, 0x3c, 0xe0, 0x01, 0x24, 0x53, 0x1e, ++ 0x18, 0x2b, 0x05, 0xdc, 0x00, 0x2b, 0x03, 0xda, 0x6f, 0x46, 0x3b, 0x89, 0x33, 0x43, 0x31, 0xe0, ++ 0x6f, 0x46, 0x3b, 0x89, 0xb3, 0x43, 0x10, 0x33, 0x2c, 0xe0, 0x52, 0x1c, 0x13, 0xd4, 0x18, 0x2a, ++ 0x0a, 0xdc, 0x43, 0x18, 0x9b, 0x18, 0x3c, 0x2b, 0x06, 0xdc, 0x0b, 0x1a, 0x9b, 0x1a, 0x06, 0x2b, ++ 0x02, 0xdb, 0x83, 0x18, 0x18, 0x2b, 0x06, 0xdd, 0x6f, 0x46, 0x3b, 0x89, 0xb3, 0x43, 0x20, 0x33, ++ 0x3b, 0x81, 0x52, 0x1e, 0x17, 0xe0, 0x01, 0x24, 0x53, 0x1c, 0xe1, 0xd4, 0x18, 0x2b, 0x0d, 0xdc, ++ 0x43, 0x18, 0x9b, 0x18, 0x5b, 0x1c, 0x3c, 0x2b, 0x08, 0xdc, 0x0b, 0x1a, 0x9b, 0x1a, 0x5b, 0x1e, ++ 0x06, 0x2b, 0x03, 0xdb, 0x83, 0x18, 0x5b, 0x1c, 0x18, 0x2b, 0xd1, 0xdd, 0x6f, 0x46, 0x3b, 0x89, ++ 0xb3, 0x43, 0x20, 0x33, 0x3b, 0x81, 0xab, 0x07, 0x9b, 0x0f, 0x01, 0x2b, 0x02, 0xd0, 0x02, 0x2b, ++ 0x1d, 0xd0, 0x4c, 0xe0, 0x03, 0x26, 0x40, 0x1e, 0x0a, 0x28, 0x07, 0xdc, 0x00, 0x28, 0x05, 0xda, ++ 0x6f, 0x46, 0x3b, 0x89, 0x33, 0x43, 0x3b, 0x81, 0x40, 0x1c, 0x40, 0xe0, 0x01, 0x24, 0x43, 0x1e, ++ 0x0a, 0x2b, 0x06, 0xdc, 0x00, 0x2b, 0x04, 0xda, 0x6f, 0x46, 0x3b, 0x89, 0x33, 0x43, 0x3b, 0x81, ++ 0x35, 0xe0, 0x6e, 0x46, 0x33, 0x89, 0x9b, 0x08, 0x9b, 0x00, 0x5b, 0x1c, 0x2e, 0xe0, 0x40, 0x1c, ++ 0x14, 0xd4, 0x0a, 0x28, 0x0a, 0xdc, 0x43, 0x18, 0x9b, 0x18, 0x3c, 0x2b, 0x06, 0xdc, 0x0b, 0x1a, ++ 0x9b, 0x1a, 0x06, 0x2b, 0x02, 0xdb, 0x83, 0x18, 0x18, 0x2b, 0x07, 0xdd, 0x6e, 0x46, 0x33, 0x89, ++ 0x9b, 0x08, 0x9b, 0x00, 0x9b, 0x1c, 0x33, 0x81, 0x40, 0x1e, 0x18, 0xe0, 0x01, 0x24, 0x43, 0x1c, ++ 0xdf, 0xd4, 0x0a, 0x2b, 0x0d, 0xdc, 0x43, 0x18, 0x9b, 0x18, 0x5b, 0x1c, 0x3c, 0x2b, 0x08, 0xdc, ++ 0x0b, 0x1a, 0x9b, 0x1a, 0x5b, 0x1e, 0x06, 0x2b, 0x03, 0xdb, 0x83, 0x18, 0x5b, 0x1c, 0x18, 0x2b, ++ 0xcf, 0xdd, 0x6e, 0x46, 0x33, 0x89, 0x9b, 0x08, 0x9b, 0x00, 0x9b, 0x1c, 0x33, 0x81, 0x63, 0x46, ++ 0xff, 0xf7, 0x87, 0xfe, 0x00, 0x2c, 0x09, 0xd0, 0xa9, 0x06, 0x89, 0x0e, 0x01, 0x20, 0x01, 0x91, ++ 0x03, 0x46, 0x04, 0x22, 0x00, 0x90, 0x1f, 0x21, 0x00, 0xf0, 0xe6, 0xfc, 0x0a, 0x4a, 0x10, 0x68, ++ 0x0a, 0x4b, 0xc0, 0x18, 0x80, 0x89, 0xc1, 0x03, 0x68, 0x46, 0x00, 0x89, 0x40, 0x04, 0x40, 0x0c, ++ 0x08, 0x43, 0x99, 0x05, 0x8c, 0x8a, 0x00, 0x24, 0x8c, 0x82, 0x11, 0x68, 0xc9, 0x18, 0x48, 0x80, ++ 0xfe, 0xbd, 0x00, 0x00, 0xf0, 0xe0, 0x00, 0x00, 0x84, 0x00, 0x00, 0x20, 0xc0, 0xa0, 0x01, 0x00, ++ 0xff, 0xc3, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0xf0, 0xb5, 0xf9, 0x4a, 0x3e, 0x23, 0x11, 0x88, ++ 0x00, 0x25, 0x99, 0x43, 0xf4, 0x4c, 0xf5, 0x4e, 0x03, 0x00, 0x00, 0xf0, 0x09, 0xfe, 0x09, 0x06, ++ 0x37, 0x68, 0x99, 0xca, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0x00, 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, ++ 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0xef, 0x4f, 0x48, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, ++ 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0xeb, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, ++ 0xe9, 0x4b, 0x83, 0x82, 0xe7, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, ++ 0xdb, 0x43, 0x83, 0x82, 0xe3, 0x4f, 0x04, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, ++ 0x86, 0x82, 0xe0, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, 0xdd, 0x4b, ++ 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x58, 0x86, 0x2e, 0x31, 0x8c, 0xe1, 0x03, 0x20, 0x00, 0x07, ++ 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0xd6, 0x4f, 0x28, 0x23, 0x3f, 0x68, 0x3f, 0x19, ++ 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0xd2, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, ++ 0x83, 0x8a, 0xd1, 0x4b, 0x83, 0x82, 0xcf, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, ++ 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0xcb, 0x4f, 0x04, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, ++ 0x83, 0x8a, 0x86, 0x82, 0xc7, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, ++ 0xc4, 0x48, 0x01, 0x23, 0x00, 0x68, 0x00, 0x19, 0x43, 0x86, 0x89, 0x1d, 0x5b, 0xe1, 0x03, 0x20, ++ 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0xbe, 0x4f, 0x2a, 0x23, 0x3f, 0x68, ++ 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0xba, 0x4b, 0x1b, 0x68, 0x1b, 0x19, ++ 0xdd, 0x85, 0x83, 0x8a, 0xb8, 0x4b, 0x83, 0x82, 0xb6, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x9d, 0x85, ++ 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0xb2, 0x4f, 0x04, 0x23, 0x3f, 0x68, 0x3f, 0x19, ++ 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0xaf, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, 0x83, 0x8a, ++ 0x86, 0x82, 0xac, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x58, 0x86, 0x08, 0x31, 0x2a, 0xe1, ++ 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0xa5, 0x4f, 0x34, 0x23, ++ 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0xa1, 0x4b, 0x1b, 0x68, ++ 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0xa0, 0x4b, 0x83, 0x82, 0x9e, 0x4b, 0x1b, 0x68, 0x1b, 0x19, ++ 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x9a, 0x4f, 0x04, 0x23, 0x3f, 0x68, ++ 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x96, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, ++ 0x83, 0x8a, 0x86, 0x82, 0x93, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x58, 0x86, 0x16, 0x31, ++ 0xf9, 0xe0, 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0x8d, 0x4f, ++ 0x3c, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0x89, 0x4b, ++ 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0x87, 0x4b, 0x83, 0x82, 0x85, 0x4b, 0x1b, 0x68, ++ 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x81, 0x4f, 0x04, 0x23, ++ 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x7e, 0x4b, 0x1b, 0x68, 0x1b, 0x19, ++ 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x7b, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x04, 0xe0, ++ 0xca, 0xe0, 0x98, 0xe0, 0x66, 0xe0, 0x34, 0xe0, 0x02, 0xe0, 0x58, 0x86, 0x20, 0x31, 0xc2, 0xe0, ++ 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0x71, 0x4f, 0x40, 0x23, ++ 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0x6d, 0x4b, 0x1b, 0x68, ++ 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0x6c, 0x4b, 0x83, 0x82, 0x6a, 0x4b, 0x1b, 0x68, 0x1b, 0x19, ++ 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x66, 0x4f, 0x04, 0x23, 0x3f, 0x68, ++ 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x62, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, ++ 0x83, 0x8a, 0x86, 0x82, 0x5f, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x58, 0x86, 0x24, 0x31, ++ 0x91, 0xe0, 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, 0x59, 0x4f, ++ 0x42, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, 0x55, 0x4b, ++ 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0x53, 0x4b, 0x83, 0x82, 0x51, 0x4b, 0x1b, 0x68, ++ 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x4d, 0x4f, 0x04, 0x23, ++ 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x4a, 0x4b, 0x1b, 0x68, 0x1b, 0x19, ++ 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x47, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, 0x58, 0x86, ++ 0x26, 0x31, 0x60, 0xe0, 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, 0x83, 0x82, ++ 0x40, 0x4f, 0x46, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, 0x83, 0x82, ++ 0x3c, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0x3b, 0x4b, 0x83, 0x82, 0x39, 0x4b, ++ 0x1b, 0x68, 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, 0x35, 0x4f, ++ 0x04, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x31, 0x4b, 0x1b, 0x68, ++ 0x1b, 0x19, 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x2e, 0x4b, 0x01, 0x20, 0x1b, 0x68, 0x1b, 0x19, ++ 0x58, 0x86, 0x2c, 0x31, 0x2f, 0xe0, 0x03, 0x20, 0x00, 0x07, 0x83, 0x8a, 0x3f, 0x23, 0x9b, 0x02, ++ 0x83, 0x82, 0x28, 0x4f, 0x50, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x3b, 0x86, 0x83, 0x8a, 0x83, 0x13, ++ 0x83, 0x82, 0x24, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0xdd, 0x85, 0x83, 0x8a, 0x22, 0x4b, 0x83, 0x82, ++ 0x20, 0x4b, 0x1b, 0x68, 0x1b, 0x19, 0x9d, 0x85, 0x83, 0x8a, 0x06, 0x23, 0xdb, 0x43, 0x83, 0x82, ++ 0x1c, 0x4f, 0x04, 0x23, 0x3f, 0x68, 0x3f, 0x19, 0x7b, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x19, 0x4b, ++ 0x1b, 0x68, 0x1b, 0x19, 0x5d, 0x86, 0x83, 0x8a, 0x86, 0x82, 0x16, 0x4b, 0x01, 0x20, 0x1b, 0x68, ++ 0x1b, 0x19, 0x58, 0x86, 0x38, 0x31, 0x11, 0x80, 0xf0, 0xbd, 0x00, 0xb5, 0x03, 0x00, 0x00, 0xf0, ++ 0x3f, 0xfc, 0x2b, 0x17, 0x29, 0x29, 0x29, 0x29, 0x17, 0x29, 0x17, 0x29, 0x29, 0x29, 0x19, 0x2d, ++ 0x2b, 0x29, 0x29, 0x29, 0x29, 0x25, 0x25, 0x25, 0x25, 0x19, 0x19, 0x17, 0x17, 0x17, 0x17, 0x17, ++ 0x27, 0x17, 0x17, 0x27, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x29, 0x29, 0x29, 0x17, 0x00, ++ 0x06, 0x20, 0x14, 0xe0, 0x03, 0x20, 0x12, 0xe0, 0x40, 0xa1, 0x01, 0x00, 0xfe, 0xff, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x20, 0x84, 0x00, 0x00, 0x20, 0xff, 0x0f, 0x00, 0x00, 0x02, 0x20, 0x06, 0xe0, ++ 0x07, 0x20, 0x04, 0xe0, 0x08, 0x20, 0x02, 0xe0, 0x05, 0x20, 0x00, 0xe0, 0x04, 0x20, 0xff, 0xf7, ++ 0xfb, 0xfd, 0x00, 0xbd, 0xf0, 0xb5, 0x4d, 0x48, 0x00, 0x21, 0x00, 0x68, 0x4c, 0x4a, 0x80, 0x18, ++ 0x02, 0x8a, 0x8c, 0x27, 0xd3, 0x05, 0xde, 0x0f, 0xd0, 0xb2, 0x93, 0x05, 0x52, 0x05, 0xd5, 0x0f, ++ 0x48, 0x4a, 0xdb, 0x0f, 0x12, 0x68, 0xdb, 0x01, 0x14, 0x88, 0xbc, 0x43, 0x1c, 0x43, 0x14, 0x80, ++ 0x0d, 0x28, 0x26, 0xd0, 0x0a, 0xdc, 0x03, 0x00, 0x00, 0xf0, 0xf2, 0xfb, 0x0d, 0x29, 0x2b, 0x2b, ++ 0x2b, 0x2b, 0x29, 0x27, 0x2c, 0x27, 0x27, 0x27, 0x23, 0x23, 0x2c, 0x00, 0x36, 0x28, 0x1e, 0xd0, ++ 0x0e, 0xdc, 0x11, 0x28, 0x15, 0xd0, 0x06, 0xdc, 0x0e, 0x28, 0x12, 0xd0, 0x0f, 0x28, 0x10, 0xd0, ++ 0x10, 0x28, 0x17, 0xd1, 0x0d, 0xe0, 0x31, 0x28, 0x0b, 0xd0, 0x35, 0x28, 0x12, 0xd1, 0x0e, 0xe0, ++ 0x07, 0x46, 0x37, 0x3f, 0x3b, 0x00, 0x00, 0xf0, 0xd3, 0xfb, 0x05, 0x0a, 0x06, 0x06, 0x06, 0x06, ++ 0x0d, 0x00, 0x01, 0x21, 0x06, 0xe0, 0x03, 0x21, 0x04, 0xe0, 0x04, 0x21, 0x02, 0xe0, 0x08, 0x21, ++ 0x00, 0xe0, 0x09, 0x21, 0x1b, 0x28, 0x23, 0xd0, 0x17, 0x28, 0x21, 0xd0, 0x15, 0x28, 0x1f, 0xd0, ++ 0x13, 0x28, 0x1d, 0xd0, 0x11, 0x28, 0x1b, 0xd0, 0x19, 0x28, 0x19, 0xd0, 0x1a, 0x28, 0x17, 0xd0, ++ 0x16, 0x28, 0x15, 0xd0, 0x14, 0x28, 0x13, 0xd0, 0x12, 0x28, 0x11, 0xd0, 0x1c, 0x28, 0x0f, 0xd0, ++ 0x1e, 0x28, 0x0d, 0xd0, 0x1f, 0x28, 0x0b, 0xd0, 0x21, 0x28, 0x09, 0xd0, 0x22, 0x28, 0x07, 0xd0, ++ 0x24, 0x28, 0x05, 0xd0, 0x28, 0x28, 0x03, 0xd0, 0x29, 0x28, 0x01, 0xd0, 0x2a, 0x28, 0x02, 0xd1, ++ 0x04, 0x20, 0x04, 0x43, 0x14, 0x80, 0x03, 0x20, 0x00, 0x07, 0x82, 0x8a, 0x0f, 0x22, 0xd2, 0x43, ++ 0x82, 0x82, 0x12, 0x4a, 0x14, 0x68, 0x14, 0x4b, 0xe4, 0x18, 0x21, 0x80, 0x81, 0x8a, 0x13, 0x49, ++ 0x81, 0x82, 0x14, 0x68, 0x49, 0x1c, 0xe3, 0x18, 0x19, 0x80, 0x81, 0x8a, 0x10, 0x49, 0x81, 0x82, ++ 0x14, 0x68, 0x73, 0x00, 0x0d, 0x26, 0x76, 0x03, 0xa4, 0x19, 0x23, 0x84, 0x83, 0x8a, 0x81, 0x82, ++ 0x10, 0x68, 0x69, 0x00, 0xff, 0x30, 0x01, 0x30, 0x81, 0x85, 0xf0, 0xbd, 0x03, 0x48, 0x00, 0x68, ++ 0x05, 0x49, 0xc0, 0x31, 0x40, 0x18, 0x40, 0x8e, 0xc0, 0xb2, 0x2e, 0xe7, 0x84, 0x00, 0x00, 0x20, ++ 0xc0, 0xa2, 0x01, 0x00, 0x90, 0x00, 0x00, 0x20, 0x00, 0xa1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, ++ 0xfd, 0xff, 0x00, 0x00, 0x31, 0x48, 0x00, 0x79, 0xc0, 0x07, 0xc0, 0x0f, 0x70, 0x47, 0x2f, 0x48, ++ 0x01, 0x78, 0x8f, 0x22, 0x11, 0x40, 0x01, 0x70, 0x01, 0x79, 0x01, 0x78, 0x01, 0x22, 0x11, 0x43, ++ 0x01, 0x70, 0x70, 0x47, 0x29, 0x48, 0x80, 0x68, 0x70, 0x47, 0x28, 0x48, 0x00, 0x89, 0x80, 0xb2, ++ 0x70, 0x47, 0x70, 0x47, 0x03, 0x20, 0x00, 0x07, 0x00, 0x8a, 0x80, 0x05, 0x80, 0x0d, 0x70, 0x47, ++ 0x23, 0x49, 0x09, 0x68, 0x80, 0x31, 0x89, 0x7c, 0x09, 0x07, 0x09, 0x0e, 0x8a, 0x00, 0x1f, 0x49, ++ 0x40, 0x31, 0x51, 0x18, 0x88, 0x60, 0x08, 0x78, 0x8f, 0x22, 0x10, 0x40, 0x10, 0x30, 0x08, 0x70, ++ 0x08, 0x78, 0x01, 0x22, 0x10, 0x43, 0x08, 0x70, 0x70, 0x47, 0x19, 0x48, 0x00, 0x68, 0x80, 0x30, ++ 0x80, 0x7c, 0x00, 0x07, 0x00, 0x0e, 0x81, 0x00, 0x14, 0x48, 0x40, 0x30, 0x08, 0x18, 0x01, 0x78, ++ 0x02, 0x22, 0x11, 0x43, 0x01, 0x70, 0x70, 0x47, 0x11, 0x48, 0x10, 0x49, 0x00, 0x68, 0x40, 0x31, ++ 0x80, 0x30, 0x80, 0x7c, 0x00, 0x07, 0x00, 0x0e, 0x80, 0x00, 0x40, 0x18, 0xc0, 0x68, 0x70, 0x47, ++ 0x0b, 0x48, 0x0a, 0x49, 0x00, 0x68, 0x40, 0x31, 0x80, 0x30, 0x80, 0x7c, 0x00, 0x07, 0x00, 0x0e, ++ 0x80, 0x00, 0x40, 0x18, 0x00, 0x79, 0xc0, 0x07, 0xc0, 0x0f, 0x70, 0x47, 0x03, 0x21, 0x09, 0x07, ++ 0x08, 0x60, 0x08, 0x7b, 0x01, 0x22, 0x10, 0x43, 0x08, 0x73, 0x70, 0x47, 0xc0, 0x00, 0x00, 0x30, ++ 0x90, 0x00, 0x00, 0x20, 0x10, 0xb5, 0x72, 0xb6, 0x56, 0x49, 0xc8, 0x69, 0xff, 0x22, 0x12, 0x04, ++ 0x90, 0x43, 0x01, 0x22, 0x92, 0x05, 0x10, 0x43, 0xc8, 0x61, 0x54, 0x48, 0x52, 0x49, 0x41, 0x60, ++ 0x81, 0x60, 0x00, 0x20, 0x52, 0x4a, 0x01, 0x21, 0xc4, 0x06, 0xe4, 0x0e, 0x0b, 0x46, 0xa3, 0x40, ++ 0x44, 0x09, 0xa4, 0x00, 0xa4, 0x18, 0x23, 0x60, 0x40, 0x1c, 0x40, 0xb2, 0x0c, 0x28, 0xf3, 0xdb, ++ 0x4c, 0x4a, 0x04, 0x20, 0xc4, 0x06, 0xe4, 0x0e, 0x0b, 0x46, 0xa3, 0x40, 0x44, 0x09, 0xa4, 0x00, ++ 0xa4, 0x18, 0x23, 0x60, 0x40, 0x1c, 0x40, 0xb2, 0x0c, 0x28, 0xf3, 0xdb, 0x62, 0xb6, 0x10, 0xbd, ++ 0xfe, 0xb5, 0x45, 0x4c, 0x21, 0x68, 0x00, 0x91, 0x44, 0x4d, 0x45, 0x4f, 0x2e, 0x68, 0x39, 0x68, ++ 0x01, 0x91, 0x01, 0x02, 0x43, 0x4a, 0x80, 0x07, 0x89, 0x18, 0x29, 0x60, 0x21, 0x68, 0xfa, 0x12, ++ 0x91, 0x43, 0x40, 0x0b, 0x01, 0x43, 0x21, 0x60, 0xff, 0xf7, 0x51, 0xfb, 0x00, 0x98, 0x20, 0x60, ++ 0x2e, 0x60, 0x01, 0x98, 0x38, 0x60, 0xfe, 0xbd, 0xfe, 0xb5, 0x37, 0x4c, 0x21, 0x68, 0x00, 0x91, ++ 0x36, 0x4d, 0x37, 0x4f, 0x2e, 0x68, 0x39, 0x68, 0x01, 0x91, 0x01, 0x02, 0x35, 0x4a, 0x80, 0x07, ++ 0x89, 0x18, 0x29, 0x60, 0x21, 0x68, 0xfa, 0x12, 0x91, 0x43, 0x40, 0x0b, 0x01, 0x43, 0x21, 0x60, ++ 0xfe, 0xf7, 0x3c, 0xfe, 0x00, 0x98, 0x20, 0x60, 0x2e, 0x60, 0x01, 0x98, 0x38, 0x60, 0xfe, 0xbd, ++ 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, 0x01, 0x98, 0x00, 0xf0, 0xc0, 0xf8, 0x10, 0xbd, 0x10, 0xb5, ++ 0x00, 0x22, 0x11, 0x46, 0x01, 0x98, 0x00, 0xf0, 0xb9, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x22, ++ 0x11, 0x46, 0x01, 0x98, 0x00, 0xf0, 0xb2, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, ++ 0x01, 0x98, 0x00, 0xf0, 0xab, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, 0x01, 0x98, ++ 0x00, 0xf0, 0xa4, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, 0x01, 0x98, 0x00, 0xf0, ++ 0x9d, 0xf8, 0x10, 0xbd, 0x18, 0x48, 0x40, 0x7e, 0x9a, 0xe7, 0x17, 0x48, 0x80, 0x7e, 0x97, 0xe7, ++ 0x15, 0x48, 0xc0, 0x7e, 0x94, 0xe7, 0x14, 0x48, 0x00, 0x7f, 0x91, 0xe7, 0x12, 0x48, 0x40, 0x7e, ++ 0xaa, 0xe7, 0x11, 0x48, 0x80, 0x7e, 0xa7, 0xe7, 0x0f, 0x48, 0xc0, 0x7e, 0xa4, 0xe7, 0x0e, 0x48, ++ 0x00, 0x7f, 0xa1, 0xe7, 0x10, 0xb5, 0x00, 0x22, 0x11, 0x46, 0x01, 0x98, 0x00, 0xf0, 0x7e, 0xf8, ++ 0x10, 0xbd, 0x00, 0x00, 0x04, 0xed, 0x00, 0xe0, 0x80, 0x80, 0x80, 0x80, 0x00, 0xe4, 0x00, 0xe0, ++ 0x80, 0xe2, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x84, 0x00, 0x00, 0x20, 0x90, 0x00, 0x00, 0x20, ++ 0x14, 0x00, 0x00, 0x30, 0x00, 0x05, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, 0x10, 0xb5, 0xff, 0x21, ++ 0x01, 0x31, 0x2b, 0x48, 0x00, 0xf0, 0xf6, 0xf9, 0x10, 0xbd, 0xc1, 0x08, 0x10, 0xb5, 0x09, 0x1d, ++ 0x1f, 0x28, 0x13, 0xd8, 0x72, 0xb6, 0x27, 0x4a, 0x25, 0x4b, 0x12, 0x68, 0x80, 0x32, 0x92, 0x7c, ++ 0x92, 0x01, 0x9c, 0x5c, 0x01, 0x2c, 0x00, 0xd1, 0x09, 0x1d, 0xd2, 0x18, 0x44, 0x07, 0x53, 0x5c, ++ 0x64, 0x0f, 0x01, 0x20, 0xa0, 0x40, 0x03, 0x43, 0x53, 0x54, 0x62, 0xb6, 0x10, 0xbd, 0xf0, 0xb5, ++ 0x1c, 0x49, 0x1b, 0x4e, 0x0b, 0x68, 0x80, 0x33, 0x99, 0x7c, 0x89, 0x01, 0x8d, 0x19, 0xa9, 0x78, ++ 0xff, 0x29, 0x2c, 0xd0, 0x6a, 0x78, 0xfe, 0x29, 0x04, 0xd0, 0x8f, 0x1a, 0x91, 0x42, 0x03, 0xd8, ++ 0x0d, 0x24, 0x02, 0xe0, 0x02, 0x24, 0x02, 0xe0, 0x00, 0x24, 0x3c, 0x19, 0x64, 0x1e, 0x24, 0x06, ++ 0x24, 0x0e, 0x1c, 0xd0, 0x01, 0x2c, 0x00, 0xd1, 0xa0, 0x1e, 0x94, 0x00, 0x2c, 0x19, 0x52, 0x1c, ++ 0xe0, 0x60, 0xd0, 0xb2, 0x0d, 0x28, 0x00, 0xd3, 0x00, 0x20, 0x9a, 0x7c, 0x92, 0x01, 0x92, 0x19, ++ 0x50, 0x70, 0xfe, 0x29, 0x0b, 0xd1, 0x99, 0x7c, 0x89, 0x01, 0x8a, 0x19, 0xd1, 0x78, 0x81, 0x42, ++ 0x05, 0xd1, 0x49, 0x1c, 0xc8, 0xb2, 0x0d, 0x28, 0x00, 0xd3, 0x00, 0x20, 0xd0, 0x70, 0xf0, 0xbd, ++ 0x00, 0x09, 0x00, 0x20, 0x90, 0x00, 0x00, 0x20, 0x10, 0xb5, 0x20, 0x21, 0x37, 0x48, 0x00, 0xf0, ++ 0x99, 0xf9, 0x20, 0x21, 0x36, 0x48, 0x00, 0xf0, 0x95, 0xf9, 0x10, 0xbd, 0x72, 0xb6, 0xbf, 0xf3, ++ 0x40, 0x8f, 0x34, 0x4b, 0x20, 0x25, 0x1c, 0x7c, 0x2c, 0x43, 0x1c, 0x74, 0xef, 0xf3, 0x05, 0x83, ++ 0x2e, 0x4c, 0x9b, 0x06, 0x9b, 0x0e, 0x25, 0x78, 0x23, 0x70, 0x00, 0x2d, 0x09, 0xd1, 0xa3, 0x70, ++ 0xa0, 0x60, 0xef, 0xf3, 0x08, 0x80, 0xe0, 0x60, 0xef, 0xf3, 0x09, 0x80, 0xe2, 0x61, 0xa1, 0x61, ++ 0x20, 0x61, 0x01, 0x20, 0x10, 0x2b, 0x06, 0xd3, 0x02, 0x46, 0x10, 0x3b, 0x61, 0x69, 0x9a, 0x40, ++ 0x11, 0x43, 0x61, 0x61, 0x04, 0xe0, 0x02, 0x46, 0x61, 0x68, 0x9a, 0x40, 0x11, 0x43, 0x61, 0x60, ++ 0x00, 0x21, 0x61, 0x70, 0xbf, 0xf3, 0x40, 0x8f, 0x62, 0xb6, 0xe1, 0x78, 0x01, 0x43, 0xe1, 0x70, ++ 0xfe, 0xe7, 0xf0, 0xb5, 0x05, 0x9d, 0x72, 0xb6, 0xbf, 0xf3, 0x40, 0x8f, 0x19, 0x4c, 0x40, 0x27, ++ 0x26, 0x7c, 0x3e, 0x43, 0x26, 0x74, 0x16, 0x4c, 0x26, 0x78, 0x20, 0x70, 0x00, 0x2e, 0x09, 0xd1, ++ 0xa0, 0x70, 0xa1, 0x60, 0xef, 0xf3, 0x08, 0x81, 0xe1, 0x60, 0xef, 0xf3, 0x09, 0x81, 0xe5, 0x61, ++ 0xa3, 0x61, 0x21, 0x61, 0x01, 0x21, 0x20, 0x28, 0x06, 0xd3, 0x0d, 0x46, 0x20, 0x38, 0x63, 0x69, ++ 0x85, 0x40, 0x2b, 0x43, 0x63, 0x61, 0x04, 0xe0, 0x0b, 0x46, 0x65, 0x68, 0x83, 0x40, 0x1d, 0x43, ++ 0x65, 0x60, 0x00, 0x20, 0x60, 0x70, 0xbf, 0xf3, 0x40, 0x8f, 0x62, 0xb6, 0x00, 0x2a, 0x03, 0xd0, ++ 0xe0, 0x78, 0x08, 0x43, 0xe0, 0x70, 0xfe, 0xe7, 0xf0, 0xbd, 0x00, 0x00, 0x24, 0x04, 0x00, 0x20, ++ 0x44, 0x04, 0x00, 0x20, 0x00, 0x04, 0x00, 0x20, 0xf0, 0xb5, 0x4c, 0x4d, 0x0a, 0x21, 0x69, 0x5e, ++ 0x00, 0x22, 0x4b, 0x4e, 0x4b, 0x4b, 0x4c, 0x4f, 0x0a, 0xe0, 0xb4, 0x5c, 0x5c, 0x54, 0x40, 0x1e, ++ 0x52, 0x1c, 0x49, 0x1e, 0x09, 0xb2, 0xc0, 0xb2, 0xd2, 0xb2, 0x00, 0x29, 0x00, 0xda, 0x39, 0x46, ++ 0x00, 0x28, 0xf2, 0xd1, 0x69, 0x81, 0xf0, 0xbd, 0xff, 0xb5, 0x81, 0xb0, 0x05, 0x46, 0x04, 0x98, ++ 0x0b, 0x9e, 0x00, 0x28, 0x00, 0xd1, 0x72, 0xb6, 0x3c, 0x49, 0x48, 0x7b, 0xff, 0x28, 0x02, 0xd1, ++ 0x4b, 0x89, 0x08, 0x2b, 0x01, 0xd3, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, 0x02, 0x9b, 0x5b, 0x1e, ++ 0x2f, 0x2b, 0x52, 0xd2, 0x00, 0x2c, 0x50, 0xd0, 0x34, 0x49, 0x49, 0x7d, 0x00, 0x29, 0x4c, 0xd1, ++ 0x01, 0x2d, 0x02, 0xd0, 0x00, 0x2d, 0x03, 0xd0, 0x04, 0xe0, 0x34, 0x48, 0x00, 0x68, 0x40, 0x79, ++ 0x90, 0x42, 0x42, 0xd3, 0xff, 0xf7, 0xce, 0xfd, 0x07, 0x46, 0x01, 0x0c, 0x30, 0x48, 0x00, 0x68, ++ 0x00, 0x0c, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x12, 0xd0, 0x29, 0x49, 0xff, 0x22, 0x8a, 0x70, ++ 0x02, 0x0a, 0x4a, 0x70, 0x08, 0x70, 0x03, 0x20, 0xff, 0xf7, 0xae, 0xff, 0x23, 0x48, 0x41, 0x7b, ++ 0xff, 0x29, 0x04, 0xd1, 0x40, 0x89, 0x08, 0x28, 0x01, 0xd2, 0x00, 0x24, 0x00, 0xe0, 0x01, 0x24, ++ 0x23, 0x48, 0x00, 0x2c, 0x07, 0x60, 0x20, 0xd0, 0x01, 0x2d, 0x24, 0xd0, 0x00, 0x2d, 0x27, 0xd0, ++ 0x08, 0x24, 0x0a, 0x98, 0x00, 0x28, 0x08, 0xd0, 0x19, 0x48, 0x31, 0x0a, 0x06, 0x70, 0x41, 0x70, ++ 0x31, 0x0c, 0x81, 0x70, 0x0a, 0x98, 0xff, 0xf7, 0x8f, 0xff, 0x0a, 0x98, 0x14, 0x49, 0x00, 0x1d, ++ 0x40, 0x01, 0x20, 0x43, 0xc8, 0x70, 0x16, 0x48, 0x00, 0x88, 0x02, 0x0a, 0x8a, 0x70, 0x48, 0x70, ++ 0x02, 0x98, 0x08, 0x70, 0x04, 0x20, 0xff, 0xf7, 0x7f, 0xff, 0x04, 0x98, 0x00, 0x28, 0x00, 0xd1, ++ 0x62, 0xb6, 0x05, 0xb0, 0xf0, 0xbd, 0x0d, 0x48, 0x00, 0x68, 0x80, 0x30, 0x84, 0x7c, 0xd8, 0xe7, ++ 0x0f, 0x24, 0xd6, 0xe7, 0x1c, 0xb5, 0x0a, 0x46, 0x00, 0x21, 0x00, 0x91, 0x0b, 0x46, 0x01, 0x91, ++ 0x01, 0x46, 0x01, 0x20, 0xff, 0xf7, 0x80, 0xff, 0x1c, 0xbd, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, ++ 0x8c, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0xff, 0x02, 0x00, 0x00, 0x90, 0x00, 0x00, 0x20, ++ 0x88, 0x00, 0x00, 0x20, 0x30, 0xb5, 0x0e, 0x49, 0x00, 0x20, 0x09, 0x78, 0x0b, 0x4d, 0x4c, 0x1e, ++ 0x11, 0xe0, 0x02, 0x02, 0x52, 0x19, 0x80, 0x32, 0x90, 0x74, 0x00, 0x28, 0x05, 0xd0, 0x43, 0x1e, ++ 0x13, 0x75, 0xa0, 0x42, 0x03, 0xd1, 0x00, 0x23, 0x02, 0xe0, 0x23, 0x46, 0xf8, 0xe7, 0x43, 0x1c, ++ 0x40, 0x1c, 0xd3, 0x74, 0xc0, 0xb2, 0x88, 0x42, 0xeb, 0xd3, 0x30, 0xbd, 0x00, 0x05, 0x00, 0x20, ++ 0x80, 0x00, 0x00, 0x20, 0x70, 0x47, 0xf8, 0xb5, 0x04, 0x2a, 0x2c, 0xd3, 0x83, 0x07, 0x12, 0xd0, ++ 0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x83, 0x07, 0x0b, 0xd0, 0x0b, 0x78, ++ 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x83, 0x07, 0x04, 0xd0, 0x0b, 0x78, 0x49, 0x1c, ++ 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x8b, 0x07, 0x9b, 0x0f, 0x05, 0xd0, 0xc9, 0x1a, 0xdf, 0x00, ++ 0x20, 0x23, 0xde, 0x1b, 0x08, 0xc9, 0x0a, 0xe0, 0xf8, 0xf7, 0xcc, 0xfc, 0xf8, 0xbd, 0x1d, 0x46, ++ 0x08, 0xc9, 0xfd, 0x40, 0x1c, 0x46, 0xb4, 0x40, 0x2c, 0x43, 0x10, 0xc0, 0x12, 0x1f, 0x04, 0x2a, ++ 0xf5, 0xd2, 0xf3, 0x08, 0xc9, 0x1a, 0x52, 0x1e, 0xf0, 0xd4, 0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, ++ 0x40, 0x1c, 0x52, 0x1e, 0xea, 0xd4, 0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x01, 0x2a, ++ 0xe4, 0xd4, 0x09, 0x78, 0x01, 0x70, 0xf8, 0xbd, 0x01, 0xe0, 0x04, 0xc0, 0x09, 0x1f, 0x04, 0x29, ++ 0xfb, 0xd2, 0x8b, 0x07, 0x01, 0xd5, 0x02, 0x80, 0x80, 0x1c, 0xc9, 0x07, 0x00, 0xd0, 0x02, 0x70, ++ 0x70, 0x47, 0x00, 0x29, 0x0b, 0xd0, 0xc3, 0x07, 0x02, 0xd0, 0x02, 0x70, 0x40, 0x1c, 0x49, 0x1e, ++ 0x02, 0x29, 0x04, 0xd3, 0x83, 0x07, 0x02, 0xd5, 0x02, 0x80, 0x80, 0x1c, 0x89, 0x1e, 0xe3, 0xe7, ++ 0x00, 0x22, 0xee, 0xe7, 0x00, 0x22, 0xdf, 0xe7, 0x03, 0x78, 0xc2, 0x78, 0x19, 0x46, 0x43, 0x78, ++ 0x12, 0x06, 0x1b, 0x02, 0x19, 0x43, 0x83, 0x78, 0xc0, 0x78, 0x1b, 0x04, 0x19, 0x43, 0x11, 0x43, ++ 0x09, 0x02, 0x09, 0x0a, 0x00, 0x06, 0x08, 0x43, 0x70, 0x47, 0x70, 0x47, 0x75, 0x46, 0x00, 0xf0, ++ 0x23, 0xf8, 0xae, 0x46, 0x05, 0x00, 0x69, 0x46, 0x53, 0x46, 0xc0, 0x08, 0xc0, 0x00, 0x85, 0x46, ++ 0x18, 0xb0, 0x20, 0xb5, 0xf8, 0xf7, 0x9e, 0xfc, 0x60, 0xbc, 0x00, 0x27, 0x49, 0x08, 0xb6, 0x46, ++ 0x00, 0x26, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, ++ 0xc0, 0xc5, 0x40, 0x3d, 0x49, 0x00, 0x8d, 0x46, 0x70, 0x47, 0x04, 0x46, 0xc0, 0x46, 0xc0, 0x46, ++ 0x20, 0x46, 0xf8, 0xf7, 0x50, 0xfc, 0x00, 0x00, 0x00, 0x48, 0x70, 0x47, 0x94, 0x00, 0x00, 0x20, ++ 0x30, 0xb4, 0x74, 0x46, 0x64, 0x1e, 0x25, 0x78, 0x64, 0x1c, 0xab, 0x42, 0x00, 0xd2, 0x1d, 0x46, ++ 0x63, 0x5d, 0x5b, 0x00, 0xe3, 0x18, 0x30, 0xbc, 0x18, 0x47, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, ++ 0x19, 0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x22, ++ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x30, ++ 0x31, 0x31, 0x32, 0x32, 0x21, 0x10, 0x42, 0x20, 0x84, 0x40, 0x08, 0x81, 0x31, 0x12, 0x62, 0x24, ++ 0xc4, 0x48, 0x88, 0x91, 0x00, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x1f, 0x00, 0x29, 0x00, 0x34, 0x00, ++ 0x3e, 0x00, 0x49, 0x00, 0x53, 0x00, 0x5d, 0x00, 0x68, 0x00, 0x72, 0x00, 0x7c, 0x00, 0x87, 0x00, ++ 0x91, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0xb0, 0x00, 0xba, 0x00, 0xc5, 0x00, 0xcf, 0x00, 0xda, 0x00, ++ 0xe4, 0x00, 0xee, 0x00, 0xf9, 0x00, 0x03, 0x01, 0x0d, 0x01, 0x18, 0x01, 0x22, 0x01, 0x2c, 0x01, ++ 0x37, 0x01, 0x41, 0x01, 0x00, 0x00, 0x11, 0x00, 0x23, 0x00, 0x34, 0x00, 0x46, 0x00, 0x57, 0x00, ++ 0x69, 0x00, 0x7a, 0x00, 0x8c, 0x00, 0x9d, 0x00, 0xaf, 0x00, 0xc0, 0x00, 0xd2, 0x00, 0xe3, 0x00, ++ 0xf5, 0x00, 0x06, 0x01, 0x18, 0x01, 0x29, 0x01, 0x3b, 0x01, 0x4c, 0x01, 0x5d, 0x01, 0x6f, 0x01, ++ 0x80, 0x01, 0x92, 0x01, 0xa3, 0x01, 0xb5, 0x01, 0xc6, 0x01, 0xd8, 0x01, 0xe9, 0x01, 0xfb, 0x01, ++ 0x0c, 0x02, 0x1e, 0x02, 0x74, 0x7a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x14, 0x00, 0x00, 0x00, ++ 0xc4, 0x01, 0x00, 0x00, 0x88, 0x7a, 0x00, 0x00, 0x94, 0x00, 0x00, 0x20, 0x6c, 0x09, 0x00, 0x00, ++ 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/pm.h b/drivers/net/ethernet/broadcom/pm.h +--- a/drivers/net/ethernet/broadcom/pm.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/pm.h 2018-05-30 15:50:51.032753168 +0800 +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef _PM_H ++#define _PM_H ++ ++ ++#define pmLoopbackMac 0 ++#define pmLoopbackPhy 1 ++ ++struct iproc_pm_stats { ++ u64 rx_frames;//XLMIB_GRxPkt ++ u64 rx_frame_good;//XLMIB_GRxPOK ++ u64 rx_bytes;//XLMIB_GRxByt ++ u64 rx_frame_64;//XLMIB_GRx64 ++ u64 rx_frame_127;//XLMIB_GRx127 ++ u64 rx_frame_255;//XLMIB_GRx255 ++ u64 rx_frame_511;//XLMIB_GRx511 ++ u64 rx_frame_1023;//XLMIB_GRx1023 ++ u64 rx_frame_1518;//XLMIB_GRx1518 ++ u64 rx_frame_1522;//XLMIB_GRx1522 ++ u64 rx_frame_jumbo;//XLMIB_GRx2047 + XLMIB_GRx4095 + XLMIB_GRx9216+ XLMIB_GRx16383 ++ u64 rx_frame_unicast;//XLMIB_GRxUCA ++ u64 rx_frame_multicast;//XLMIB_GRxMCA ++ u64 rx_frame_broadcast;//XLMIB_GRxBCA ++ u64 rx_frame_control;//XLMIB_GRxCF ++ u64 rx_frame_pause;//XLMIB_GRxPF ++ u64 rx_frame_jabber;//XLMIB_GRxJBR ++ u64 rx_frame_fragment;//XLMIB_GRxFRG ++ u64 rx_frame_vlan;//XLMIB_GRxVLN ++ u64 rx_frame_dvlan;//XLMIB_GRxDVLN ++ u64 rx_frame_fcs_error;//XLMIB_GRxFCS ++ u64 rx_frame_unsupport;//XLMIB_GRxUO ++ u64 rx_frame_wrong_sa;//XLMIB_GRxWSA ++ u64 rx_frame_align_err;//XLMIB_GRxALN ++ u64 rx_frame_length_err;//XLMIB_GRxFLR ++ u64 rx_frame_oversize;//XLMIB_GRxOVR ++ u64 rx_frame_mtu_err;//XLMIB_GRxMTUE ++ u64 rx_frame_truncated_err;//XLMIB_GRxTRFU ++ u64 rx_frame_undersize;//XLMIB_GRxUND ++ u64 tx_frames;//XLMIB_GTxPkt ++ u64 tx_frame_good;//XLMIB_GTxPOK ++ u64 tx_bytes;//XLMIB_GTxBYT ++ u64 tx_frame_64;//XLMIB_GTx64 ++ u64 tx_frame_127;//XLMIB_GTx127 ++ u64 tx_frame_255;//XLMIB_GTx255 ++ u64 tx_frame_511;//XLMIB_GTx511 ++ u64 tx_frame_1023;//XLMIB_GTx1023 ++ u64 tx_frame_1518;//XLMIB_GTx1518 ++ u64 tx_frame_1522;//XLMIB_GTx1522 ++ u64 tx_frame_jumbo;//XLMIB_GTx2047 + XLMIB_GTx4095 + XLMIB_GTx9216 + XLMIB_GTx16383 ++ u64 tx_frame_unicast;//XLMIB_GTxUCA ++ u64 tx_frame_multicast;//XLMIB_GTxMCA ++ u64 tx_frame_broadcast;//XLMIB_GTxBCA ++ u64 tx_frame_control;//XLMIB_GTxCF ++ u64 tx_frame_pause;//XLMIB_GTxPF ++ u64 tx_frame_jabber;//XLMIB_GTxJBR ++ u64 tx_frame_fragment;//XLMIB_GTxFRG ++ u64 tx_frame_vlan;//XLMIB_GTxVLN ++ u64 tx_frame_dvlan;//XLMIB_GTxDVLN ++ u64 tx_frame_fcs_error;//XLMIB_GTxFCS ++ u64 tx_frame_oversize;//XLMIB_GTxOVR ++ u64 tx_frame_error;//XLMIB_GTxErr ++ u64 tx_frame_fifo_underrun;//XLMIB_GTxUFL ++ u64 tx_frame_collision;//XLMIB_GTxNCL ++}; ++ ++struct iproc_pm_ops { ++ int (*port_enable)(int port, int enable); ++ int (*port_speed)(int port, int speed); ++ int (*port_loopback)(int port, int lb_type, int lb_en); ++ int (*port_mac_addr)(int port, u8 *mac); ++ int (*port_stats)(int port, struct iproc_pm_stats *stats); ++ int (*port_stats_clear)(int port); ++}; ++ ++extern int pm4x10_pm_init(struct iproc_pm_ops *pm_ops, u8 lane_idx); ++extern int pm4x10_pm_deinit(struct iproc_pm_ops *pm_ops); ++ ++extern int pm4x10_pm_xlport_port_config(int port, int enable); ++extern int pm4x10_xlport_speed_set(int port, int speed); ++extern int pm4x10_xlport_loopback_set(int port, int lb_type, int lb_en); ++extern int pm4x10_xlport_mac_addr_set(int port, u8 *mac); ++extern int pm4x10_xlport_stats_get(int port, struct iproc_pm_stats *stats); ++extern int pm4x10_xlport_mib_reset(int port); ++ ++#endif /* _PM_H */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/pm4x10.c b/drivers/net/ethernet/broadcom/pm4x10.c +--- a/drivers/net/ethernet/broadcom/pm4x10.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/ethernet/broadcom/pm4x10.c 2018-05-31 16:19:28.761893937 +0800 +@@ -0,0 +1,1175 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 "pm.h" ++#include "merlin16_ucode.h" ++ ++#define JUMBO_MAXSZ 0x3fe8 ++ ++#define debug(fmt, args...) do {} while (0) ++ ++ ++#define PM_CORE_ADDR(port) ((1 << (port + 1)) + 1) ++ ++#define PM_PMD_X1_CTL_REG(port) (0x00009010 | (PM_CORE_ADDR(port) << 19)) ++#define PM_PMD_X4_CTL_REG(port) (0x0000c010 | (PM_CORE_ADDR(port) << 19)) ++#define PM_CKRST_LN_CLK_RST_N_PWRDWN_CTL_REG(port) (0x0001d0b1 | (PM_CORE_ADDR(port) << 19)) ++#define PM_DIG_TOP_USER_CTL0_REG(port) (0x0001d104 | (PM_CORE_ADDR(port) << 19)) ++#define PM_TXFIR_MISC_CTL1_REG(port) (0x0001d139 | (PM_CORE_ADDR(port) << 19)) ++ ++#define TSC_OPERATION_WRITE 0x1 ++#define TSC_OPERATION_READ 0x0 ++ ++ ++/* S-channel address */ ++/* Per port registers */ ++#define XLMIB_GRx64(port) (0x00000000 + port) ++#define XLMIB_GRx127(port) (0x00000100 + port) ++#define XLMIB_GRx255(port) (0x00000200 + port) ++#define XLMIB_GRx511(port) (0x00000300 + port) ++#define XLMIB_GRx1023(port) (0x00000400 + port) ++#define XLMIB_GRx1518(port) (0x00000500 + port) ++#define XLMIB_GRx1522(port) (0x00000600 + port) ++#define XLMIB_GRx2047(port) (0x00000700 + port) ++#define XLMIB_GRx4095(port) (0x00000800 + port) ++#define XLMIB_GRx9216(port) (0x00000900 + port) ++#define XLMIB_GRx16383(port) (0x00000a00 + port) ++#define XLMIB_GRxPkt(port) (0x00000b00 + port) ++#define XLMIB_GRxUCA(port) (0x00000c00 + port) ++#define XLMIB_GRxMCA(port) (0x00000d00 + port) ++#define XLMIB_GRxBCA(port) (0x00000e00 + port) ++#define XLMIB_GRxFCS(port) (0x00000f00 + port) ++#define XLMIB_GRxCF(port) (0x00001000 + port) ++#define XLMIB_GRxPF(port) (0x00001100 + port) ++#define XLMIB_GRxUO(port) (0x00001300 + port) ++#define XLMIB_GRxWSA(port) (0x00001500 + port) ++#define XLMIB_GRxALN(port) (0x00001600 + port) ++#define XLMIB_GRxFLR(port) (0x00001700 + port) ++#define XLMIB_GRxOVR(port) (0x00001a00 + port) ++#define XLMIB_GRxJBR(port) (0x00001b00 + port) ++#define XLMIB_GRxMTUE(port) (0x00001c00 + port) ++#define XLMIB_GRxVLN(port) (0x00001f00 + port) ++#define XLMIB_GRxDVLN(port) (0x00002000 + port) ++#define XLMIB_GRxTRFU(port) (0x00002100 + port) ++#define XLMIB_GRxPOK(port) (0x00002200 + port) ++#define XLMIB_GRxUND(port) (0x00003400 + port) ++#define XLMIB_GRxFRG(port) (0x00003500 + port) ++#define XLMIB_GRxByt(port) (0x00003d00 + port) ++#define XLMIB_GTx64(port) (0x00004000 + port) ++#define XLMIB_GTx127(port) (0x00004100 + port) ++#define XLMIB_GTx255(port) (0x00004200 + port) ++#define XLMIB_GTx511(port) (0x00004300 + port) ++#define XLMIB_GTx1023(port) (0x00004400 + port) ++#define XLMIB_GTx1518(port) (0x00004500 + port) ++#define XLMIB_GTx1522(port) (0x00004600 + port) ++#define XLMIB_GTx2047(port) (0x00004700 + port) ++#define XLMIB_GTx4095(port) (0x00004800 + port) ++#define XLMIB_GTx9216(port) (0x00004900 + port) ++#define XLMIB_GTx16383(port) (0x00004a00 + port) ++#define XLMIB_GTxPOK(port) (0x00004b00 + port) ++#define XLMIB_GTxPkt(port) (0x00004c00 + port) ++#define XLMIB_GTxUCA(port) (0x00004d00 + port) ++#define XLMIB_GTxMCA(port) (0x00004e00 + port) ++#define XLMIB_GTxBCA(port) (0x00004f00 + port) ++#define XLMIB_GTxPF(port) (0x00005000 + port) ++#define XLMIB_GTxJBR(port) (0x00005200 + port) ++#define XLMIB_GTxFCS(port) (0x00005300 + port) ++#define XLMIB_GTxCF(port) (0x00005400 + port) ++#define XLMIB_GTxOVR(port) (0x00005500 + port) ++#define XLMIB_GTxFRG(port) (0x00005c00 + port) ++#define XLMIB_GTxErr(port) (0x00005d00 + port) ++#define XLMIB_GTxVLN(port) (0x00005e00 + port) ++#define XLMIB_GTxDVLN(port) (0x00005f00 + port) ++#define XLMIB_GTxUFL(port) (0x00006100 + port) ++#define XLMIB_GTxNCL(port) (0x00006e00 + port) ++#define XLMIB_GTxBYT(port) (0x00006f00 + port) ++ ++#define XLPORT_CONFIG(port) (0x00020000 + port) ++#define XLMAC_CTRL(port) (0x00060000 + port) ++#define XLMAC_CTRL__SW_LINK_STATUS 12 ++#define XLMAC_CTRL__XGMII_IPG_CHECK_DISABLE 11 ++#define XLMAC_CTRL__SOFT_RESET 6 ++#define XLMAC_CTRL__LOCAL_LPBK 2 ++#define XLMAC_CTRL__RX_EN 1 ++#define XLMAC_CTRL__TX_EN 0 ++#define XLMAC_MODE(port) (0x00060100 + port) ++#define XLMAC_MODE_OFFSET 0x1 ++#define XLMAC_MODE__SPEED_MODE_L 6 ++#define XLMAC_MODE__SPEED_MODE_R 4 ++#define XLMAC_MODE__SPEED_MODE_WIDTH 3 ++#define SPEED_MODE_LINK_10M 0x0 ++#define SPEED_MODE_LINK_100M 0x1 ++#define SPEED_MODE_LINK_1G 0x2 ++#define SPEED_MODE_LINK_2G5 0x3 ++#define SPEED_MODE_LINK_10G_PLUS 0x4 ++#define XLMAC_MODE__SPEED_MODE_RESETVALUE 0x4 ++#define XLMAC_MODE__NO_SOP_FOR_CRC_HG 3 ++#define XLMAC_MODE__NO_SOP_FOR_CRC_HG_WIDTH 1 ++#define XLMAC_MODE__NO_SOP_FOR_CRC_HG_RESETVALUE 0x0 ++#define XLMAC_MODE__HDR_MODE_L 2 ++#define XLMAC_MODE__HDR_MODE_R 0 ++#define XLMAC_MODE__HDR_MODE_WIDTH 3 ++#define HDR_MODE_IEEE 0x0 ++#define HDR_MODE_HG_PLUS 0x1 ++#define HDR_MODE_HG_2 0x2 ++#define HDR_MODE_SOP_ONLY_IEEE 0x5 ++#define XLMAC_TX_CTRL(port) (0x00060400 + port) ++#define XLMAC_TX_CTRL__AVERAGE_IPG_R 12 ++#define XLMAC_TX_CTRL__PAD_EN 4 ++#define XLMAC_TX_CTRL__CRC_MODE_R 0 ++#define CRC_MODE_APPEND 0x0 ++#define CRC_MODE_KEEP 0x1 ++#define CRC_MODE_REPLACE 0x2 ++#define CRC_MODE_PER_PKT_MODE 0x3 ++#define XLMAC_TX_MAC_SA(port) (0x00060500 + port) ++#define XLMAC_RX_MAX_SIZE(port) (0x00060800 + port) ++#define XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_L 13 ++#define XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_R 0 ++#define XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_WIDTH 14 ++#define XLMAC_RX_CTRL(port) (0x00060600 + port) ++#define XLMAC_RX_CTRL__STRIP_CRC 2 ++#define XLMAC_RX_LSS_CTRL(port) (0x00060a00 + port) ++#define XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_LINK_INTERRUPT 6 ++#define XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_REMOTE_FAULT 5 ++#define XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_LOCAL_FAULT 4 ++#define XLMAC_RX_LSS_CTRL__REMOTE_FAULT_DISABLE 1 ++#define XLMAC_RX_LSS_CTRL__LOCAL_FAULT_DISABLE 0 ++#define XLMAC_PAUSE_CTRL(port) (0x00060d00 + port) ++#define XLMAC_PAUSE_CTRL__RX_PAUSE_EN 18 ++#define XLMAC_PAUSE_CTRL__TX_PAUSE_EN 17 ++#define XLMAC_PFC_CTRL(port) (0x00060e00 + port) ++#define XLMAC_PFC_CTRL__PFC_REFRESH_EN 32 ++/* General type registers */ ++#define XLPORT_MODE_REG (0x02020a00) ++#define XLPORT_MODE_REG__RESET_MASK 0x3f ++#define XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_L 5 ++#define XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_R 3 ++#define XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_WIDTH 3 ++#define XPORT0_CORE_PORT_MODE_QUAD 0x0 ++#define XPORT0_CORE_PORT_MODE_TRI_012 0x1 ++#define XPORT0_CORE_PORT_MODE_TRI_023 0x2 ++#define XPORT0_CORE_PORT_MODE_DUAL 0x3 ++#define XPORT0_CORE_PORT_MODE_SINGLE 0x4 ++#define XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_L 2 ++#define XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_R 0 ++#define XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_WIDTH 3 ++#define XPORT0_PHY_PORT_MODE_QUAD 0x0 ++#define XPORT0_PHY_PORT_MODE_TRI_012 0x1 ++#define XPORT0_PHY_PORT_MODE_TRI_023 0x2 ++#define XPORT0_PHY_PORT_MODE_DUAL 0x3 ++#define XPORT0_PHY_PORT_MODE_SINGLE 0x4 ++#define XLPORT_ENABLE_REG (0x02020b00) ++#define XLPORT_ENABLE_REG__PORT3 3 ++#define XLPORT_ENABLE_REG__PORT2 2 ++#define XLPORT_ENABLE_REG__PORT1 1 ++#define XLPORT_ENABLE_REG__PORT0 0 ++#define XLPORT_MAC_CONTROL (0x02021000) ++#define XLPORT_MAC_CONTROL__RX_DUAL_CYCLE_TDM_EN 5 ++#define XLPORT_MAC_CONTROL__RX_NON_LINEAR_QUAD_TDM_EN 3 ++#define XLPORT_MAC_CONTROL__RX_FLEX_TDM_ENABLE 2 ++#define XLPORT_MAC_CONTROL__XMAC0_BYPASS_OSTS 1 ++#define XLPORT_MAC_CONTROL__XMAC0_RESET 0 ++#define XLPORT_XGXS0_CTRL_REG (0x02021400) ++#define XLPORT_XGXS0_CTRL_REG__RefSel 8 ++#define XLPORT_XGXS0_CTRL_REG__RefCMOS 7 ++#define XLPORT_XGXS0_CTRL_REG__Pwrdwn_CML_LC 6 ++#define XLPORT_XGXS0_CTRL_REG__Pwrdwn_CML 5 ++#define XLPORT_XGXS0_CTRL_REG__IDDQ 4 ++#define XLPORT_XGXS0_CTRL_REG__PWRDWN 3 ++#define XLPORT_XGXS0_CTRL_REG__Refin_EN 2 ++#define XLPORT_XGXS0_CTRL_REG__RSTB_HW 0 ++#define XLPORT_WC_UCMEM_CTRL (0x02021900) ++#define XLPORT_WC_UCMEM_CTRL__ACCESS_MODE 0 ++#define XLPORT_MIB_RESET (0x02022400) ++#define XLPORT_MIB_RESET__CLR_CNT_L 3 ++#define XLPORT_MIB_RESET__CLR_CNT_R 0 ++#define XLPORT_INTR_STATUS (0x02022900) ++#define XLPORT_INTR_ENABLE (0x02022a00) ++#define XLPORT_SOFT_RESET (0x02020c00) ++#define XLPORT_SOFT_RESET__PORT3 3 ++#define XLPORT_SOFT_RESET__PORT2 2 ++#define XLPORT_SOFT_RESET__PORT1 1 ++#define XLPORT_SOFT_RESET__PORT0 0 ++#define XLPORT_POWER_SAVE (0x02020d00) ++#define XLPORT_POWER_SAVE__XPORT_CORE0 0 ++ ++#define XLPORT_PORT_FIELD(reg, port) reg##__PORT##port ++#define XLPORT_PORT_FIELD_SET(_r, _p, _v) { \ ++ if (_p == 0) val |= (1 << _r##__PORT0); \ ++ else if (_p == 1) val |= (1 << _r##__PORT1); \ ++ else if (_p == 2) val |= (1 << _r##__PORT2); \ ++ else if (_p == 3) val |= (1 << _r##__PORT3); \ ++} ++ ++#define XLPORT_PORT_FIELD_CLEAR(_r, _p, _v) { \ ++ if (_p == 0) val &= ~(1 << _r##__PORT0); \ ++ else if (_p == 1) val &= ~(1 << _r##__PORT1); \ ++ else if (_p == 2) val &= ~(1 << _r##__PORT2); \ ++ else if (_p == 3) val &= ~(1 << _r##__PORT3); \ ++} ++ ++static u32 pm4x10_enabled = 0; ++ ++static inline void ++xlmac_reg64_write(u32 addr, u64 val) ++{ ++ iproc_cmic_schan_reg64_write(CMIC_BLOCK_TYPE_APM, addr, val); ++} ++ ++static inline u64 ++xlmac_reg64_read(u32 addr) ++{ ++ return iproc_cmic_schan_reg64_read(CMIC_BLOCK_TYPE_APM, addr); ++} ++ ++static inline void ++xlport_reg32_write(u32 addr, u32 val) ++{ ++ iproc_cmic_schan_reg32_write(CMIC_BLOCK_TYPE_APM, addr, val); ++} ++ ++static inline u32 ++xlport_reg32_read(u32 addr) ++{ ++ return iproc_cmic_schan_reg32_read(CMIC_BLOCK_TYPE_APM, addr); ++} ++ ++ ++/* MDIO address for each lane in this PM */ ++static u32 lane_mdio_addr[4] = { 3, 4, 5, 6 }; ++ ++static inline void ++pm_phy_sbus_write(u32 lane, u32 addr, u32 val, u32 mask, u32 shift) ++{ ++ u32 device, mem_data[4]; ++ ++ /* TSC register address (indirect access) */ ++ if ((addr == 0x0002) || (addr == 0x0003) || ((addr <= 0xc340) && (addr >= 0x9000))) ++ device = 0; /* PCS (TSC) */ ++ else ++ device = 1; /* PMA/PMD (Physical Media Device or called serdes(merlin)) */ ++ ++ mem_data[0] = (device << 27) | (lane_mdio_addr[lane] << 19) | (lane << 16) | addr; ++ mem_data[1] = ((val << shift) << 16) | /* data */ ++ (~(mask << shift) & 0xffff); /* mask */ ++ mem_data[2] = TSC_OPERATION_WRITE; ++ mem_data[3] = 0; ++ iproc_cmic_schan_ucmem_write(CMIC_BLOCK_TYPE_APM, mem_data); ++ } ++ ++static inline u32 ++pm_phy_sbus_read(u32 lane, u32 addr, u32 *val) ++{ ++ u32 device, mem_data[4]; ++ ++ /* TSC register address (indirect access) */ ++ if ((addr == 0x0002) || (addr == 0x0003) || ((addr <= 0xc340) && (addr >= 0x9000))) ++ device = 0; /* PCS (TSC) */ ++ else ++ device = 1; /* PMA/PMD (Physical Media Device or called serdes(merlin)) */ ++ ++ mem_data[0] = (device << 27) | (lane_mdio_addr[lane] << 19) | (lane << 16) | addr; ++ mem_data[1] = 0; ++ mem_data[2] = TSC_OPERATION_READ; ++ mem_data[3] = 0; ++ iproc_cmic_schan_ucmem_write(CMIC_BLOCK_TYPE_APM, mem_data); ++ *val = iproc_cmic_schan_ucmem_read(CMIC_BLOCK_TYPE_APM, mem_data); ++ return 0; ++} ++ ++ ++static void cmpw(u8 readonly, u32 addr, u32 val) ++{ ++ u8 i; ++ ++ if (readonly) ++ { ++ //printk("(read only) Reg addr = 0x%x, current = 0x%x, expect = 0x%x\n", reg_addr, get_val, reg_data_val); ++ } else ++ { ++ //printk("(write) Reg addr = 0x%x, current = 0x%x, expect = 0x%x\n", reg_addr, get_val, reg_data_val); ++ for (i=0; i<4; ++i) /* per lane */ ++ if ((i % 2) == 0) ++ pm_phy_sbus_write(i, addr, val, 0xffff, 0); ++ } ++} ++ ++static inline u32 ++pm_phy_configure(int port) ++{ ++ cmpw(0, 0x0002, 0x600d); cmpw(0, 0x0003, 0x8770); cmpw(0, 0x000d, 0x0000); cmpw(0, 0x000e, 0x0000); ++ cmpw(0, 0x0096, 0x0000); cmpw(0, 0x0097, 0x0000); cmpw(0, 0x0098, 0x0000); cmpw(0, 0x0099, 0x0000); ++ cmpw(0, 0x009a, 0x0000); cmpw(0, 0x009b, 0x0000); cmpw(0, 0x9000, 0x6000); cmpw(0, 0x9001, 0x00aa); ++ cmpw(0, 0x9003, 0xe4e4); cmpw(0, 0x9004, 0x0083); cmpw(0, 0x9005, 0x0000); cmpw(0, 0x9007, 0x0000); ++ cmpw(0, 0x9008, 0x0000); cmpw(0, 0x9009, 0x0000); cmpw(0, 0x900a, 0xf800); cmpw(0, 0x900e, 0x0312); ++ cmpw(0, 0x9010, 0x0003); cmpw(0, 0x9011, 0x0000); cmpw(1, 0x9012, 0x0002); cmpw(1, 0x9013, 0x0002); ++ cmpw(0, 0x9014, 0x0000); cmpw(0, 0x9030, 0x0000); cmpw(0, 0x9031, 0x0028); cmpw(0, 0x9032, 0x0000); ++ cmpw(0, 0x9033, 0x0000); cmpw(0, 0x9034, 0x0000); cmpw(0, 0x9035, 0x0000); cmpw(0, 0x9037, 0x0000); ++ cmpw(0, 0x9038, 0x0000); cmpw(0, 0x9039, 0x0000); cmpw(0, 0x903a, 0x0000); cmpw(0, 0x903b, 0x0000); ++ cmpw(0, 0x903c, 0x0000); cmpw(0, 0x903d, 0x0000); cmpw(0, 0x903e, 0x0000); cmpw(0, 0x9040, 0x0000); ++ cmpw(0, 0x9041, 0x0000); cmpw(0, 0x9042, 0x0000); cmpw(0, 0x9043, 0x0000); cmpw(0, 0x9044, 0x0000); ++ cmpw(0, 0x9045, 0x0000); cmpw(0, 0x9050, 0x0000); cmpw(0, 0x9051, 0x0000); cmpw(0, 0x9052, 0x0000); ++ cmpw(0, 0x9053, 0x0000); cmpw(0, 0x9054, 0x0000); cmpw(0, 0x9055, 0x0000); cmpw(0, 0x9056, 0x0000); ++ cmpw(0, 0x9057, 0x0000); cmpw(0, 0x9058, 0x0000); cmpw(0, 0x9059, 0x0000); cmpw(0, 0x905a, 0x0000); ++ cmpw(0, 0x9060, 0x0000); cmpw(0, 0x9061, 0x0000); cmpw(0, 0x9062, 0x0000); cmpw(1, 0x90b1, 0x0000); ++ cmpw(0, 0x90b3, 0x0000); cmpw(0, 0x90b4, 0x001d); cmpw(0, 0x90b5, 0xffff); cmpw(0, 0x9123, 0x3fff); ++ cmpw(0, 0x9130, 0x7690); cmpw(0, 0x9131, 0xc4f0); cmpw(0, 0x9132, 0xe647); cmpw(0, 0x9140, 0x0000); ++ cmpw(0, 0x9141, 0x0000); cmpw(0, 0x9142, 0x0000); cmpw(0, 0x9220, 0x0101); cmpw(0, 0x9221, 0x6140); ++ cmpw(0, 0x9222, 0xeea7); cmpw(0, 0x9230, 0x4010); cmpw(0, 0x9231, 0x0400); cmpw(0, 0x9232, 0x0041); ++ cmpw(0, 0x9233, 0x8090); cmpw(0, 0x9234, 0xa0b0); cmpw(0, 0x9235, 0xc0d0); cmpw(0, 0x9236, 0xe070); ++ cmpw(0, 0x9237, 0x0001); cmpw(0, 0x9238, 0xf0f0); cmpw(0, 0x9239, 0xf0f0); cmpw(0, 0x923a, 0xf0f0); ++ cmpw(0, 0x923b, 0xf0f0); cmpw(0, 0x923c, 0x0003); cmpw(0, 0x9240, 0x0000); cmpw(0, 0x9241, 0x0000); ++ cmpw(0, 0x9242, 0x0000); cmpw(0, 0x9243, 0x0000); cmpw(0, 0x9244, 0x0000); cmpw(0, 0x9245, 0x0000); ++ cmpw(0, 0x9246, 0x0000); cmpw(0, 0x9247, 0x0000); cmpw(0, 0x9248, 0x0000); cmpw(0, 0x9251, 0x029a); ++ cmpw(0, 0x9252, 0x0000); cmpw(0, 0x9253, 0x10ed); cmpw(0, 0x9254, 0x0000); cmpw(0, 0x9255, 0x14d4); ++ cmpw(0, 0x9256, 0x029a); cmpw(0, 0x9257, 0x8382); cmpw(0, 0x9258, 0x0bb8); cmpw(0, 0x9259, 0x0a6a); ++ cmpw(0, 0x925a, 0x029a); cmpw(0, 0x925b, 0x0a6a); cmpw(0, 0x925c, 0x029a); cmpw(0, 0x925d, 0x3b5f); ++ cmpw(0, 0x925e, 0x006b); cmpw(0, 0x9260, 0x0000); cmpw(0, 0x9261, 0x0000); cmpw(0, 0x9262, 0x00ff); ++ cmpw(0, 0x9263, 0x0002); cmpw(0, 0x9264, 0x0000); cmpw(0, 0x9270, 0xff00); cmpw(0, 0x9272, 0x0000); ++ cmpw(0, 0x9273, 0x0000); cmpw(0, 0x9274, 0x0400); cmpw(0, 0x9275, 0x0000); cmpw(0, 0x9276, 0x0000); ++ cmpw(0, 0x9277, 0x0000); cmpw(0, 0x9278, 0x0000); cmpw(0, 0x9279, 0x0000); cmpw(0, 0x927a, 0x0000); ++ cmpw(0, 0x9280, 0xff00); cmpw(0, 0x9282, 0x0000); cmpw(0, 0x9283, 0x0000); cmpw(0, 0x9284, 0x0400); ++ cmpw(0, 0x9285, 0x0000); cmpw(0, 0x9286, 0x0000); cmpw(0, 0x9287, 0x0000); cmpw(0, 0x9288, 0x0000); ++ cmpw(0, 0x9289, 0x0000); cmpw(0, 0x928a, 0x0000); cmpw(0, 0x9290, 0xff00); cmpw(0, 0x9292, 0x0000); ++ cmpw(0, 0x9293, 0x0000); cmpw(0, 0x9294, 0x0400); cmpw(0, 0x9295, 0x0000); cmpw(0, 0x9296, 0x0000); ++ cmpw(0, 0x9297, 0x0000); cmpw(0, 0x9298, 0x0000); cmpw(0, 0x9299, 0x0000); cmpw(0, 0x929a, 0x0000); ++ cmpw(0, 0x92a0, 0xff00); cmpw(0, 0x92a2, 0x0000); cmpw(0, 0x92a3, 0x0000); cmpw(0, 0x92a4, 0x0400); ++ cmpw(0, 0x92a5, 0x0000); cmpw(0, 0x92a6, 0x0000); cmpw(0, 0x92a7, 0x0000); cmpw(0, 0x92a8, 0x0000); ++ cmpw(0, 0x92a9, 0x0000); cmpw(0, 0x92aa, 0x0000); cmpw(0, 0xa000, 0xfffc); cmpw(0, 0xa001, 0x8030); ++ cmpw(0, 0xa002, 0x0070); cmpw(0, 0xa003, 0x0064); cmpw(1, 0xa011, 0x0812); cmpw(0, 0xa020, 0x0000); ++ cmpw(0, 0xa021, 0x0000); cmpw(0, 0xa022, 0x0000); cmpw(0, 0xa023, 0x1400); cmpw(0, 0xa024, 0x030f); ++ cmpw(0, 0xa031, 0x0000); cmpw(0, 0xa032, 0x0000); cmpw(0, 0xa080, 0x0000); cmpw(0, 0xa081, 0x0000); ++ cmpw(0, 0xa085, 0x0000); cmpw(0, 0xa086, 0x8000); cmpw(0, 0xc010, 0xc003); cmpw(0, 0xc011, 0x0000); ++ cmpw(1, 0xc012, 0x000e); cmpw(0, 0xc013, 0x000c); cmpw(0, 0xc014, 0x0000); cmpw(0, 0xc018, 0x0000); ++ cmpw(0, 0xc019, 0x0000); cmpw(0, 0xc040, 0x0000); cmpw(0, 0xc041, 0x0000); cmpw(0, 0xc042, 0x0000); ++ cmpw(0, 0xc043, 0x0000); ++ //cmpw(0, 0xc050, 0x0135); /* speed = 10M */ ++ //cmpw(0, 0xc050, 0x0136); /* speed = 100M */ ++ cmpw(0, 0xc050, 0x0137); /* speed = 1000M */ ++ //cmpw(0, 0xc050, 0x011c); /* speed = 10G */ ++ cmpw(1, 0xc051, 0x0000); cmpw(0, 0xc052, 0x0000); cmpw(1, 0xc054, 0xef62); cmpw(0, 0xc055, 0x0000); ++ cmpw(0, 0xc058, 0x0000); cmpw(0, 0xc060, 0x0000); cmpw(0, 0xc061, 0x0000); cmpw(0, 0xc070, 0x1c00); ++ cmpw(0, 0xc072, 0x0e05); cmpw(0, 0xc073, 0x0830); cmpw(0, 0xc074, 0x0010); cmpw(0, 0xc075, 0x0021); ++ cmpw(0, 0xc076, 0x0000); cmpw(0, 0xc077, 0x0040); cmpw(0, 0xc078, 0x0004); cmpw(0, 0xc079, 0x0000); ++ cmpw(0, 0xc07a, 0x0000); cmpw(0, 0xc100, 0x0000); cmpw(0, 0xc101, 0x0000); cmpw(0, 0xc102, 0x0000); ++ cmpw(0, 0xc103, 0x0000); cmpw(0, 0xc104, 0x0000); cmpw(0, 0xc105, 0x0000); cmpw(0, 0xc111, 0x0000); ++ cmpw(0, 0xc112, 0x01b4); cmpw(0, 0xc113, 0x01cb); cmpw(0, 0xc114, 0x0000); cmpw(1, 0xc120, 0x4811); ++ cmpw(1, 0xc121, 0x0084); cmpw(0, 0xc130, 0x0000); cmpw(0, 0xc131, 0x2000); cmpw(0, 0xc132, 0x442c); ++ cmpw(0, 0xc133, 0x0000); cmpw(0, 0xc134, 0x0870); cmpw(0, 0xc135, 0x0000); cmpw(0, 0xc136, 0x0000); ++ cmpw(0, 0xc137, 0x0001); cmpw(0, 0xc139, 0x0000); cmpw(0, 0xc13d, 0x14a0); cmpw(0, 0xc140, 0x0000); ++ cmpw(0, 0xc141, 0x0000); cmpw(0, 0xc142, 0x0000); cmpw(0, 0xc143, 0x0000); cmpw(0, 0xc144, 0x0000); ++ cmpw(0, 0xc145, 0x0000); cmpw(0, 0xc146, 0x0000); cmpw(0, 0xc147, 0x0000); cmpw(0, 0xc148, 0x0000); ++ cmpw(0, 0xc149, 0x0000); cmpw(0, 0xc14a, 0x0000); cmpw(0, 0xc14b, 0x0000); cmpw(0, 0xc14c, 0x0000); ++ cmpw(0, 0xc14d, 0x0000); cmpw(0, 0xc14e, 0x0000); cmpw(0, 0xc152, 0x0000); cmpw(0, 0xc153, 0x0000); ++ cmpw(0, 0xc154, 0x0000); cmpw(0, 0xc155, 0x0000); cmpw(0, 0xc156, 0x0000); cmpw(0, 0xc157, 0x0000); ++ cmpw(0, 0xc158, 0x0000); cmpw(0, 0xc159, 0x0000); cmpw(0, 0xc15a, 0x0000); cmpw(0, 0xc15b, 0x0000); ++ cmpw(0, 0xc15c, 0x0000); cmpw(0, 0xc161, 0x0000); cmpw(0, 0xc162, 0x0000); cmpw(0, 0xc163, 0x0000); ++ cmpw(0, 0xc170, 0x0000); cmpw(0, 0xc171, 0x0000); cmpw(0, 0xc172, 0x0000); cmpw(0, 0xc173, 0x0000); ++ cmpw(0, 0xc174, 0x0000); cmpw(0, 0xc175, 0x0000); cmpw(0, 0xc176, 0x0000); cmpw(0, 0xc177, 0x0000); ++ cmpw(0, 0xc178, 0x0000); cmpw(0, 0xc179, 0x0000); cmpw(0, 0xc17a, 0x0000); cmpw(0, 0xc17b, 0x0000); ++ cmpw(0, 0xc17c, 0x0000); cmpw(0, 0xc17d, 0x0000); cmpw(0, 0xc180, 0x0000); cmpw(0, 0xc181, 0x0056); ++ cmpw(0, 0xc182, 0x0005); cmpw(0, 0xc183, 0x2000); cmpw(0, 0xc184, 0x0001); cmpw(0, 0xc185, 0x02a1); ++ cmpw(0, 0xc186, 0x0168); cmpw(0, 0xc187, 0x0000); cmpw(0, 0xc188, 0x0000); cmpw(0, 0xc190, 0x0000); ++ cmpw(0, 0xc191, 0x0000); cmpw(0, 0xc192, 0x0000); cmpw(0, 0xc193, 0x0000); cmpw(0, 0xc194, 0x0000); ++ cmpw(0, 0xc195, 0x0000); cmpw(0, 0xc196, 0x0000); cmpw(0, 0xc197, 0x0000); cmpw(0, 0xc198, 0x0000); ++ cmpw(0, 0xc199, 0x0000); cmpw(0, 0xc19a, 0x0000); cmpw(0, 0xc1a0, 0x0000); cmpw(0, 0xc1a1, 0x0000); ++ cmpw(0, 0xc1a2, 0x0000); cmpw(0, 0xc1a3, 0x0000); cmpw(0, 0xc1a4, 0x0000); cmpw(0, 0xc1a5, 0x0000); ++ cmpw(0, 0xc1a6, 0x0000); cmpw(0, 0xc1a7, 0x0000); cmpw(0, 0xc1a8, 0x0000); cmpw(0, 0xc1a9, 0x0000); ++ cmpw(0, 0xc1aa, 0x0000); cmpw(0, 0xc1ab, 0x0030); cmpw(0, 0xc1ac, 0x0000); cmpw(0, 0xc1ad, 0x0001); ++ cmpw(0, 0xc1ae, 0x0000); cmpw(0, 0xc253, 0x4000); cmpw(0, 0xc30a, 0x0000); cmpw(0, 0xc30b, 0x0000); ++ cmpw(0, 0xc330, 0x0002); cmpw(0, 0xc340, 0x0011); cmpw(0, 0xd001, 0x0205); cmpw(0, 0xd002, 0x0690); ++ cmpw(0, 0xd003, 0x00f0); cmpw(0, 0xd004, 0x2401); cmpw(1, 0xd005, 0xf07c); cmpw(1, 0xd006, 0x0002); ++ cmpw(1, 0xd007, 0x6969); cmpw(1, 0xd008, 0x3414); cmpw(1, 0xd009, 0x5878); cmpw(1, 0xd00a, 0x00e0); ++ cmpw(0, 0xd00b, 0x0060); cmpw(0, 0xd00d, 0x0805); cmpw(0, 0xd00e, 0x0000); cmpw(0, 0xd010, 0x0028); ++ cmpw(0, 0xd011, 0x0200); cmpw(0, 0xd012, 0x0087); cmpw(0, 0xd013, 0x1c1e); cmpw(0, 0xd014, 0x35ad); ++ cmpw(0, 0xd015, 0x35af); cmpw(0, 0xd016, 0x340d); cmpw(0, 0xd017, 0x0000); cmpw(0, 0xd018, 0x0011); ++ cmpw(0, 0xd019, 0x0000); cmpw(1, 0xd01a, 0x0004); cmpw(1, 0xd01b, 0x0dff); cmpw(1, 0xd01c, 0x0000); ++ cmpw(1, 0xd01d, 0x0000); cmpw(1, 0xd01e, 0x0880); cmpw(0, 0xd020, 0x0000); cmpw(0, 0xd021, 0x0000); ++ cmpw(0, 0xd022, 0x0000); cmpw(0, 0xd023, 0x0000); cmpw(0, 0xd024, 0x0000); cmpw(0, 0xd025, 0x0000); ++ cmpw(0, 0xd026, 0x0000); cmpw(0, 0xd027, 0x8400); cmpw(0, 0xd029, 0x0000); cmpw(0, 0xd02a, 0x0000); ++ cmpw(0, 0xd02b, 0x2e02); cmpw(0, 0xd02c, 0x0000); cmpw(0, 0xd02d, 0x0000); cmpw(0, 0xd02e, 0xc400); ++ cmpw(0, 0xd030, 0xa404); cmpw(0, 0xd031, 0x2060); cmpw(0, 0xd032, 0x0100); cmpw(0, 0xd033, 0x0000); ++ cmpw(1, 0xd034, 0xfff0); cmpw(1, 0xd035, 0x00d0); cmpw(1, 0xd036, 0xfffa); cmpw(1, 0xd037, 0x0096); ++ cmpw(1, 0xd038, 0x000b); cmpw(1, 0xd039, 0x0108); cmpw(1, 0xd03a, 0x2118); cmpw(1, 0xd03b, 0x0000); ++ cmpw(1, 0xd03c, 0x0000); cmpw(1, 0xd03d, 0x0000); cmpw(1, 0xd03e, 0x009f); cmpw(0, 0xd040, 0x00b8); ++ cmpw(0, 0xd041, 0x0000); cmpw(0, 0xd042, 0x0001); cmpw(0, 0xd050, 0x0004); cmpw(0, 0xd051, 0x0052); ++ cmpw(0, 0xd052, 0x0310); cmpw(0, 0xd053, 0x0000); cmpw(0, 0xd054, 0x0000); cmpw(0, 0xd055, 0x0000); ++ cmpw(0, 0xd056, 0x0000); cmpw(0, 0xd060, 0x0000); cmpw(0, 0xd061, 0x0000); cmpw(0, 0xd062, 0x0000); ++ cmpw(0, 0xd063, 0x0004); cmpw(0, 0xd064, 0x0a00); cmpw(0, 0xd065, 0x0032); cmpw(1, 0xd066, 0x0002); ++ cmpw(0, 0xd067, 0x03f5); cmpw(0, 0xd070, 0x0000); cmpw(0, 0xd071, 0x0000); cmpw(0, 0xd072, 0x0000); ++ cmpw(0, 0xd073, 0x3100); cmpw(0, 0xd074, 0x0004); cmpw(0, 0xd075, 0x0004); cmpw(0, 0xd078, 0x0000); ++ cmpw(0, 0xd079, 0x0000); cmpw(0, 0xd07a, 0x0000); cmpw(0, 0xd07b, 0x0000); cmpw(0, 0xd07c, 0x0000); ++ cmpw(1, 0xd07d, 0x0002); ++ //cmpw(0, 0xd080, 0x8008); /* speed = 10M */ ++ //cmpw(0, 0xd080, 0x8008); /* speed = 100M */ ++ cmpw(0, 0xd080, 0x8008); /* speed = 1000M */ ++ //cmpw(0, 0xd080, 0x8000); /* speed = 10G */ ++ cmpw(0, 0xd081, 0x0001); cmpw(0, 0xd083, 0x0000); cmpw(0, 0xd085, 0x0000); cmpw(0, 0xd086, 0x0000); ++ cmpw(1, 0xd089, 0x0000); cmpw(0, 0xd08a, 0x0000); cmpw(1, 0xd08b, 0x0000); cmpw(1, 0xd08c, 0x0000); ++ cmpw(0, 0xd08e, 0x0001); cmpw(0, 0xd090, 0x1c40); cmpw(0, 0xd091, 0x1048); cmpw(0, 0xd092, 0x7e92); ++ cmpw(0, 0xd093, 0x288f); cmpw(0, 0xd094, 0x0820); cmpw(0, 0xd095, 0x07a0); cmpw(0, 0xd096, 0x14f8); ++ cmpw(0, 0xd097, 0x0121); cmpw(0, 0xd098, 0x0000); cmpw(0, 0xd099, 0x0088); cmpw(0, 0xd0a0, 0x2800); ++ cmpw(0, 0xd0a1, 0x0744); cmpw(0, 0xd0a2, 0x5250); cmpw(0, 0xd0a3, 0x1556); cmpw(0, 0xd0a4, 0x0000); ++ cmpw(0, 0xd0a5, 0x2800); cmpw(0, 0xd0a6, 0x0001); cmpw(0, 0xd0a7, 0x0aa0); cmpw(0, 0xd0a8, 0x0000); ++ cmpw(0, 0xd0a9, 0x0000); cmpw(0, 0xd0aa, 0x0088); cmpw(0, 0xd0b0, 0x2480); cmpw(0, 0xd0b1, 0x0007); ++ cmpw(0, 0xd0b2, 0x0080); cmpw(0, 0xd0b3, 0x460e); cmpw(0, 0xd0b4, 0x0501); cmpw(0, 0xd0b5, 0x1405); ++ cmpw(0, 0xd0b6, 0x0000); cmpw(0, 0xd0b7, 0x0000); cmpw(0, 0xd0b8, 0x4442); cmpw(0, 0xd0b9, 0x5285); ++ cmpw(0, 0xd0ba, 0x0015); cmpw(0, 0xd0be, 0x0000); cmpw(0, 0xd0bf, 0x0001); cmpw(0, 0xd0c0, 0x5229); ++ cmpw(0, 0xd0c1, 0x0008); cmpw(0, 0xd0c2, 0xfd29); cmpw(1, 0xd0c8, 0x0333); cmpw(1, 0xd0c9, 0x0303); ++ cmpw(1, 0xd0ca, 0x0000); cmpw(1, 0xd0cb, 0x0001); cmpw(1, 0xd0cc, 0x0009); cmpw(0, 0xd0d0, 0x0602); ++ cmpw(0, 0xd0d1, 0x002a); cmpw(0, 0xd0d2, 0x000e); cmpw(0, 0xd0d3, 0x0000); cmpw(0, 0xd0d4, 0x0000); ++ cmpw(0, 0xd0d5, 0x0000); cmpw(0, 0xd0d6, 0x0000); cmpw(0, 0xd0d7, 0x0000); cmpw(0, 0xd0d8, 0x0002); ++ cmpw(0, 0xd0d9, 0x0000); cmpw(0, 0xd0da, 0x8000); cmpw(0, 0xd0db, 0x0000); cmpw(0, 0xd0dc, 0x0000); ++ cmpw(0, 0xd0e0, 0x0000); cmpw(0, 0xd0e1, 0x000a); cmpw(0, 0xd0e2, 0x0002); cmpw(0, 0xd0e3, 0x0000); ++ cmpw(0, 0xd0e8, 0x0002); cmpw(0, 0xd0f0, 0x0363); cmpw(0, 0xd0f1, 0x0001); cmpw(0, 0xd0f2, 0x0000); ++ cmpw(0, 0xd0f3, 0x0000); cmpw(0, 0xd0f4, 0xa271); cmpw(0, 0xd0f5, 0x0000); cmpw(0, 0xd0f6, 0x0000); ++ cmpw(0, 0xd0f7, 0x8604); cmpw(1, 0xd0f8, 0x0000); cmpw(1, 0xd0f9, 0x001c); cmpw(1, 0xd0fa, 0x403c); ++ cmpw(0, 0xd0fe, 0x0000); cmpw(0, 0xd100, 0xff00); cmpw(0, 0xd101, 0xff00); cmpw(0, 0xd102, 0xff00); ++ cmpw(0, 0xd103, 0xff00); cmpw(0, 0xd104, 0xff00); cmpw(0, 0xd105, 0xff00); cmpw(0, 0xd106, 0xff00); ++ cmpw(0, 0xd107, 0xff00); cmpw(0, 0xd108, 0xff00); cmpw(0, 0xd109, 0xff00); cmpw(0, 0xd10a, 0xff00); ++ cmpw(0, 0xd10b, 0xff00); cmpw(0, 0xd10c, 0xff00); cmpw(0, 0xd10d, 0xff00); cmpw(0, 0xd10e, 0xff00); ++ cmpw(0, 0xd110, 0x0000); cmpw(0, 0xd111, 0x0020); cmpw(1, 0xd112, 0x0000); cmpw(0, 0xd113, 0xc140); ++ cmpw(0, 0xd11b, 0x00aa); cmpw(0, 0xd11c, 0x4155); cmpw(0, 0xd11d, 0x4914); cmpw(0, 0xd11e, 0x000f); ++ cmpw(0, 0xd120, 0x1ffa); cmpw(0, 0xd121, 0xfff0); cmpw(0, 0xd122, 0x0fff); cmpw(0, 0xd123, 0x1007); ++ cmpw(0, 0xd124, 0x8240); cmpw(0, 0xd125, 0x8160); cmpw(0, 0xd126, 0x0000); cmpw(1, 0xd128, 0x4f52); ++ cmpw(1, 0xd129, 0x1fdb); cmpw(1, 0xd12a, 0xbffd); cmpw(1, 0xd12b, 0xfff3); cmpw(1, 0xd12c, 0xfff3); ++ cmpw(1, 0xd12d, 0x23ff); cmpw(1, 0xd12e, 0x5288); cmpw(0, 0xd130, 0x01f4); cmpw(0, 0xd131, 0x00c8); ++ cmpw(1, 0xd141, 0x003f); cmpw(1, 0xd142, 0x0003); cmpw(1, 0xd143, 0x0000); cmpw(1, 0xd144, 0x003f); ++ cmpw(1, 0xd145, 0x0003); cmpw(1, 0xd146, 0x0000); cmpw(1, 0xd147, 0x0010); cmpw(0, 0xd150, 0x0000); ++ cmpw(0, 0xd151, 0x0101); cmpw(0, 0xd152, 0x0202); cmpw(0, 0xd153, 0x0303); cmpw(0, 0xd161, 0x0000); ++ cmpw(0, 0xd162, 0x0000); cmpw(0, 0xd163, 0x0000); cmpw(0, 0xd164, 0x0003); cmpw(0, 0xd167, 0x0000); ++ cmpw(0, 0xd168, 0x041c); cmpw(1, 0xd16c, 0x0000); cmpw(0, 0xd171, 0x0000); cmpw(0, 0xd172, 0x0000); ++ cmpw(0, 0xd174, 0x0003); cmpw(0, 0xd177, 0x0000); cmpw(1, 0xd17c, 0x0000); cmpw(0, 0xd17d, 0x0001); ++ cmpw(0, 0xd180, 0x8000); cmpw(0, 0xd181, 0x0001); cmpw(0, 0xd183, 0x0000); cmpw(1, 0xd185, 0x0000); ++ cmpw(0, 0xd186, 0x0000); cmpw(1, 0xd189, 0x0000); cmpw(1, 0xd18a, 0x0000); cmpw(1, 0xd18b, 0x0000); ++ cmpw(1, 0xd18c, 0x0000); cmpw(0, 0xd18e, 0x0001); cmpw(0, 0xd190, 0x8000); cmpw(0, 0xd191, 0x0001); ++ cmpw(0, 0xd193, 0x0000); cmpw(1, 0xd195, 0x0000); cmpw(0, 0xd196, 0x0000); cmpw(1, 0xd199, 0x0000); ++ cmpw(0, 0xd19a, 0x0000); cmpw(1, 0xd19b, 0x0000); cmpw(1, 0xd19c, 0x0000); cmpw(0, 0xd19e, 0x0001); ++ cmpw(0, 0xd200, 0x0003); cmpw(0, 0xd201, 0x000b); cmpw(0, 0xd202, 0x0011); cmpw(0, 0xd200, 0x0003); ++ cmpw(1, 0xd203, 0x0001); cmpw(0, 0xd204, 0x0800); cmpw(0, 0xd205, 0x2000); cmpw(0, 0xd206, 0x0200); ++ cmpw(0, 0xd207, 0x0000); cmpw(0, 0xd208, 0x0800); cmpw(0, 0xd209, 0x2000); cmpw(1, 0xd20a, 0x0200); ++ cmpw(1, 0xd20b, 0x0000); cmpw(0, 0xd20c, 0x0000); cmpw(0, 0xd20d, 0x0000); cmpw(0, 0xd20e, 0x0000); ++ cmpw(1, 0xd210, 0x02ec); cmpw(0, 0xd211, 0x0000); cmpw(0, 0xd212, 0x0000); cmpw(1, 0xd213, 0x0000); ++ cmpw(1, 0xd214, 0x0000); cmpw(0, 0xd215, 0x0000); cmpw(0, 0xd216, 0x0007); cmpw(1, 0xd217, 0x0000); ++ cmpw(1, 0xd218, 0x0802); cmpw(1, 0xd219, 0x0802); cmpw(1, 0xd21a, 0x7a90); cmpw(0, 0xd21b, 0x0000); ++ cmpw(0, 0xd220, 0x0000); cmpw(0, 0xd221, 0x0000); cmpw(1, 0xd222, 0x0000); cmpw(1, 0xd223, 0x0018); ++ cmpw(0, 0xd224, 0x0000); cmpw(0, 0xd225, 0x8401); cmpw(0, 0xd226, 0x0000); cmpw(1, 0xd227, 0x0000); ++ cmpw(0, 0xd228, 0x0101); cmpw(0, 0xd229, 0x0000); cmpw(1, 0xd22a, 0x0007); cmpw(0, 0xffdc, 0x001f); ++ cmpw(0, 0xffdd, 0x404d); cmpw(0, 0xffde, 0x0000); cmpw(0, 0xffdf, 0x0000); ++} ++ ++ ++static inline u32 ++pm_ucode_download(u8 *ucode_image, u16 ucode_len) ++{ ++ u32 get_val; ++ u8 i, wrdata_lsb; ++ u16 wrdata_lsw, ucode_len_padded, count = 0; ++ ++ /* Check array pointer */ ++ if (ucode_image == (u8 *)NULL) { ++ printk("uCode Image is empty !!\n"); ++ return -1; ++ } ++ ++ /* Check ucode size */ ++ if (ucode_len > (32768)) { /* 16 x 2048 */ ++ printk("Can't fit all of the firmware into the device load table(max = 16 x 2048 bytes) \n"); ++ return -1; ++ } ++ ++ //[1] EFUN(wrc_micro_master_clk_en(0x1)); /* Enable clock to microcontroller subsystem */ ++ /* [0xd200] Write to Clock control register 0 to enable micro core clock (m0) */ ++ pm_phy_sbus_write(0, 0xd200, 0x0001, 0x0001, 0); ++ ++ //[2] EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ ++ /* [0xd201] Write to Reset control registers 0 to make micro_master_rstb = 1 */ ++ pm_phy_sbus_write(0, 0xd201, 0x0001, 0x0001, 0); ++ ++ //[3] EFUN(wrc_micro_master_rstb(0x0)); /* Assert reset to microcontroller sybsystem - Toggling reset */ ++ /* [0xd201] Write to Reset control registers 0 to make micro_master_rstb = 0 */ ++ pm_phy_sbus_write(0, 0xd201, 0x0000, 0x0001, 0); ++ ++ //[4] EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ ++ /* [0xd201] Write to Reset control registers 0 to make micro_master_rstb = 1 */ ++ pm_phy_sbus_write(0, 0xd201, 0x0001, 0x0001, 0); ++ ++ //[5] EFUN(wrc_micro_ra_init(0x1)); /* Set initialization command to initialize code RAM */ ++ /* [0xd202] Write to rmi to ahb control register 0 to initialize code RAMs */ ++ pm_phy_sbus_write(0, 0xd202, 0x0001, 0x0003, 8); ++ ++ //[6] EFUN(merlin16_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll for micro_ra_initdone = 1 to indicate initialization done */ ++ /* [0xd203] Read from ahb status register 0 to make sure all are done */ ++ for (i=0; i<100; ++i) ++ { ++ pm_phy_sbus_read(0, 0xd203, &get_val); ++ if (get_val == 0x1) /* code/data RAM initialization process is complete */ ++ break; ++ udelay(2500); ++ } ++ if (i == 100) ++ { ++ printk("code/data RAM initialization process is timeout !!\n"); ++ return -1; ++ } ++ ++ //[7] EFUN(wrc_micro_ra_init(0x0)); /* Clear initialization command */ ++ /* [0xd202] Write to rmi to ahb control register 0 to clear intialize code/data RAM command */ ++ pm_phy_sbus_write(0, 0xd202, 0x0000, 0x0003, 8); ++ ++ ucode_len_padded = ((ucode_len + 3) & 0xFFFC); /* Aligning ucode size to 4-byte boundary */ ++ ++ /* Code to Load microcode */ ++ //[8] EFUN(wrc_micro_autoinc_wraddr_en(0x1)); /* To auto increment RAM write address */ ++ /* [0xd202] Write to rmi to ahb control register 0 to make Automatic increment write address enable */ ++ pm_phy_sbus_write(0, 0xd202, 0x0001, 0x0001, 12); ++ ++ //[9] EFUN(wrc_micro_ra_wrdatasize(0x1)); /* Select 16bit transfers */ ++ /* [0xd202] Write to rmi to ahb control register 0 to select write data size = 16 bits */ ++ pm_phy_sbus_write(0, 0xd202, 0x0001, 0x0003, 0); ++ ++ //[10] EFUN(wrc_micro_ra_wraddr_msw(0x0)); /* Upper 16bits of start address of Program RAM where the ucode is to be loaded */ ++ /* [0xd205] Write to rmi to ahb write address MSW (bits 31:16) register with 0 */ ++ pm_phy_sbus_write(0, 0xd205, 0x0000, 0xffff, 0); ++ ++ //[11] EFUN(wrc_micro_ra_wraddr_lsw(0x0)); /* Lower 16bits of start address of Program RAM where the ucode is to be loaded */ ++ /* [0xd206] Write to rmi to ahb write data LSW (bits 15:0) register with 0 (starting address = 0x0) */ ++ pm_phy_sbus_write(0, 0xd206, 0x0000, 0xffff, 0); ++ ++ do { /* ucode_image loaded 16bits at a time */ ++ /* wrdata_lsb read from ucode_image; zero padded to 4byte boundary */ ++ wrdata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; ++ count++; ++ /* wrdata_msb read from ucode_image; zero padded to 4byte boundary */ ++ wrdata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; ++ count++; ++ /* 16bit wrdata_lsw formed from 8bit msb and lsb values read from ucode_image */ ++ wrdata_lsw = ((wrdata_lsw << 8) | wrdata_lsb); ++ ++ //[12] EFUN(wrc_micro_ra_wrdata_lsw(wrdata_lsw)); /* Program RAM lower 16bits write data */ ++ /* [0xd206] Write to rmi to ahb write data LSW (bits 15:0) register with data */ ++ pm_phy_sbus_write(0, 0xd206, wrdata_lsw, 0xffff, 0); ++ } while (count < ucode_len_padded); /* Loop repeated till entire image loaded (upto the 4byte boundary) */ ++ ++ //[13] EFUN(wrc_micro_ra_wrdatasize(0x2)); /* Select 32bit transfers as default */ ++ /* [0xd202] Write to rmi to ahb control register 0 to Select 32bit transfers as default */ ++ pm_phy_sbus_write(0, 0xd202, 0x0002, 0x0003, 0); ++ ++ //[14] EFUN(wrc_micro_core_clk_en(0x1)); /* Enable clock to M0 core */ ++ /* [0xd200] Write to Clock control register 0 to enable micro core clock enable (m0) */ ++ pm_phy_sbus_write(0, 0xd200, 0x0001, 0x0001, 1); ++ ++ return 0; ++} ++ ++static int __xlmac_credit_reset(int port) ++{ ++ return 0; ++} ++ ++static void __xlmac_enable_set(int port, bool enable) ++{ ++ u64 ctrl, octrl; ++ int soft_reset; ++ ++ ctrl = xlmac_reg64_read(XLMAC_CTRL(port)); ++ octrl = ctrl; ++ /* Don't disable TX since it stops egress and hangs if CPU sends */ ++ ctrl |= (1 << XLMAC_CTRL__TX_EN); ++ ctrl &= ~(1 << XLMAC_CTRL__RX_EN); ++ if (enable) { ++ ctrl |= (1 << XLMAC_CTRL__RX_EN); ++ } ++ ++ if (ctrl == octrl) { ++ /* SDK-49952 fix soluition : ++ * >> to avoid the unexpected early return to prevent this problem. ++ * 1. Problem occurred for disabling process only. ++ * 2. To comply origianl designing senario, XLMAC_CTRLr.SOFT_RESETf is ++ * used to early check to see if this port is at disabled state ++ * already. ++ */ ++ soft_reset = ctrl & (1 << XLMAC_CTRL__SOFT_RESET); ++ if ((enable) || (!enable && soft_reset)){ ++ return; ++ } ++ } ++ ++ ctrl |= (1 << XLMAC_CTRL__SOFT_RESET); ++ if (enable) { ++ /* Reset EP credit before de-assert SOFT_RESET */ ++ __xlmac_credit_reset(port); ++ /* Deassert SOFT_RESET */ ++ ctrl &= ~(1 << XLMAC_CTRL__SOFT_RESET); ++ } ++ ++ xlmac_reg64_write(XLMAC_CTRL(port), ctrl); ++} ++ ++static int __xlmac_enable_get(int port) ++{ ++ u64 ctrl; ++ int tx_en, rx_en; ++ ++ ctrl = xlmac_reg64_read(XLMAC_CTRL(port)); ++ tx_en = ctrl & (1 << XLMAC_CTRL__TX_EN); ++ rx_en = ctrl & (1 << XLMAC_CTRL__RX_EN); ++ ++ return (tx_en && rx_en); ++} ++ ++static int __xlmac_speed_set(int port, int speed) ++{ ++ u64 speed_cfg, val64; ++ int enable; ++ ++ //pm_phy_sbus_write(port, 0xd080, 0x8008, 0x8008, 0); /* CKRST_CTRL_OSR_MODE_CONTROL */ ++ ++ if (speed == 1000) { ++ speed_cfg = SPEED_MODE_LINK_1G; ++ pm_phy_sbus_write(port, 0xc050, 0x0037, 0x01ff, 0); /* SC_X4_CONTROL_CONTROL */ ++ } else if (speed == 100) { ++ speed_cfg = SPEED_MODE_LINK_100M; ++ pm_phy_sbus_write(port, 0xc050, 0x0036, 0x01ff, 0); /* SC_X4_CONTROL_CONTROL */ ++ } else if (speed == 10) { ++ speed_cfg = SPEED_MODE_LINK_10M; ++ pm_phy_sbus_write(port, 0xc050, 0x0035, 0x01ff, 0); /* SC_X4_CONTROL_CONTROL */ ++ } else { ++ printk("%s: Invalid xlport speed(%d)!\n", __func__, speed); ++ return -1; ++ } ++ ++ pm_phy_sbus_write(port, 0xc050, 0x0000, 0x0001, 8); /* SC_X4_CONTROL_CONTROL */ ++ pm_phy_sbus_write(port, 0xc050, 0x0001, 0x0001, 8); /* SC_X4_CONTROL_CONTROL */ ++ ++ enable = __xlmac_enable_get(port); ++ /* disable before updating the speed */ ++ if (enable) { ++ __xlmac_enable_set(port, 0); ++ } ++ ++ /* Update the speed */ ++ val64 = xlmac_reg64_read(XLMAC_MODE(port)); ++ val64 &= ~(0x70); ++ val64 |= speed_cfg << XLMAC_MODE__SPEED_MODE_R; ++ xlmac_reg64_write(XLMAC_MODE(port), val64); ++ debug("%s XLMAC_MODE = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_MODE(port))); ++ ++ if (enable) { ++ __xlmac_enable_set(port, 1); ++ } ++ return 0; ++} ++ ++static int __xlmac_rx_max_size_set(int port, int value) ++{ ++ u64 val64; ++ u64 mask64; ++ ++ val64 = xlmac_reg64_read(XLMAC_RX_MAX_SIZE(port)); ++ mask64 = (1 << XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_WIDTH) - 1; ++ val64 &= ~(mask64 << XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_R); ++ val64 |= value << XLMAC_RX_MAX_SIZE__RX_MAX_SIZE_R; ++ xlmac_reg64_write(XLMAC_RX_MAX_SIZE(port), val64); ++ ++ return 0; ++} ++ ++static int __xlmac_tx_mac_addr_set(int port, u8 *mac) ++{ ++ u64 val64; ++ ++ /* set our local address */ ++ debug("GMAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ val64 = (u64)htonl(*(u32 *)&mac[2]); ++ val64 |= ((u64)htons(*(u32 *)mac) << 32); ++ xlmac_reg64_write(XLMAC_TX_MAC_SA(port), val64); ++ ++ debug("%s XLMAC_TX_MAC_SA = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_TX_MAC_SA(port))); ++ return 0; ++} ++ ++static int __xlmac_init(int port) ++{ ++ u64 val64; ++ ++ /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ ++ val64 = xlmac_reg64_read(XLMAC_CTRL(port)); ++ val64 &= ~(1 << XLMAC_CTRL__XGMII_IPG_CHECK_DISABLE); ++ val64 &= ~(1 << XLMAC_CTRL__RX_EN); ++ val64 &= ~(1 << XLMAC_CTRL__TX_EN); ++ xlmac_reg64_write(XLMAC_CTRL(port), val64); ++ ++ /* XLMAC_RX_CTRL */ ++ val64 = xlmac_reg64_read(XLMAC_RX_CTRL(port)); ++ val64 &= ~(1 << XLMAC_RX_CTRL__STRIP_CRC); ++ xlmac_reg64_write(XLMAC_RX_CTRL(port), val64); ++ ++ /* XLMAC_TX_CTRL */ ++ val64 = xlmac_reg64_read(XLMAC_TX_CTRL(port)); ++ val64 &= ~(0x3 << XLMAC_TX_CTRL__CRC_MODE_R); ++ val64 |= (CRC_MODE_REPLACE << XLMAC_TX_CTRL__CRC_MODE_R); ++ val64 |= (1 << XLMAC_TX_CTRL__PAD_EN); ++ xlmac_reg64_write(XLMAC_TX_CTRL(port), val64); ++ ++ /* PAUSE */ ++ val64 = xlmac_reg64_read(XLMAC_PAUSE_CTRL(port)); ++ val64 |= 1 << XLMAC_PAUSE_CTRL__RX_PAUSE_EN; ++ val64 |= 1 << XLMAC_PAUSE_CTRL__TX_PAUSE_EN; ++ xlmac_reg64_write(XLMAC_PAUSE_CTRL(port), val64); ++ ++ /* PFC */ ++ val64 = xlmac_reg64_read(XLMAC_PFC_CTRL(port)); ++ val64 |= ((u64)1 << XLMAC_PFC_CTRL__PFC_REFRESH_EN); ++ xlmac_reg64_write(XLMAC_PFC_CTRL(port), val64); ++ ++ /* Set jumbo max size (8000 byte payload) */ ++ __xlmac_rx_max_size_set(port, JUMBO_MAXSZ); ++ ++ /* XLMAC_RX_LSS_CTRL */ ++ val64 = xlmac_reg64_read(XLMAC_RX_LSS_CTRL(port)); ++ val64 |= 1 << XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_LINK_INTERRUPT; ++ val64 |= 1 << XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_REMOTE_FAULT; ++ val64 |= 1 << XLMAC_RX_LSS_CTRL__DROP_TX_DATA_ON_LOCAL_FAULT; ++ xlmac_reg64_write(XLMAC_RX_LSS_CTRL(port), val64); ++ ++ /* Disable loopback and bring XLMAC out of reset */ ++ val64 = xlmac_reg64_read(XLMAC_CTRL(port)); ++ val64 &= ~(1 << XLMAC_CTRL__SOFT_RESET);; ++ val64 &= ~(1 << XLMAC_CTRL__LOCAL_LPBK); ++ val64 |= 1 << XLMAC_CTRL__RX_EN; ++ val64 |= 1 << XLMAC_CTRL__TX_EN; ++ xlmac_reg64_write(XLMAC_CTRL(port), val64); ++ ++ return 0; ++} ++ ++static int __tsc_reset(int in_reset) ++{ ++ u32 val; ++ ++ val = xlport_reg32_read(XLPORT_XGXS0_CTRL_REG); ++ if (in_reset) { ++ //val &= ~(7 << XLPORT_XGXS0_CTRL_REG__RefSel); ++ val |= (1 << XLPORT_XGXS0_CTRL_REG__IDDQ); ++ //val &= ~(1 << XLPORT_XGXS0_CTRL_REG__Refin_EN); ++ val |= 1 << XLPORT_XGXS0_CTRL_REG__PWRDWN; ++ val &= ~(1 << XLPORT_XGXS0_CTRL_REG__RSTB_HW); ++ } else { ++ //val |= (5 << XLPORT_XGXS0_CTRL_REG__RefSel); ++ val &= ~(1 << XLPORT_XGXS0_CTRL_REG__IDDQ); ++ //val |= (1 << XLPORT_XGXS0_CTRL_REG__Refin_EN); ++ val &= ~(1 << XLPORT_XGXS0_CTRL_REG__PWRDWN); ++ //val &= ~(0 << XLPORT_XGXS0_CTRL_REG__RSTB_HW); ++ val |= (1 << XLPORT_XGXS0_CTRL_REG__RSTB_HW); ++ } ++ xlport_reg32_write(XLPORT_XGXS0_CTRL_REG, val); ++ ++ ++/* if (!in_reset) ++ { ++ msleep(1); ++ val |= (1 << XLPORT_XGXS0_CTRL_REG__RSTB_HW); ++ xlport_reg32_write(XLPORT_XGXS0_CTRL_REG, val); ++ } */ ++ msleep(1); ++ return 0; ++} ++ ++static void pm4x10_tsc_config(int port) ++{ ++#ifdef CONFIG_IPROC_EMULATION ++ printf("skip %s... in emulation\n", __func__); ++#else ++ u32 val; ++ int i; ++ ++ /* Global PMD reset controls */ ++ pm_phy_sbus_write(port, 0x9010, 0x0000, 0xffff, 0); ++ udelay(10); ++ pm_phy_sbus_write(port, 0x9010, 0x0003, 0xffff, 0); ++ udelay(10); ++ ++ /* PMD lane reset controls */ ++ for (i=0; i<4; ++i) ++ { ++ pm_phy_sbus_write(i, 0xc010, 0x0000, 0xc003, 0); ++ udelay(10); ++ pm_phy_sbus_write(i, 0xc010, 0xc003, 0xc003, 0); ++ } ++ /* set refclk_sel = 156.25 MHz */ ++ pm_phy_sbus_write(port, 0x9000, 0x0003, 0x0007, 13); ++ /* set heartbeat_count_1us = 0x271 */ ++ pm_phy_sbus_write(port, 0xd0f4, 0x0271, 0x03ff, 0); ++#endif ++ return 0; ++} ++ ++/***************************************************************************** ++*****************************************************************************/ ++static void pm4x10_xlport_mac_enable(int port) ++{ ++ __xlmac_enable_set(port, 1); ++} ++ ++static void pm4x10_xlport_mac_disable(int port) ++{ ++ __xlmac_enable_set(port, 0); ++} ++ ++//static int pm4x10_xlport_speed_set(int port, int speed) ++int pm4x10_xlport_speed_set(int port, int speed) ++{ ++ return __xlmac_speed_set(port, speed); ++} ++ ++//static int pm4x10_xlport_mac_addr_set(int port, u8 *mac) ++int pm4x10_xlport_mac_addr_set(int port, u8 *mac) ++{ ++ return __xlmac_tx_mac_addr_set(port, mac); ++} ++ ++static int pm4x10_xlport_max_packet_size_set(int port, int value) ++{ ++ return __xlmac_rx_max_size_set(port, value); ++} ++ ++//static int pm4x10_xlport_loopback_set(int port, int lb_type, int lb_en) ++int pm4x10_xlport_loopback_set(int port, int lb_type, int lb_en) ++{ ++ u64 val64; ++ u32 val32; ++//printk(" (%s) enter.....port = %d, lb_type = %d, lb_en = %d\n", __func__, port, lb_type, lb_en); ++ ++ switch(lb_type) { ++ case pmLoopbackMac: ++ val64 = xlmac_reg64_read(XLMAC_CTRL(port)); ++ val64 &= ~(1 << XLMAC_CTRL__LOCAL_LPBK); ++ if (lb_en) { ++ printk("(%s) MAC port = %d, lb_en = %d\n", __func__, port, lb_en); ++ val64 |= (1 << XLMAC_CTRL__LOCAL_LPBK); ++ } ++ xlmac_reg64_write(XLMAC_CTRL(port), val64); ++ break; ++ ++ case pmLoopbackPhy: ++ if (lb_en) { ++ printk("(%s) PHY port = %d, lb_en = %d\n", __func__, port, lb_en); ++ pm_phy_sbus_write(port*2, 0x9009, (1 << port*2), 0x000f, 4); /* MAIN0_LOOPBACK_CONTROL */ ++ pm_phy_sbus_write(port*2, 0xc014, 0x0043, 0x0043, 0); /* PMD_X4_OVERRIDE */ ++ pm_phy_sbus_write(port*2, 0xc010, 0x0001, 0x0001, 8); /* PMD_X4_CONTROL */ ++ } else { ++ pm_phy_sbus_write(port*2, 0x9009, 0x0000, 0x000f, 4); /* MAIN0_LOOPBACK_CONTROL */ ++ pm_phy_sbus_write(port*2, 0xc014, 0x0000, 0x0043, 0); /* PMD_X4_OVERRIDE */ ++ pm_phy_sbus_write(port*2, 0xc010, 0x0000, 0x0001, 8); /* PMD_X4_CONTROL */ ++ } ++ break; ++ ++ default: ++ break; ++ } ++ return 0; ++} ++ ++//static int pm4x10_xlport_stats_get(int port, struct iproc_pm_stats *stats) ++int pm4x10_xlport_stats_get(int port, struct iproc_pm_stats *stats) ++{ ++ stats->rx_frames = xlmac_reg64_read(XLMIB_GRxPkt(port)); ++ stats->rx_frame_good = xlmac_reg64_read(XLMIB_GRxPOK(port)); ++ stats->rx_bytes = xlmac_reg64_read(XLMIB_GRxByt(port)); ++ stats->rx_frame_64 = xlmac_reg64_read(XLMIB_GRx64(port)); ++ stats->rx_frame_127 = xlmac_reg64_read(XLMIB_GRx127(port)); ++ stats->rx_frame_255 = xlmac_reg64_read(XLMIB_GRx255(port)); ++ stats->rx_frame_511 = xlmac_reg64_read(XLMIB_GRx511(port)); ++ stats->rx_frame_1023 = xlmac_reg64_read(XLMIB_GRx1023(port)); ++ stats->rx_frame_1518 = xlmac_reg64_read(XLMIB_GRx1518(port)); ++ stats->rx_frame_1522 = xlmac_reg64_read(XLMIB_GRx1522(port)); ++ stats->rx_frame_jumbo = xlmac_reg64_read(XLMIB_GRx2047(port)) + ++ xlmac_reg64_read(XLMIB_GRx4095(port)) + ++ xlmac_reg64_read(XLMIB_GRx9216(port)) + ++ xlmac_reg64_read(XLMIB_GRx16383(port)); ++ stats->rx_frame_unicast = xlmac_reg64_read(XLMIB_GRxUCA(port)); ++ stats->rx_frame_multicast = xlmac_reg64_read(XLMIB_GRxMCA(port)); ++ stats->rx_frame_broadcast = xlmac_reg64_read(XLMIB_GRxBCA(port)); ++ stats->rx_frame_control = xlmac_reg64_read(XLMIB_GRxCF(port)); ++ stats->rx_frame_pause = xlmac_reg64_read(XLMIB_GRxPF(port)); ++ stats->rx_frame_jabber = xlmac_reg64_read(XLMIB_GRxJBR(port)); ++ stats->rx_frame_fragment = xlmac_reg64_read(XLMIB_GRxFRG(port)); ++ stats->rx_frame_vlan = xlmac_reg64_read(XLMIB_GRxVLN(port)); ++ stats->rx_frame_dvlan = xlmac_reg64_read(XLMIB_GRxDVLN(port)); ++ stats->rx_frame_fcs_error = xlmac_reg64_read(XLMIB_GRxFCS(port)); ++ stats->rx_frame_unsupport = xlmac_reg64_read(XLMIB_GRxUO(port)); ++ stats->rx_frame_wrong_sa = xlmac_reg64_read(XLMIB_GRxWSA(port)); ++ stats->rx_frame_align_err = xlmac_reg64_read(XLMIB_GRxALN(port)); ++ stats->rx_frame_length_err = xlmac_reg64_read(XLMIB_GRxFLR(port)); ++ stats->rx_frame_oversize = xlmac_reg64_read(XLMIB_GRxOVR(port)); ++ stats->rx_frame_mtu_err = xlmac_reg64_read(XLMIB_GRxMTUE(port)); ++ stats->rx_frame_truncated_err = xlmac_reg64_read(XLMIB_GRxTRFU(port)); ++ stats->rx_frame_undersize = xlmac_reg64_read(XLMIB_GRxUND(port)); ++ stats->tx_frames = xlmac_reg64_read(XLMIB_GTxPkt(port)); ++ stats->tx_frame_good = xlmac_reg64_read(XLMIB_GTxPOK(port)); ++ stats->tx_bytes = xlmac_reg64_read(XLMIB_GTxBYT(port)); ++ stats->tx_frame_64 = xlmac_reg64_read(XLMIB_GTx64(port)); ++ stats->tx_frame_127 = xlmac_reg64_read(XLMIB_GTx127(port)); ++ stats->tx_frame_255 = xlmac_reg64_read(XLMIB_GTx255(port)); ++ stats->tx_frame_511 = xlmac_reg64_read(XLMIB_GTx511(port)); ++ stats->tx_frame_1023 = xlmac_reg64_read(XLMIB_GTx1023(port)); ++ stats->tx_frame_1518 = xlmac_reg64_read(XLMIB_GTx1518(port)); ++ stats->tx_frame_1522 = xlmac_reg64_read(XLMIB_GTx1522(port)); ++ stats->tx_frame_jumbo = xlmac_reg64_read(XLMIB_GTx2047(port)) + ++ xlmac_reg64_read(XLMIB_GTx4095(port)) + ++ xlmac_reg64_read(XLMIB_GTx9216(port)) + ++ xlmac_reg64_read(XLMIB_GTx16383(port)); ++ stats->tx_frame_unicast = xlmac_reg64_read(XLMIB_GTxUCA(port)); ++ stats->tx_frame_multicast = xlmac_reg64_read(XLMIB_GTxMCA(port)); ++ stats->tx_frame_broadcast = xlmac_reg64_read(XLMIB_GTxBCA(port)); ++ stats->tx_frame_control = xlmac_reg64_read(XLMIB_GTxCF(port)); ++ stats->tx_frame_pause = xlmac_reg64_read(XLMIB_GTxPF(port)); ++ stats->tx_frame_jabber = xlmac_reg64_read(XLMIB_GTxJBR(port)); ++ stats->tx_frame_fragment = xlmac_reg64_read(XLMIB_GTxFRG(port)); ++ stats->tx_frame_vlan = xlmac_reg64_read(XLMIB_GTxVLN(port)); ++ stats->tx_frame_dvlan = xlmac_reg64_read(XLMIB_GTxDVLN(port)); ++ stats->tx_frame_fcs_error = xlmac_reg64_read(XLMIB_GTxFCS(port)); ++ stats->tx_frame_oversize = xlmac_reg64_read(XLMIB_GTxOVR(port)); ++ stats->tx_frame_error = xlmac_reg64_read(XLMIB_GTxErr(port)); ++ stats->tx_frame_fifo_underrun = xlmac_reg64_read(XLMIB_GTxUFL(port)); ++ stats->tx_frame_collision = xlmac_reg64_read(XLMIB_GTxNCL(port)); ++ ++ return 0; ++} ++ ++//static int pm4x10_xlport_mib_reset(int port) ++int pm4x10_xlport_mib_reset(int port) ++{ ++ u32 val; ++ ++ /* MIB reset */ ++ val = xlport_reg32_read(XLPORT_MIB_RESET); ++ val |= (1 << port) << XLPORT_MIB_RESET__CLR_CNT_R; ++ xlport_reg32_write(XLPORT_MIB_RESET, val); ++ ++ val &= ~((1 << port) << XLPORT_MIB_RESET__CLR_CNT_R); ++ xlport_reg32_write(XLPORT_MIB_RESET, val); ++ ++ return 0; ++} ++ ++//static int pm4x10_pm_xlport_port_config(int port, int enable) ++int pm4x10_pm_xlport_port_config(int port, int enable) ++{ ++ u32 val; ++ ++ if (enable) { ++ /* Soft reset */ ++ val = xlport_reg32_read(XLPORT_SOFT_RESET); ++ XLPORT_PORT_FIELD_SET(XLPORT_SOFT_RESET, port, val); ++ xlport_reg32_write(XLPORT_SOFT_RESET, val); ++ ++ XLPORT_PORT_FIELD_CLEAR(XLPORT_SOFT_RESET, port, val); ++ xlport_reg32_write(XLPORT_SOFT_RESET, val); ++ ++ /* Port enable */ ++ val = xlport_reg32_read(XLPORT_ENABLE_REG); ++ XLPORT_PORT_FIELD_SET(XLPORT_ENABLE_REG, port, val); ++ xlport_reg32_write(XLPORT_ENABLE_REG, val); ++ ++ /* Init MAC */ ++ __xlmac_init(port); ++ ++#if 0 //FIXME ++ /* LSS */ ++ val = xlport_reg32_read(XLPORT_FAULT_LINK_STATUS(port)); ++ val |= 1 << XLPORT_FAULT_LINK_STATUS__REMOTE_FAULT; ++ val |= 1 << XLPORT_FAULT_LINK_STATUS__LOCAL_FAULT; ++ xlport_reg32_write(XLPORT_FAULT_LINK_STATUS(port), val); ++#endif /* 0 */ ++ ++ /* MIB reset */ ++ val = xlport_reg32_read(XLPORT_MIB_RESET); ++ val |= (1 << port) << XLPORT_MIB_RESET__CLR_CNT_R; ++ xlport_reg32_write(XLPORT_MIB_RESET, val); ++ ++ val &= ~((1 << port) << XLPORT_MIB_RESET__CLR_CNT_R); ++ xlport_reg32_write(XLPORT_MIB_RESET, val); ++ } else { ++ /* Port disable */ ++ val = xlport_reg32_read(XLPORT_ENABLE_REG); ++ XLPORT_PORT_FIELD_CLEAR(XLPORT_ENABLE_REG, port, val); ++ xlport_reg32_write(XLPORT_ENABLE_REG, val); ++ ++ /* Soft reset */ ++ val = xlport_reg32_read(XLPORT_SOFT_RESET); ++ XLPORT_PORT_FIELD_CLEAR(XLPORT_SOFT_RESET, port, val); ++ xlport_reg32_write(XLPORT_SOFT_RESET, val); ++ } ++ ++ return 0; ++} ++ ++static int pm4x10_pm_disable(void) ++{ ++ u32 val; ++ ++ /* Put MAC in reset */ ++ val = xlport_reg32_read(XLPORT_MAC_CONTROL); ++ val |= 1 << XLPORT_MAC_CONTROL__XMAC0_RESET; ++ xlport_reg32_write(XLPORT_MAC_CONTROL, val); ++ ++ /* Put Serdes in reset*/ ++ __tsc_reset(1); ++ ++ return 0; ++} ++ ++static int pm4x10_pm_enable(void) ++{ ++ u32 val; ++ u32 mask; ++ ++ /* Power Save */ ++ val = xlport_reg32_read(XLPORT_POWER_SAVE); ++ val &= ~(1 << XLPORT_POWER_SAVE__XPORT_CORE0); ++ xlport_reg32_write(XLPORT_POWER_SAVE, val); ++ ++ /* Port configuration */ ++ val = xlport_reg32_read(XLPORT_MODE_REG); ++ mask = (1 << XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_WIDTH) - 1; ++ val &= ~(mask << XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_R); ++ val |= (XPORT0_CORE_PORT_MODE_QUAD << XLPORT_MODE_REG__XPORT0_CORE_PORT_MODE_R); ++ mask = (1 << XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_WIDTH) - 1; ++ val &= ~(mask << XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_R); ++ val |= (XPORT0_CORE_PORT_MODE_QUAD << XLPORT_MODE_REG__XPORT0_PHY_PORT_MODE_R); ++ xlport_reg32_write(XLPORT_MODE_REG, val); ++ ++ /* Get Serdes OOR */ ++ __tsc_reset(1); ++ __tsc_reset(0); ++ ++ /* Bring MAC OOR */ ++ val = xlport_reg32_read(XLPORT_MAC_CONTROL); ++ val &= ~(1 << XLPORT_MAC_CONTROL__XMAC0_RESET); ++ xlport_reg32_write(XLPORT_MAC_CONTROL, val); ++ ++ return 0; ++} ++ ++int pm4x10_pm_init(struct iproc_pm_ops *pm_ops, u8 land_idx) ++{ ++#if 0 ++ pm_ops = kmalloc(sizeof(struct iproc_pm_ops), GFP_KERNEL); ++ if (!pm_ops) { ++ return -ENOMEM; ++ } ++ pm_ops->port_enable= pm4x10_pm_xlport_port_config; ++ pm_ops->port_speed = pm4x10_xlport_speed_set; ++ pm_ops->port_loopback = pm4x10_xlport_loopback_set; ++ pm_ops->port_mac_addr = pm4x10_xlport_mac_addr_set; ++ pm_ops->port_stats = pm4x10_xlport_stats_get; ++ pm_ops->port_stats_clear = pm4x10_xlport_mib_reset; ++#endif ++ ++#if 0 ++ if (!pm4x10_enabled) /* check initialize for first time */ ++#else ++ if (pm4x10_enabled == 0x100) /* don't do it now */ ++#endif ++ { ++ /* configure TSC registers before download ucode */ ++ pm4x10_tsc_config(land_idx); ++ ++ /* ucode download */ ++ pm_ucode_download(merlin16_ucode, merlin16_ucode_len); ++ ++ /* Configure TSC/merlin16 registers */ ++ pm_phy_configure(land_idx); ++ ++ /* Enable PM4x10 */ ++ pm4x10_pm_enable(); ++ pm4x10_enabled++; ++ } ++ ++ return 0; ++} ++ ++int pm4x10_pm_deinit(struct iproc_pm_ops *pm_ops) ++{ ++#if 0 ++ kfree(pm_ops); ++ pm_ops = NULL; ++#endif ++ pm4x10_enabled--; ++ if (!pm4x10_enabled) { ++ pm4x10_pm_disable(); ++ } ++ ++ return 0; ++} ++ ++#if 0 ++static void pm4x10_xlport_config(int port) ++{ ++ u32 val; ++ u64 val64; ++ ++ /* xlport_mac_config */ ++ val = xlport_reg32_read(XLPORT_ENABLE_REG); ++ val |= ((1 << XLPORT_ENABLE_REG__PORT0) | (1 << XLPORT_ENABLE_REG__PORT2)); ++ xlport_reg32_write(XLPORT_ENABLE_REG, val); ++ debug("%s XLPORT_ENABLE_REG = 0x%x\n", __func__, xlport_reg32_read(XLPORT_ENABLE_REG)); ++ ++ val = xlport_reg32_read(XLPORT_MAC_CONTROL); ++ val &= ~(1 << XLPORT_MAC_CONTROL__XMAC0_RESET); ++ xlport_reg32_write(XLPORT_MAC_CONTROL, val); ++ ++ /* xlport_intr_enable ? */ ++ ++ /* Resetting MIB counter */ ++ xlport_reg32_write(XLPORT_MIB_RESET, 0xf); ++ /* FIXME : delay? */ ++ /* udelay(10); */ ++ xlport_reg32_write(XLPORT_MIB_RESET, 0x0); ++ ++ /* Ethernet mode, 1G */ ++ val64 = xlmac_reg64_read(XLMAC_MODE(port)); ++ val64 &= ~(0x70); ++ val64 |= SPEED_MODE_LINK_1G << XLMAC_MODE__SPEED_MODE_R; ++ xlmac_reg64_write(XLMAC_MODE(port), val64); ++ debug("%s XLMAC_MODE = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_MODE(port))); ++ ++ val64 = xlmac_reg64_read(XLMAC_RX_CTRL(port)); ++ val64 &= ~(1 << XLMAC_RX_CTRL__STRIP_CRC); ++ xlmac_reg64_write(XLMAC_RX_CTRL(port), val64); ++ debug("%s XLMAC_RX_CTRL = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_RX_CTRL(port))); ++ ++ val64 = xlmac_reg64_read(XLMAC_TX_CTRL(port)); ++ val64 &= ~(0x3 << XLMAC_TX_CTRL__CRC_MODE_R); ++ val64 |= (CRC_MODE_REPLACE << XLMAC_TX_CTRL__CRC_MODE_R); ++ val64 |= (1 << XLMAC_TX_CTRL__PAD_EN); ++ xlmac_reg64_write(XLMAC_TX_CTRL(port), val64); ++ debug("%s XLMAC_TX_CTRL = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_TX_CTRL(port))); ++ ++#if 0 ++ val64 = xlmac_reg64_read(XLMAC_CTRL(port)); ++ val64 &= ~(1 << XLMAC_CTRL__SOFT_RESET); ++ val64 |= ((1 << XLMAC_CTRL__RX_EN) | (1 << XLMAC_CTRL__TX_EN)); ++ xlmac_reg64_write(XLMAC_CTRL(port), val64); ++ debug("%s XLMAC_CTRL = 0x%llx\n", __func__, xlmac_reg64_read(XLMAC_CTRL(port))); ++#endif ++} ++#endif /* 0 */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +--- a/drivers/net/phy/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/phy/Kconfig 2018-05-10 11:31:32.077402284 +0800 +@@ -198,6 +198,14 @@ config LED_TRIGGER_PHY + Mbps or Gbps + + ++config MDIO_XGS_IPROC ++ tristate "Broadcom XGS iProc MDIO bus controller" ++ depends on ARCH_XGS_IPROC || COMPILE_TEST ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This module provides a driver for the MDIO busses found in the ++ Broadcom XGS iProc SoC's. ++ + comment "MII PHY device drivers" + + config SFP +@@ -262,6 +270,12 @@ config BROADCOM_PHY + Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, + BCM5481, BCM54810 and BCM5482 PHYs. + ++config XGS_IPROC_SERDES ++ tristate "Broadcom XGS iProc SERDES" ++ depends on MDIO_XGS_IPROC ++ ---help--- ++ Supports HX4/KT2/GH2 SERDES. ++ + config CICADA_PHY + tristate "Cicada PHYs" + ---help--- +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +--- a/drivers/net/phy/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/phy/Makefile 2018-05-10 11:31:32.081402288 +0800 +@@ -38,6 +38,7 @@ obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon + obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o + obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o + obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o ++obj-$(CONFIG_MDIO_XGS_IPROC) += mdio-xgs-iproc-cmicx.o mdio-xgs-iproc-cmicd.o mdio-xgs-iproc-cc.o + + obj-$(CONFIG_SFP) += sfp.o + sfp-obj-$(CONFIG_SFP) += sfp-bus.o +@@ -52,6 +53,7 @@ obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o + obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o + obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o + obj-$(CONFIG_BROADCOM_PHY) += broadcom.o ++obj-$(CONFIG_XGS_IPROC_SERDES) += xgs-iproc-serdes.o + obj-$(CONFIG_CICADA_PHY) += cicada.o + obj-$(CONFIG_CORTINA_PHY) += cortina.o + obj-$(CONFIG_DAVICOM_PHY) += davicom.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/mdio-xgs-iproc-cc.c b/drivers/net/phy/mdio-xgs-iproc-cc.c +--- a/drivers/net/phy/mdio-xgs-iproc-cc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/mdio-xgs-iproc-cc.c 2018-05-10 11:31:32.085402292 +0800 +@@ -0,0 +1,492 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++#include ++#include ++#include "mdio-xgs-iproc.h" ++ ++#define MGMT_CTL_REG 0x000 ++#define MGMT_CTL__BYP_SHIFT 10 ++#define MGMT_CTL__BYP_WIDTH 1 ++#define MGMT_CTL__BYP_MASK ((1 << MGMT_CTL__BYP_WIDTH) - 1) ++#define MGMT_CTL__EXT_SHIFT 9 ++#define MGMT_CTL__EXT_WIDTH 1 ++#define MGMT_CTL__EXT_MASK ((1 << MGMT_CTL__EXT_WIDTH) - 1) ++#define MGMT_CTL__BSY_SHIFT 8 ++#define MGMT_CTL__BSY_WIDTH 1 ++#define MGMT_CTL__BSY_MASK ((1 << MGMT_CTL__BSY_WIDTH) - 1) ++#define MGMT_CTL__PRE_SHIFT 7 ++#define MGMT_CTL__PRE_WIDTH 1 ++#define MGMT_CTL__PRE_MASK ((1 << MGMT_CTL__BSY_WIDTH) - 1) ++#define MGMT_CTL__MDCDIV_SHIFT 0 ++#define MGMT_CTL__MDCDIV_WIDTH 7 ++#define MGMT_CTL__MDCDIV_MASK ((1 << MGMT_CTL__MDCDIV_WIDTH) - 1) ++ ++#define MGMT_CMD_DATA_REG 0x004 ++#define MGMT_CMD_DATA__SB_SHIFT 30 ++#define MGMT_CMD_DATA__SB_WIDTH 2 ++#define MGMT_CMD_DATA__SB_MASK ((1 << MGMT_CMD_DATA__SB_WIDTH) - 1) ++#define MGMT_CMD_DATA__OP_SHIFT 28 ++#define MGMT_CMD_DATA__OP_WIDTH 2 ++#define MGMT_CMD_DATA__OP_MASK ((1 << MGMT_CMD_DATA__OP_WIDTH) - 1) ++#define MGMT_CMD_DATA__PA_SHIFT 23 ++#define MGMT_CMD_DATA__PA_WIDTH 5 ++#define MGMT_CMD_DATA__PA_MASK ((1 << MGMT_CMD_DATA__PA_WIDTH) - 1) ++#define MGMT_CMD_DATA__RA_SHIFT 18 ++#define MGMT_CMD_DATA__RA_WIDTH 5 ++#define MGMT_CMD_DATA__RA_MASK ((1 << MGMT_CMD_DATA__RA_WIDTH) - 1) ++#define MGMT_CMD_DATA__TA_SHIFT 16 ++#define MGMT_CMD_DATA__TA_WIDTH 2 ++#define MGMT_CMD_DATA__TA_MASK ((1 << MGMT_CMD_DATA__TA_WIDTH) - 1) ++#define MGMT_CMD_DATA__DATA_SHIFT 0 ++#define MGMT_CMD_DATA__DATA_WIDTH 16 ++#define MGMT_CMD_DATA__DATA_MASK ((1 << MGMT_CMD_DATA__DATA_WIDTH) - 1) ++ ++#define MII_OP_HALT_USEC 10 ++ ++struct cc_mii_cmd { ++ int bus_id; ++ int ext_sel; ++ int phy_id; ++ int regnum; ++ u16 op_mode; ++ u16 val; ++}; ++ ++static struct iproc_mdio_ctrl *cc_mdio_ctrl = NULL; ++ ++/* ++ * For HX4/KT2, the mdio bus is shared with iProc mdio and CMICd mdio ++ * controllers. By default the mdio bus is released to CMICd for SDK to run. ++ * Set kernel argument mdio_bus_release to 0 if ethtool test is required. ++ */ ++static bool mdio_bus_release = true; ++static int __init set_mdio_bus_release(char *str) ++{ ++ return strtobool(str, &mdio_bus_release); ++} ++__setup("mdio_bus_release=", set_mdio_bus_release); ++ ++ ++/* HX4/KT2 need to release mdio bus from iProc to cmicd */ ++bool xgs_mdio_bus_release(void) ++{ ++ if (of_machine_is_compatible("brcm,helix4") || ++ of_machine_is_compatible("brcm,katana2")) ++ return mdio_bus_release; ++ else ++ return 0; ++} ++ ++/* HX4/KT2/SB2 needs to enable iProc mdio bus access, default is cimcd access */ ++static void xgs_iproc_mdio_enable(struct iproc_mdio_ctrl *ctrl, int enable) ++{ ++ void __iomem *iproc_mdio_enable_reg = NULL; ++ u32 iproc_mdio_sel; ++ u32 tmp; ++ ++ if (!ctrl->iproc_mdio_enable_reg) ++ return; ++ ++ iproc_mdio_enable_reg = ctrl->iproc_mdio_enable_reg; ++ iproc_mdio_sel = ctrl->iproc_mdio_sel_bit; ++ ++ tmp = readl(iproc_mdio_enable_reg); ++ ++ if (enable) ++ tmp |= (1 << iproc_mdio_sel); ++ else ++ tmp &= ~(1 << iproc_mdio_sel); ++ ++ writel(tmp, iproc_mdio_enable_reg); ++} ++ ++static inline u32 cc_mii_reg_read(struct iproc_mdio_ctrl *cc_mii, u32 reg) ++{ ++ return readl(cc_mii->base + reg); ++} ++ ++static inline void cc_mii_reg_write(struct iproc_mdio_ctrl *cc_mii, ++ u32 reg, u32 data) ++{ ++ writel(data, cc_mii->base + reg); ++} ++ ++static int cc_mii_busy(struct iproc_mdio_ctrl *cc_mii, int to_usec) ++{ ++ do { ++ if(!GET_REG_FIELD(cc_mii_reg_read(cc_mii, MGMT_CTL_REG), ++ MGMT_CTL__BSY_SHIFT, MGMT_CTL__BSY_MASK)) ++ return 0; ++ ++ udelay(MII_OP_HALT_USEC); ++ to_usec -= MII_OP_HALT_USEC; ++ } while (to_usec > 0); ++ ++ return 1; ++} ++ ++static int do_cc_mii_op(struct iproc_mdio_ctrl *cc_mii, struct cc_mii_cmd *cmd) ++{ ++ u32 cmd_data = 0; ++ u32 mgt_ctrl; ++ u32 op_mode = cmd->op_mode; ++ unsigned long flags; ++ int ret = 0; ++ ++ if (MII_OP_MODE_WRITE == op_mode) { ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__OP_SHIFT, ++ MGMT_CMD_DATA__OP_MASK, 1); ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__DATA_SHIFT, ++ MGMT_CMD_DATA__DATA_MASK, cmd->val); ++ } ++ else if (MII_OP_MODE_READ == op_mode) { ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__OP_SHIFT, ++ MGMT_CMD_DATA__OP_MASK, 2); ++ } ++ else { ++ pr_err("%s : invalid op code %d\n", __func__, op_mode); ++ return -EINVAL; ++ } ++ ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__PA_SHIFT, ++ MGMT_CMD_DATA__PA_MASK, cmd->phy_id); ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__RA_SHIFT, ++ MGMT_CMD_DATA__RA_MASK, cmd->regnum); ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__TA_SHIFT, ++ MGMT_CMD_DATA__TA_MASK, 2); ++ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__SB_SHIFT, ++ MGMT_CMD_DATA__SB_MASK, 1); ++ ++ spin_lock_irqsave(&cc_mii->lock, flags); ++ ++ if (cc_mii_busy(cc_mii, MII_OP_MAX_HALT_USEC)) { ++ ret = -EBUSY; ++ pr_err("%s : bus busy (1)\n", __func__); ++ goto err_exit_unlock; ++ } ++ ++ mgt_ctrl = cc_mii_reg_read(cc_mii, MGMT_CTL_REG); ++ if (cmd->ext_sel != GET_REG_FIELD(mgt_ctrl, MGMT_CTL__EXT_SHIFT, ++ MGMT_CTL__EXT_MASK)) { ++ SET_REG_FIELD(mgt_ctrl, MGMT_CTL__EXT_SHIFT, ++ MGMT_CTL__EXT_MASK, cmd->ext_sel); ++ cc_mii_reg_write(cc_mii, MGMT_CTL_REG, mgt_ctrl); ++ } ++ ++ cc_mii_reg_write(cc_mii, MGMT_CMD_DATA_REG, cmd_data); ++ ++ if (cc_mii_busy(cc_mii, MII_OP_MAX_HALT_USEC)) { ++ ret = -EBUSY; ++ pr_err("%s : bus busy (2)\n", __func__); ++ goto err_exit_unlock; ++ } ++ ++ if (MII_OP_MODE_READ == cmd->op_mode) { ++ ret = GET_REG_FIELD(cc_mii_reg_read(cc_mii, MGMT_CMD_DATA_REG), ++ MGMT_CMD_DATA__DATA_SHIFT, MGMT_CMD_DATA__DATA_MASK); ++ } ++ ++ spin_unlock_irqrestore(&cc_mii->lock, flags); ++ ++ return ret; ++ ++err_exit_unlock: ++ spin_unlock_irqrestore(&cc_mii->lock, flags); ++ return ret; ++} ++ ++static int cc_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) ++{ ++ struct iproc_mdiobus_private *bus_priv = bus->priv; ++ struct iproc_mdiobus_data *bus_data = bus_priv->bus_data; ++ struct cc_mii_cmd cmd = {0}; ++ int ret; ++ ++ xgs_iproc_mdio_enable(bus_priv->hw_ctrl, 1); ++ ++ cmd.bus_id = bus_data->phybus_num; ++ if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) ++ cmd.ext_sel = 1; ++ cmd.phy_id = phy_id; ++ cmd.regnum = regnum; ++ cmd.op_mode = MII_OP_MODE_READ; ++ ++ ret = do_cc_mii_op(bus_priv->hw_ctrl, &cmd); ++ ++ xgs_iproc_mdio_enable(bus_priv->hw_ctrl, 0); ++ ++ return ret; ++} ++ ++static int cc_mdiobus_write(struct mii_bus *bus, int phy_id, ++ int regnum, u16 val) ++{ ++ struct iproc_mdiobus_private *bus_priv = bus->priv; ++ struct iproc_mdiobus_data *bus_data = bus_priv->bus_data; ++ struct cc_mii_cmd cmd = {0}; ++ int ret; ++ ++ xgs_iproc_mdio_enable(bus_priv->hw_ctrl, 1); ++ ++ cmd.bus_id = bus_data->phybus_num; ++ ++ if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) ++ cmd.ext_sel = 1; ++ ++ cmd.phy_id = phy_id; ++ cmd.regnum = regnum; ++ cmd.op_mode = MII_OP_MODE_WRITE; ++ cmd.val = val; ++ ++ ret = do_cc_mii_op(bus_priv->hw_ctrl, &cmd); ++ ++ xgs_iproc_mdio_enable(bus_priv->hw_ctrl, 0); ++ ++ return ret; ++} ++ ++static struct iproc_mdio_ctrl * cc_mdio_res_alloc(void) ++{ ++ if (!cc_mdio_ctrl) { ++ cc_mdio_ctrl = kzalloc(sizeof(*cc_mdio_ctrl), GFP_KERNEL); ++ if (!cc_mdio_ctrl) ++ return NULL; ++ ++ spin_lock_init(&cc_mdio_ctrl->lock); ++ cc_mdio_ctrl->ref_cnt = 1; ++ } ++ else ++ cc_mdio_ctrl->ref_cnt++; ++ ++ return cc_mdio_ctrl; ++} ++ ++static void cc_mdio_res_free(struct iproc_mdio_ctrl *ctrl) ++{ ++ if (ctrl) { ++ ctrl->ref_cnt--; ++ if (ctrl->ref_cnt == 0) { ++ iounmap(ctrl->base); ++ kfree(ctrl); ++ cc_mdio_ctrl = NULL; ++ } ++ } ++} ++ ++static void cc_mii_init(struct iproc_mdio_ctrl *cc_mii, u32 mdio_clk_rate) ++{ ++ u32 val = 0; ++ ++ if(cc_mii->ref_cnt == 1) { ++ /* Set preamble enabled */ ++ ISET_REG_FIELD(val, MGMT_CTL__PRE_SHIFT, MGMT_CTL__PRE_MASK, 1); ++ /* Set the MII clock to 1 MHz */ ++ ISET_REG_FIELD(val, MGMT_CTL__MDCDIV_SHIFT, MGMT_CTL__MDCDIV_MASK, ++ mdio_clk_rate/(1000000)); ++ cc_mii_reg_write(cc_mii, MGMT_CTL_REG, val); ++ } ++} ++ ++static int cc_mdiobus_probe(struct platform_device *pdev) ++{ ++ struct mii_bus *mii_bus; ++ struct device_node *dn = pdev->dev.of_node; ++ struct resource *res; ++ struct iproc_mdiobus_private *bus_priv; ++ struct iproc_mdiobus_data *bus_data; ++ struct iproc_mdio_ctrl *cc_ctrl; ++ u32 mdio_clk_rate; ++ const char *mdio_bus_type; ++ struct clk *clk=NULL; ++ int ret; ++ ++ /* hw_ctrl is shared */ ++ if (cc_mdio_ctrl) ++ goto hw_ctrl_allocated; ++ ++ cc_ctrl = cc_mdio_res_alloc(); ++ if (!cc_ctrl) { ++ dev_err(&pdev->dev, "CC mdio resource alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ cc_ctrl->base = (void *)of_iomap(dn, 0); ++ if (!cc_ctrl->base) { ++ dev_err(&pdev->dev, "cc mdio register base map error\n"); ++ ret = -ENXIO; ++ goto err_ctrl_free; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "iproc-mdio-enable"); ++ if (res) { ++ cc_ctrl->iproc_mdio_enable_reg = ++ devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(cc_ctrl->iproc_mdio_enable_reg)) { ++ ret = PTR_ERR(cc_ctrl->iproc_mdio_enable_reg); ++ goto err_ctrl_free; ++ } ++ } ++ ++ if (cc_ctrl->iproc_mdio_enable_reg) { ++ if (of_property_read_u32(dn, "iproc-mdio-sel-bit", ++ &cc_ctrl->iproc_mdio_sel_bit)) { ++ dev_err(&pdev->dev, "No mdio bus select bit!\n"); ++ ret = -EINVAL; ++ goto err_ctrl_free; ++ } ++ } ++ ++hw_ctrl_allocated: ++ cc_ctrl = cc_mdio_ctrl; ++ ++ clk = of_clk_get(dn, 0); ++ if (clk) { ++ mdio_clk_rate = clk_get_rate(clk) / 2; ++ } else { ++ dev_warn(&pdev->dev, "No CC MDIO clock available in DT, \ ++ use default clock rate: 50MHz\n"); ++ mdio_clk_rate = 50000000; ++ } ++ ++ cc_mii_init(cc_ctrl, mdio_clk_rate); ++ ++ /* If no property available, use default: "internal" */ ++ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) ++ mdio_bus_type = "internal"; ++ ++ bus_data = devm_kzalloc(&pdev->dev, sizeof(*bus_data), GFP_KERNEL); ++ if (!bus_data) { ++ dev_err(&pdev->dev, "iProc MDIO bus data alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_bus_data_free; ++ } ++ ++ bus_priv = devm_kzalloc(&pdev->dev, sizeof(*bus_priv), GFP_KERNEL); ++ if (!bus_priv) { ++ dev_err(&pdev->dev, "iProc MDIO private data alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_bus_priv_free; ++ } ++ ++ if (!strcmp(mdio_bus_type, "internal")) ++ bus_data->phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; ++ else ++ bus_data->phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; ++ ++ bus_priv->bus_data = bus_data; ++ bus_priv->hw_ctrl = cc_ctrl; ++ ++ mii_bus = mdiobus_alloc(); ++ if (!mii_bus) { ++ dev_err(&pdev->dev, "mdiobus alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_ctrl_free; ++ } ++ ++ mii_bus->name = "iproc_cc_mdiobus"; ++ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s-%s", "cc mdio", ++ bus_data->phybus_type? "external":"internal"); ++ mii_bus->parent = &pdev->dev; ++ mii_bus->read = cc_mdiobus_read; ++ mii_bus->write = cc_mdiobus_write; ++ mii_bus->priv = bus_priv; ++ ++ ret = of_mdiobus_register(mii_bus, dn); ++ if (ret) { ++ dev_err(&pdev->dev, "mdiobus register failed\n"); ++ goto err_bus_free; ++ } ++ ++ platform_set_drvdata(pdev, mii_bus); ++ ++ return 0; ++ ++err_bus_free: ++ mdiobus_free(mii_bus); ++err_bus_priv_free: ++ kfree(bus_priv); ++err_bus_data_free: ++ kfree(bus_data); ++err_ctrl_free: ++ cc_mdio_res_free(cc_ctrl); ++err_exit: ++ return ret; ++} ++ ++static int cc_mdiobus_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *mii_bus = platform_get_drvdata(pdev); ++ struct iproc_mdiobus_private *bus_priv; ++ ++ if (mii_bus) { ++ bus_priv = mii_bus->priv; ++ ++ mdiobus_unregister(mii_bus); ++ if (bus_priv) ++ cc_mdio_res_free(bus_priv->hw_ctrl); ++ mdiobus_free(mii_bus); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id cc_mdio_dt_ids[] = { ++ { .compatible = "brcm,iproc-ccb-mdio"}, ++ { .compatible = "brcm,iproc-ccg-mdio"}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, cc_mdio_dt_ids); ++ ++ ++static struct platform_driver iproc_cc_mdiobus_driver = ++{ ++ .driver = { ++ .name = "iproc_cc_mdio", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(cc_mdio_dt_ids), ++ }, ++ .probe = cc_mdiobus_probe, ++ .remove = cc_mdiobus_remove, ++}; ++ ++static int __init cc_mdio_init(void) ++{ ++ return platform_driver_register(&iproc_cc_mdiobus_driver); ++} ++ ++static void __exit cc_mdio_exit(void) ++{ ++ platform_driver_unregister(&iproc_cc_mdiobus_driver); ++} ++ ++//module_init(cc_mdio_init); ++subsys_initcall(cc_mdio_init); ++module_exit(cc_mdio_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc CC mdio driver"); ++MODULE_LICENSE("GPL"); ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/mdio-xgs-iproc-cmicd.c b/drivers/net/phy/mdio-xgs-iproc-cmicd.c +--- a/drivers/net/phy/mdio-xgs-iproc-cmicd.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/mdio-xgs-iproc-cmicd.c 2018-05-10 11:31:32.085402292 +0800 +@@ -0,0 +1,457 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++#include ++ ++#include "mdio-xgs-iproc.h" ++ ++/* CMICD MDIO */ ++#define CMIC_MIIM_PARAM_OFFSET 0x080 ++#define CMIC_MIIM_PARAM_MIIM_CYCLE_R 29 ++#define CMIC_MIIM_PARAM_MIIM_CYCLE_W 3 ++#define CMIC_MIIM_PARAM_INTERNAL_SEL 25 ++#define CMIC_MIIM_PARAM_INTERNAL_SEL_W 1 ++#define CMIC_MIIM_PARAM_BUS_ID_R 22 ++#define CMIC_MIIM_PARAM_BUS_ID_W 3 ++#define CMIC_MIIM_PARAM_C45_SEL 21 ++#define CMIC_MIIM_PARAM_C45_SEL_W 1 ++#define CMIC_MIIM_PARAM_PHY_ID_R 16 ++#define CMIC_MIIM_PARAM_PHY_ID_W 5 ++#define CMIC_MIIM_PARAM_PHY_DATA_R 0 ++#define CMIC_MIIM_PARAM_PHY_DATA_W 16 ++ ++#define CMIC_MIIM_READ_DATA_OFFSET 0x084 ++#define CMIC_MIIM_READ_DATA_DATA_R 0 ++#define CMIC_MIIM_READ_DATA_DATA_W 16 ++ ++#define CMIC_MIIM_ADDR_OFFSET 0x088 ++#define CMIC_MIIM_ADDR_C45_DTYPE_R 16 ++#define CMIC_MIIM_ADDR_C45_DTYPE_W 5 ++#define CMIC_MIIM_ADDR_C45_REGADR_R 0 ++#define CMIC_MIIM_ADDR_C45_REGADR_W 16 ++#define CMIC_MIIM_ADDR_C22_REGADR_R 0 ++#define CMIC_MIIM_ADDR_C22_REGADR_W 5 ++ ++#define CMIC_MIIM_CTRL_OFFSET 0x08c ++#define CMIC_MIIM_CTRL_RD_START 1 ++#define CMIC_MIIM_CTRL_RD_START_W 1 ++#define CMIC_MIIM_CTRL_WR_START 0 ++#define CMIC_MIIM_CTRL_WR_START_W 1 ++ ++#define CMIC_MIIM_STAT_OFFSET 0x090 ++#define CMIC_MIIM_STAT_OPN_DONE 0 ++#define CMIC_MIIM_STAT_OPN_DONE_W 1 ++ ++#define CMIC_COMMON_UC0_PIO_ENDIANESS 0x1F0 ++ ++#define MIIM_PARAM_REG CMIC_MIIM_PARAM_OFFSET ++#define MIIM_PARAM_MIIM_CYCLE_SHIFT CMIC_MIIM_PARAM_MIIM_CYCLE_R ++#define MIIM_PARAM_MIIM_CYCLE_MASK ((1 << CMIC_MIIM_PARAM_MIIM_CYCLE_W)-1) ++#define MIIM_PARAM_INTERNAL_SEL_SHIFT CMIC_MIIM_PARAM_INTERNAL_SEL ++#define MIIM_PARAM_INTERNAL_SEL_MASK ((1<base + reg); ++#if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) ++ if (readl(cmic_mdio->base + CMIC_COMMON_UC0_PIO_ENDIANESS) != 0) ++ /* CMICD is in big-endian mode */ ++ value = swab32(value); ++#endif ++ return value; ++} ++ ++static inline void cmicd_miim_reg_write(struct iproc_mdio_ctrl *cmic_mdio, ++ u32 reg, u32 data) ++{ ++ u32 value = data; ++#if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) ++ if (readl(cmic_mdio->base + CMIC_COMMON_UC0_PIO_ENDIANESS) != 0) ++ /* CMICD is in big-endian mode */ ++ value = swab32(data); ++#endif ++ writel(value, cmic_mdio->base + reg); ++} ++ ++static inline void cmicd_miim_set_op_read(u32 *data, u32 set) ++{ ++ SET_REG_FIELD(*data, MIIM_CTRL_RD_START_SHIFT, ++ MIIM_CTRL_RD_START_MASK, set); ++} ++ ++static inline void cmicd_miim_set_op_write(u32 *data, u32 set) ++{ ++ SET_REG_FIELD(*data, MIIM_CTRL_WR_START_SHIFT, ++ MIIM_CTRL_WR_START_MASK, set); ++} ++ ++static int do_cmicd_miim_op(struct iproc_mdio_ctrl *cmic_mdio, u32 op, ++ u32 param, u32 addr) ++{ ++ u32 val, op_done; ++ unsigned long flags; ++ int ret = 0; ++ int usec = MII_OP_MAX_HALT_USEC; ++ ++ if (op >= MII_OP_MODE_MAX) { ++ pr_err("%s : invalid op code %d\n", __func__, op); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&cmic_mdio->lock, flags); ++ ++ cmicd_miim_reg_write(cmic_mdio, MIIM_PARAM_REG, param); ++ cmicd_miim_reg_write(cmic_mdio, MIIM_ADDRESS_REG, addr); ++ val = cmicd_miim_reg_read(cmic_mdio, MIIM_CTRL_REG); ++ if(op == MII_OP_MODE_READ) ++ cmicd_miim_set_op_read(&val, 1); ++ else ++ cmicd_miim_set_op_write(&val, 1); ++ cmicd_miim_reg_write(cmic_mdio, MIIM_CTRL_REG, val); ++ ++ do { ++ op_done = GET_REG_FIELD( ++ cmicd_miim_reg_read(cmic_mdio, MIIM_STAT_REG), ++ MIIM_STAT_OPN_DONE_SHIFT, ++ MIIM_STAT_OPN_DONE_MASK); ++ if (op_done) ++ break; ++ ++ udelay(1); ++ } while (usec-- > 0); ++ ++ if (op_done) { ++ if(op == MII_OP_MODE_READ) ++ ret = cmicd_miim_reg_read(cmic_mdio, MIIM_READ_DATA_REG); ++ } else { ++ ret = -ETIME; ++ } ++ ++ val = cmicd_miim_reg_read(cmic_mdio, MIIM_CTRL_REG); ++ if(op == MII_OP_MODE_READ) ++ cmicd_miim_set_op_read(&val, 0); ++ else ++ cmicd_miim_set_op_write(&val, 0); ++ cmicd_miim_reg_write(cmic_mdio, MIIM_CTRL_REG, val); ++ ++ spin_unlock_irqrestore(&cmic_mdio->lock, flags); ++ ++ return ret; ++} ++ ++ ++static int cmicd_miim_op(struct iproc_mdio_ctrl *cmic_mdio, ++ struct cmicd_miim_cmd *cmd) ++{ ++ u32 miim_param =0, miim_addr = 0; ++ ++ ISET_REG_FIELD(miim_param, MIIM_PARAM_BUS_ID_SHIFT, ++ MIIM_PARAM_BUS_ID_MASK, cmd->bus_id); ++ ++ if (cmd->int_sel) ++ ISET_REG_FIELD(miim_param, MIIM_PARAM_INTERNAL_SEL_SHIFT, ++ MIIM_PARAM_INTERNAL_SEL_MASK, 1); ++ ++ ISET_REG_FIELD(miim_param, MIIM_PARAM_PHY_ID_SHIFT, ++ MIIM_PARAM_PHY_ID_MASK, cmd->phy_id); ++ ++ if (cmd->op_mode == MII_OP_MODE_WRITE) ++ ISET_REG_FIELD(miim_param, MIIM_PARAM_PHY_DATA_SHIFT, ++ MIIM_PARAM_PHY_DATA_MASK, cmd->val); ++ ++ if (cmd->c45_sel) { ++ ISET_REG_FIELD(miim_param, MIIM_PARAM_C45_SEL_SHIFT, ++ MIIM_PARAM_C45_SEL_MASK, 1); ++ ISET_REG_FIELD(miim_addr, MIIM_ADDR_C45_REGADR_SHIFT, ++ MIIM_ADDR_C45_REGADR_MASK, cmd->regnum); ++ ISET_REG_FIELD(miim_addr, MIIM_ADDR_C45_DTYPE_SHIFT, ++ MIIM_ADDR_C45_REGADR_MASK, cmd->regnum >> 16); ++ } ++ else { ++ ISET_REG_FIELD(miim_addr, MIIM_ADDR_C22_REGADR_SHIFT, ++ MIIM_ADDR_C22_REGADR_MASK, cmd->regnum); ++ } ++ ++ return do_cmicd_miim_op(cmic_mdio, cmd->op_mode, miim_param, miim_addr); ++} ++ ++ ++static int cmicd_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) ++{ ++ struct iproc_mdiobus_private *bus_priv = bus->priv; ++ struct iproc_mdiobus_data *bus_data = bus_priv->bus_data; ++ struct cmicd_miim_cmd cmd = {0}; ++ ++ cmd.bus_id = bus_data->phybus_num; ++ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) ++ cmd.int_sel = 1; ++ cmd.phy_id = phy_id; ++ cmd.regnum = regnum; ++ ++ if (regnum & MII_ADDR_C45) ++ cmd.c45_sel = 1; ++ ++ cmd.op_mode = MII_OP_MODE_READ; ++ ++ return cmicd_miim_op(bus_priv->hw_ctrl, &cmd); ++} ++ ++static int cmicd_mdiobus_write(struct mii_bus *bus, int phy_id, ++ int regnum, u16 val) ++{ ++ struct iproc_mdiobus_private *bus_priv = bus->priv; ++ struct iproc_mdiobus_data *bus_data = bus_priv->bus_data; ++ struct cmicd_miim_cmd cmd = {0}; ++ ++ cmd.bus_id = bus_data->phybus_num; ++ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) ++ cmd.int_sel = 1; ++ cmd.phy_id = phy_id; ++ cmd.regnum = regnum; ++ cmd.val = val; ++ ++ if (regnum & MII_ADDR_C45) ++ cmd.c45_sel = 1; ++ ++ cmd.op_mode = MII_OP_MODE_WRITE; ++ ++ return cmicd_miim_op(bus_priv->hw_ctrl, &cmd); ++} ++ ++static struct iproc_mdio_ctrl * cmicd_mdio_res_alloc(void) ++{ ++ if (!cmic_common) { ++ cmic_common = kzalloc(sizeof(*cmic_common), GFP_KERNEL); ++ if (!cmic_common) ++ return NULL; ++ spin_lock_init(&cmic_common->lock); ++ cmic_common->ref_cnt = 1; ++ } ++ else ++ cmic_common->ref_cnt++; ++ ++ return cmic_common; ++} ++ ++static void cmicd_mdio_res_free(struct iproc_mdio_ctrl *ctrl) ++{ ++ if (ctrl) { ++ ctrl->ref_cnt--; ++ if (ctrl->ref_cnt == 0) { ++ iounmap(ctrl->base); ++ kfree(ctrl); ++ cmic_common = NULL; ++ } ++ } ++} ++ ++static int cmicd_mdiobus_probe(struct platform_device *pdev) ++{ ++ struct mii_bus *mii_bus; ++ struct device_node *dn = pdev->dev.of_node; ++ struct iproc_mdiobus_private *bus_priv; ++ struct iproc_mdiobus_data *bus_data; ++ struct iproc_mdio_ctrl *cmicd_ctrl; ++ u32 mdio_bus_id; ++ const char *mdio_bus_type; ++ int ret; ++ ++ cmicd_ctrl = cmicd_mdio_res_alloc(); ++ if (!cmicd_ctrl) { ++ dev_err(&pdev->dev, "cmicd mdio resource alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* Get register base address for the first mdio node only */ ++ if (!cmicd_ctrl->base) ++ cmicd_ctrl->base = of_iomap(dn, 0); ++ if (!cmicd_ctrl->base) { ++ dev_err(&pdev->dev, "cmicd mdio register base map error\n"); ++ ret = -ENXIO; ++ goto err_ctrl_free; ++ } ++ ++ /* If no property available, use default: 2 */ ++ if (of_property_read_u32(dn, "#bus-id", &mdio_bus_id)) ++ mdio_bus_id = 2; ++ ++ /* If no property available, use default: "external" */ ++ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) ++ mdio_bus_type = "external"; ++ ++ bus_data = devm_kzalloc(&pdev->dev, sizeof(*bus_data), GFP_KERNEL); ++ if (!bus_data) { ++ dev_err(&pdev->dev, "iProc MDIO bus data alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_bus_data_free; ++ } ++ ++ bus_priv = devm_kzalloc(&pdev->dev, sizeof(*bus_priv), GFP_KERNEL); ++ if (!bus_priv) { ++ dev_err(&pdev->dev, "iProc MDIO private data alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_bus_priv_free; ++ } ++ ++ bus_data->phybus_num = mdio_bus_id; ++ if (!strcmp(mdio_bus_type, "internal")) ++ bus_data->phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; ++ else ++ bus_data->phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; ++ ++ bus_priv->bus_data = bus_data; ++ bus_priv->hw_ctrl = cmicd_ctrl; ++ ++ mii_bus = mdiobus_alloc(); ++ if (!mii_bus) { ++ dev_err(&pdev->dev, "mdiobus_alloc failed\n"); ++ ret = -ENOMEM; ++ goto err_ctrl_free; ++ } ++ ++ mii_bus->name = "iproc_cmicd_mdiobus"; ++ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s-%d-%d", "cmicd mdio", ++ mdio_bus_id, bus_data->phybus_type? 1:0); ++ mii_bus->parent = &pdev->dev; ++ mii_bus->read = cmicd_mdiobus_read; ++ mii_bus->write = cmicd_mdiobus_write; ++ mii_bus->priv = bus_priv; ++ ++ ret = of_mdiobus_register(mii_bus, dn); ++ if (ret) { ++ dev_err(&pdev->dev, "mdiobus register failed\n"); ++ goto err_bus_free; ++ } ++ ++ platform_set_drvdata(pdev, mii_bus); ++ ++ return 0; ++ ++err_bus_free: ++ mdiobus_free(mii_bus); ++err_bus_priv_free: ++ kfree(bus_priv); ++err_bus_data_free: ++ kfree(bus_data); ++err_ctrl_free: ++ cmicd_mdio_res_free(cmicd_ctrl); ++err_exit: ++ return ret; ++} ++ ++static int cmicd_mdiobus_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *mii_bus = platform_get_drvdata(pdev); ++ struct iproc_mdiobus_private *bus_priv; ++ ++ if (mii_bus) { ++ bus_priv = mii_bus->priv; ++ ++ mdiobus_unregister(mii_bus); ++ if (bus_priv) ++ cmicd_mdio_res_free(bus_priv->hw_ctrl); ++ mdiobus_free(mii_bus); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id cmicd_mdio_dt_ids[] = { ++ { .compatible = "brcm,iproc-cmicd-mdio"}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, cmicd_mdio_dt_ids); ++ ++static struct platform_driver iproc_cmicd_mdiobus_driver = ++{ ++ .driver = { ++ .name = "iproc_cmicd_mdio", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(cmicd_mdio_dt_ids), ++ }, ++ .probe = cmicd_mdiobus_probe, ++ .remove = cmicd_mdiobus_remove, ++}; ++ ++static int __init cmicd_mdio_init(void) ++{ ++ return platform_driver_register(&iproc_cmicd_mdiobus_driver); ++} ++ ++static void __exit cmicd_mdio_exit(void) ++{ ++ platform_driver_unregister(&iproc_cmicd_mdiobus_driver); ++} ++ ++//module_init(cmicd_mdio_init); ++subsys_initcall(cmicd_mdio_init); ++module_exit(cmicd_mdio_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc CMICd mdio driver"); ++MODULE_LICENSE("GPL"); ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/mdio-xgs-iproc-cmicx.c b/drivers/net/phy/mdio-xgs-iproc-cmicx.c +--- a/drivers/net/phy/mdio-xgs-iproc-cmicx.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/mdio-xgs-iproc-cmicx.c 2018-05-30 15:50:51.032753168 +0800 +@@ -0,0 +1,543 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++#include ++ ++#include "mdio-xgs-iproc.h" ++ ++#define MIIM_CH0_CONTROL_REG 0x000 ++#define MIIM_CH1_CONTROL_REG 0x010 ++#define MIIM_CH2_CONTROL_REG 0x020 ++#define MIIM_CH3_CONTROL_REG 0x030 ++#define MIIM_CONTROL__START_SHIFT 0 ++#define MIIM_CONTROL__START_WIDTH 1 ++#define MIIM_CONTROL__START_MASK ((1 << MIIM_CONTROL__START_WIDTH) - 1) ++#define MIIM_CH0_PARAMS_REG 0x004 ++#define MIIM_CH1_PARAMS_REG 0x014 ++#define MIIM_CH2_PARAMS_REG 0x024 ++#define MIIM_CH3_PARAMS_REG 0x034 ++#define MIIM_PARAMS__RING_MAP_SHIFT 20 ++#define MIIM_PARAMS__RING_MAP_WIDTH 12 ++#define MIIM_PARAMS__RING_MAP_MASK ((1 << MIIM_PARAMS__RING_MAP_WIDTH) - 1) ++#define MIIM_PARAMS__MDIO_OP_TYPE_SHIFT 17 ++#define MIIM_PARAMS__MDIO_OP_TYPE_WIDTH 3 ++#define MIIM_PARAMS__MDIO_OP_TYPE_MASK ((1 << MIIM_PARAMS__MDIO_OP_TYPE_WIDTH) - 1) ++#define CLAUSE_22_WRITE_OP_MODE 0x0 ++#define CLAUSE_22_READ_OP_MODE 0x1 ++#define CLAUSE_45_WRITE_OP_MODE 0x5 ++#define CLAUSE_45_READ_OP_MODE 0x6 ++#define MIIM_PARAMS__SEL_INT_PHY_SHIFT 16 ++#define MIIM_PARAMS__SEL_INT_PHY_WIDTH 1 ++#define MIIM_PARAMS__SEL_INT_PHY_MASK ((1 << MIIM_PARAMS__SEL_INT_PHY_WIDTH) - 1) ++#define MIIM_PARAMS__PHY_WR_DATA_SHIFT 0 ++#define MIIM_PARAMS__PHY_WR_DATA_WIDTH 16 ++#define MIIM_PARAMS__PHY_WR_DATA_MASK ((1 << MIIM_PARAMS__PHY_WR_DATA_WIDTH) - 1) ++#define MIIM_CH0_ADDRESS_REG 0x008 ++#define MIIM_CH1_ADDRESS_REG 0x018 ++#define MIIM_CH2_ADDRESS_REG 0x028 ++#define MIIM_CH3_ADDRESS_REG 0x038 ++#define MIIM_ADDRESS__C45_REGADDR_SHIFT 16 ++#define MIIM_ADDRESS__C45_REGADDR_WIDTH 16 ++#define MIIM_ADDRESS__C45_REGADDR_MASK ((1 << MIIM_ADDRESS__C45_REGADDR_WIDTH) - 1) ++#define MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_SHIFT 11 ++#define MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_WIDTH 5 ++#define MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_MASK ((1 << MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_WIDTH) - 1) ++#define MIIM_ADDRESS__PHY_ID_SHIFT 6 ++#define MIIM_ADDRESS__PHY_ID_WIDTH 5 ++#define MIIM_ADDRESS__PHY_ID_MASK ((1 << MIIM_ADDRESS__PHY_ID_WIDTH) - 1) ++#define MIIM_CH0_STATUS_REG 0x00c ++#define MIIM_CH1_STATUS_REG 0x01c ++#define MIIM_CH2_STATUS_REG 0x02c ++#define MIIM_CH3_STATUS_REG 0x03c ++#define MIIM_STATUS__DONE_SHIFT 18 ++#define MIIM_STATUS__DONE_WIDTH 1 ++#define MIIM_STATUS__DONE_MASK ((1 << MIIM_STATUS__DONE_WIDTH) - 1) ++#define MIIM_STATUS__ERROR_SHIFT 17 ++#define MIIM_STATUS__ERROR_WIDTH 1 ++#define MIIM_STATUS__ERROR_MASK ((1 << MIIM_STATUS__ERROR_WIDTH) - 1) ++#define MIIM_STATUS__ACTIVE_SHIFT 16 ++#define MIIM_STATUS__ACTIVE_WIDTH 1 ++#define MIIM_STATUS__ACTIVE_MASK ((1 << MIIM_STATUS__ACTIVE_WIDTH) - 1) ++#define MIIM_STATUS__PHY_RD_DATA_SHIFT 0 ++#define MIIM_STATUS__PHY_RD_DATA_WIDTH 16 ++#define MIIM_STATUS__PHY_RD_DATA_MASK ((1 << MIIM_STATUS__PHY_RD_DATA_WIDTH) - 1) ++#define MIIM_RING0_CONTROL_REG 0x0f0 ++#define MIIM_RING1_CONTROL_REG 0x0f4 ++#define MIIM_RING2_CONTROL_REG 0x0f8 ++#define MIIM_RING3_CONTROL_REG 0x0fc ++#define MIIM_RING4_CONTROL_REG 0x100 ++#define MIIM_RING5_CONTROL_REG 0x104 ++#define MIIM_RING6_CONTROL_REG 0x108 ++#define MIIM_RING7_CONTROL_REG 0x10c ++#define MIIM_RING8_CONTROL_REG 0x110 ++#define MIIM_RING9_CONTROL_REG 0x114 ++#define MIIM_RING10_CONTROL_REG 0x118 ++#define MIIM_RING11_CONTROL_REG 0x11c ++#define MIIM_RING_CTRL__MDC_MODE_SHIFT 26 ++#define MIIM_RING_CTRL__MDC_MODE_WIDTH 1 ++#define MIIM_RING_CTRL__MDC_MODE_MASK ((1 << MIIM_RING_CTRL__MDC_MODE_WIDTH) - 1) ++#define MIIM_RING_CTRL__PREAMBLE_SHIFT 24 ++#define MIIM_RING_CTRL__PREAMBLE_WIDTH 2 ++#define MIIM_RING_CTRL__PREAMBLE_MASK ((1 << MIIM_RING_CTRL__PREAMBLE_WIDTH) - 1) ++#define MIIM_RING_CTRL__MDIO_OUT_DELAY_SHIFT 16 ++#define MIIM_RING_CTRL__MDIO_OUT_DELAY_WIDTH 8 ++#define MIIM_RING_CTRL__MDIO_OUT_DELAY_MASK ((1 << MIIM_RING_CTRL__MDIO_OUT_DELAY_WIDTH) - 1) ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_SHIFT 8 ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_WIDTH 8 ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_MASK ((1 << MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_WIDTH) - 1) ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_INT_SHIFT 0 ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_INT_WIDTH 8 ++#define MIIM_RING_CTRL__CLOCK_DIVIDER_INT_MASK ((1 << MIIM_RING_CTRL__CLOCK_DIVIDER_INT_WIDTH) - 1) ++#define MIIM_COMMON_CONTROL_REG 0x140 ++#define MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_SHIFT 0 ++#define MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_WIDTH 1 ++#define MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_MASK ((1 << MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_WIDTH) - 1) ++ ++#define MIIM_MAX_RINGS 12 ++ ++struct cmicx_miim_cmd { ++ u32 bus_id; ++ u32 int_sel; ++ u32 phy_id; ++ u32 reg_num; ++ u32 c45_sel; ++ u16 op_mode; ++ u16 phy_data; ++}; ++ ++static inline u32 cmicx_miim_read(struct iproc_mdio_ctrl *mdio_ctrl, u32 reg) ++{ ++ return readl(mdio_ctrl->base + reg); ++} ++ ++static inline void cmicx_miim_write(struct iproc_mdio_ctrl *mdio_ctrl, ++ u32 reg, u32 data) ++{ ++ writel(data, mdio_ctrl->base + reg); ++} ++ ++static int cmicx_miim_init(struct iproc_mdio_ctrl *mdio_ctrl) ++{ ++ u32 val; ++ u32 mstr_ctrl; ++ ++ /* Give MDIO control to IPROC */ ++ val = cmicx_miim_read(mdio_ctrl, MIIM_COMMON_CONTROL_REG); ++ mstr_ctrl = GET_REG_FIELD(val, MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_SHIFT, ++ MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_MASK); ++ if (!mstr_ctrl) { ++ ISET_REG_FIELD(val, MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_SHIFT, ++ MIIM_COMM_CTRL__EXT_MDIO_MSTR_CNTRL_MASK, 1); ++ cmicx_miim_write(mdio_ctrl, MIIM_COMMON_CONTROL_REG, val); ++ } ++ return 0; ++} ++ ++static int cmicx_miim_ring_init(struct iproc_mdio_ctrl *mdio_ctrl, u32 ring_idx, ++ int int_divider, int ext_divider, int out_delay) ++{ ++ u32 ring_ctrl_reg[] = { MIIM_RING0_CONTROL_REG, ++ MIIM_RING1_CONTROL_REG, ++ MIIM_RING2_CONTROL_REG, ++ MIIM_RING3_CONTROL_REG, ++ MIIM_RING4_CONTROL_REG, ++ MIIM_RING5_CONTROL_REG, ++ MIIM_RING6_CONTROL_REG, ++ MIIM_RING7_CONTROL_REG, ++ MIIM_RING8_CONTROL_REG, ++ MIIM_RING9_CONTROL_REG, ++ MIIM_RING10_CONTROL_REG, ++ MIIM_RING11_CONTROL_REG }; ++ u32 val; ++ ++ if (ring_idx >= MIIM_MAX_RINGS) { ++ return -EINVAL; ++ } ++ ++ val = cmicx_miim_read(mdio_ctrl, ring_ctrl_reg[ring_idx]); ++ if (int_divider != -1) { ++ ISET_REG_FIELD(val, MIIM_RING_CTRL__CLOCK_DIVIDER_INT_SHIFT, ++ MIIM_RING_CTRL__CLOCK_DIVIDER_INT_MASK, int_divider); ++ } ++ if (ext_divider != -1) { ++ ISET_REG_FIELD(val, MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_SHIFT, ++ MIIM_RING_CTRL__CLOCK_DIVIDER_EXT_MASK, ext_divider); ++ } ++ if (out_delay != -1) { ++ ISET_REG_FIELD(val, MIIM_RING_CTRL__MDIO_OUT_DELAY_SHIFT, ++ MIIM_RING_CTRL__MDIO_OUT_DELAY_MASK, out_delay); ++ } ++ cmicx_miim_write(mdio_ctrl, ring_ctrl_reg[ring_idx], val); ++ ++ return 0; ++} ++ ++static int cmicx_miim_operation(struct iproc_mdio_ctrl *mdio_ctrl, ++ struct cmicx_miim_cmd *miim_cmd) ++{ ++ unsigned long flags; ++ u32 is_done, is_error; ++ u32 optype = 0; ++ u32 val; ++ int usec = MII_OP_MAX_HALT_USEC; ++ int ret = 0,bus_id = miim_cmd->bus_id; ++ ++ spin_lock_irqsave(&mdio_ctrl->lock, flags); ++ ++ /* prepare transaction data */ ++ //val = cmicx_miim_read(mdio_ctrl, (MIIM_CH0_ADDRESS_REG + 0x10 * bus_id)); ++ val = 0; ++ ISET_REG_FIELD(val, MIIM_ADDRESS__PHY_ID_SHIFT, ++ MIIM_ADDRESS__PHY_ID_MASK, miim_cmd->phy_id); ++ if (miim_cmd->c45_sel) { ++ ISET_REG_FIELD(val, MIIM_ADDRESS__C45_REGADDR_SHIFT, ++ MIIM_ADDRESS__C45_REGADDR_MASK, miim_cmd->reg_num); ++ ISET_REG_FIELD(val, MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_SHIFT, ++ MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_MASK, (miim_cmd->reg_num >> 16)); ++ } else { ++ ISET_REG_FIELD(val, MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_SHIFT, ++ MIIM_ADDRESS__C22_REGADDR_C45_DTYPE_MASK, miim_cmd->reg_num); ++ } ++ //cmicx_miim_write(mdio_ctrl, MIIM_CH1_ADDRESS_REG, val); ++ cmicx_miim_write(mdio_ctrl, (MIIM_CH0_ADDRESS_REG + 0x10 * bus_id), val); ++ ++ /* _SOC_IF_ERR_EXIT(READ_MIIM_CH0_PARAMSr(unit, ®_val)); */ ++ //val = cmicx_miim_read(mdio_ctrl, (MIIM_CH0_PARAMS_REG + 0x10 * bus_id)); ++ val = 0; ++ ISET_REG_FIELD(val, MIIM_PARAMS__PHY_WR_DATA_SHIFT, ++ MIIM_PARAMS__PHY_WR_DATA_MASK, miim_cmd->phy_data); ++ ISET_REG_FIELD(val, MIIM_PARAMS__SEL_INT_PHY_SHIFT, ++ MIIM_PARAMS__SEL_INT_PHY_MASK, miim_cmd->int_sel); ++ ISET_REG_FIELD(val, MIIM_PARAMS__RING_MAP_SHIFT, ++ MIIM_PARAMS__RING_MAP_MASK, (1 << miim_cmd->bus_id)); ++ if (miim_cmd->c45_sel) { ++ optype = CLAUSE_45_READ_OP_MODE; ++ if (miim_cmd->op_mode == MII_OP_MODE_WRITE) { ++ optype = CLAUSE_45_WRITE_OP_MODE; ++ } ++ } else { ++ optype = CLAUSE_22_READ_OP_MODE; ++ if (miim_cmd->op_mode == MII_OP_MODE_WRITE) { ++ optype = CLAUSE_22_WRITE_OP_MODE; ++ } ++ } ++ ISET_REG_FIELD(val, MIIM_PARAMS__MDIO_OP_TYPE_SHIFT, ++ MIIM_PARAMS__MDIO_OP_TYPE_MASK, optype); ++ //cmicx_miim_write(mdio_ctrl, MIIM_CH1_PARAMS_REG, val); ++ cmicx_miim_write(mdio_ctrl, (MIIM_CH0_PARAMS_REG + 0x10 * bus_id), val); ++ ++ /* start transaction */ ++ val = 0; ++ ISET_REG_FIELD(val, MIIM_CONTROL__START_SHIFT, ++ MIIM_CONTROL__START_MASK, 0x1); ++ //cmicx_miim_write(mdio_ctrl, MIIM_CH1_CONTROL_REG, val); ++ cmicx_miim_write(mdio_ctrl, (MIIM_CH0_CONTROL_REG + 0x10 * bus_id), val); ++ ++ /* poll for DONE bit */ ++ do { ++ //val = cmicx_miim_read(mdio_ctrl, MIIM_CH1_STATUS_REG); ++ val = cmicx_miim_read(mdio_ctrl, (MIIM_CH0_STATUS_REG + 0x10 * bus_id)); ++ is_done = GET_REG_FIELD(val, MIIM_STATUS__DONE_SHIFT, MIIM_STATUS__DONE_MASK); ++ if (is_done) { ++ break; /* MIIM operation is done */ ++ } ++ ++ udelay(1); ++ } while (usec-- > 0); ++ ++ /* check for transaction error */ ++ //val = cmicx_miim_read(mdio_ctrl, MIIM_CH1_STATUS_REG); ++ val = cmicx_miim_read(mdio_ctrl, (MIIM_CH0_STATUS_REG + 0x10 * bus_id)); ++ is_error = GET_REG_FIELD(val, MIIM_STATUS__ERROR_SHIFT, MIIM_STATUS__ERROR_MASK); ++ if (is_error) { ++ printk(KERN_ERR "%s : mdio execution error.\n", __func__); ++ ret = -EIO; ++ goto exit; ++ } ++ ++ /* in case of read - get data */ ++ if (miim_cmd->op_mode == MII_OP_MODE_READ) { ++ miim_cmd->phy_data = GET_REG_FIELD(val, MIIM_STATUS__PHY_RD_DATA_SHIFT, ++ MIIM_STATUS__PHY_RD_DATA_MASK); ++ } ++ ++exit: ++ /* cleanup */ ++ //cmicx_miim_write(mdio_ctrl, MIIM_CH1_CONTROL_REG, 0); ++ cmicx_miim_write(mdio_ctrl, (MIIM_CH0_CONTROL_REG + 0x10 * bus_id), 0); ++ spin_unlock_irqrestore(&mdio_ctrl->lock, flags); ++ ++ return ret; ++} ++ ++static int cmicx_mdiobus_read(struct mii_bus *bus, int phy_id, int reg_num) ++{ ++ struct iproc_mdiobus_private *mdio_bus_priv = bus->priv; ++ struct iproc_mdiobus_data *mdio_bus_data = mdio_bus_priv->bus_data; ++ struct cmicx_miim_cmd miim_cmd = { 0 }; ++ int ret = 0; ++ ++ if (IPROC_MDIOBUS_TYPE_INTERNAL == mdio_bus_data->phybus_type) { ++ miim_cmd.int_sel = 1; ++ } ++ if (reg_num & MII_ADDR_C45) { ++ miim_cmd.c45_sel = 1; ++ } ++ miim_cmd.bus_id = mdio_bus_data->phybus_num; ++ miim_cmd.phy_id = phy_id; ++ miim_cmd.reg_num = reg_num; ++ miim_cmd.op_mode = MII_OP_MODE_READ; ++ miim_cmd.phy_data = 0; ++ ++ ret = cmicx_miim_operation(mdio_bus_priv->hw_ctrl, &miim_cmd); ++ if (ret == 0) { ++ return miim_cmd.phy_data; ++ } ++ return ret; ++} ++ ++static int cmicx_mdiobus_write(struct mii_bus *bus, int phy_id, ++ int reg_num, u16 val) ++{ ++ struct iproc_mdiobus_private *mdio_bus_priv = bus->priv; ++ struct iproc_mdiobus_data *mdio_bus_data = mdio_bus_priv->bus_data; ++ struct cmicx_miim_cmd miim_cmd = {0}; ++ ++ if (IPROC_MDIOBUS_TYPE_INTERNAL == mdio_bus_data->phybus_type) { ++ miim_cmd.int_sel = 1; ++ } ++ if (reg_num & MII_ADDR_C45) { ++ miim_cmd.c45_sel = 1; ++ } ++ miim_cmd.bus_id = mdio_bus_data->phybus_num; ++ miim_cmd.phy_id = phy_id; ++ miim_cmd.reg_num = reg_num; ++ miim_cmd.op_mode = MII_OP_MODE_WRITE; ++ miim_cmd.phy_data = val; ++ ++ return cmicx_miim_operation(mdio_bus_priv->hw_ctrl, &miim_cmd); ++} ++ ++/************************************************************************************* ++**************************************************************************************/ ++static int cmicx_mdiobus_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *dn = pdev->dev.of_node; ++ struct mii_bus *mii_bus = NULL; ++ struct iproc_mdiobus_private *mdio_bus_priv = NULL; ++ struct iproc_mdiobus_data *mdio_bus_data = NULL; ++ struct iproc_mdio_ctrl *mdio_ctrl = NULL; ++ u32 mdio_bus_id; ++ int clock_divider, out_delay; ++ int divider_int = -1, divider_ext = -1; ++ const char *mdio_bus_type; ++ int ret; ++ ++ mdio_ctrl = devm_kzalloc(dev, sizeof(*mdio_ctrl), GFP_KERNEL); ++ if (!mdio_ctrl) { ++ dev_err(dev, "cmicx mdio resource allocated failed\n"); ++ return -ENOMEM; ++ } ++ ++ spin_lock_init(&mdio_ctrl->lock); ++ ++ /* Get register base address */ ++ mdio_ctrl->base = of_iomap(dn, 0); ++ if (!mdio_ctrl->base) { ++ dev_err(dev, "cmicx mdio register base map error\n"); ++ ret = -ENXIO; ++ goto err; ++ } ++ ++ /* If no property available, use default: 2 */ ++ if (of_property_read_u32(dn, "#bus-id", &mdio_bus_id)) { ++ mdio_bus_id = 2; ++ } ++ ++ /* If no property available, use default: "external" */ ++ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) { ++ mdio_bus_type = "external"; ++ } ++ ++ /* If no property available, use default: -1 */ ++ if (of_property_read_u32(dn, "#divider", &clock_divider)) { ++ clock_divider = -1; ++ } ++ ++ /* If no property available, use default: -1 */ ++ if (of_property_read_u32(dn, "#delay", &out_delay)) { ++ out_delay = -1; ++ } ++ ++ mdio_bus_data = devm_kzalloc(dev, sizeof(*mdio_bus_data), GFP_KERNEL); ++ if (!mdio_bus_data) { ++ dev_err(dev, "iProc MDIO bus data allocated failed\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ mdio_bus_data->phybus_num = mdio_bus_id; ++ if (!strcmp(mdio_bus_type, "internal")) { ++ mdio_bus_data->phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; ++ divider_int = clock_divider; ++ } else { ++ mdio_bus_data->phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; ++ divider_ext = clock_divider; ++ } ++ ++ mdio_bus_priv = devm_kzalloc(dev, sizeof(*mdio_bus_priv), GFP_KERNEL); ++ if (!mdio_bus_priv) { ++ dev_err(dev, "iProc MDIO private data allocated failed\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ mdio_bus_priv->bus_data = mdio_bus_data; ++ mdio_bus_priv->hw_ctrl = mdio_ctrl; ++ ++ ret = cmicx_miim_init(mdio_ctrl); ++ if (ret) { ++ dev_err(dev, "cmicx init failed\n"); ++ goto err; ++ } ++ ++ ret = cmicx_miim_ring_init(mdio_ctrl, mdio_bus_id, ++ divider_int, divider_ext, out_delay); ++ if (ret) { ++ dev_err(dev, "cmicx init ring failed\n"); ++ goto err; ++ } ++ ++ mii_bus = mdiobus_alloc(); ++ if (!mii_bus) { ++ dev_err(dev, "MII bus memory allocated failed\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ mii_bus->name = "iproc_cmicx_mdiobus"; ++ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s-%d-%d", "cmicx mdio", mdio_bus_id, ++ (mdio_bus_data->phybus_type == IPROC_MDIOBUS_TYPE_EXTERNAL) ? 1 : 0); ++ mii_bus->parent = dev; ++ mii_bus->read = cmicx_mdiobus_read; ++ mii_bus->write = cmicx_mdiobus_write; ++ mii_bus->priv = mdio_bus_priv; ++ ++ ret = of_mdiobus_register(mii_bus, dn); ++ if (ret) { ++ dev_err(dev, "mdiobus register failed\n"); ++ goto err; ++ } ++ ++ platform_set_drvdata(pdev, mii_bus); ++ ++ return 0; ++ ++err: ++ if (mii_bus) { ++ mdiobus_free(mii_bus); ++ } ++ if (mdio_bus_priv) { ++ devm_kfree(dev, mdio_bus_priv); ++ } ++ if (mdio_bus_data) { ++ devm_kfree(dev, mdio_bus_data); ++ } ++ if (mdio_ctrl->base) { ++ iounmap(mdio_ctrl->base); ++ } ++ if (mdio_ctrl) { ++ devm_kfree(dev, mdio_ctrl); ++ } ++ ++ return ret; ++} ++ ++static int cmicx_mdiobus_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mii_bus *mii_bus = platform_get_drvdata(pdev); ++ struct iproc_mdiobus_private *mdio_bus_priv; ++ struct iproc_mdiobus_data *mdio_bus_data; ++ struct iproc_mdio_ctrl *mdio_ctrl; ++ ++ if (mii_bus) { ++ mdio_bus_priv = mii_bus->priv; ++ mdio_bus_data = mdio_bus_priv->bus_data; ++ mdio_ctrl = mdio_bus_priv->hw_ctrl; ++ ++ mdiobus_unregister(mii_bus); ++ mdiobus_free(mii_bus); ++ ++ if (mdio_bus_priv) { ++ if (mdio_ctrl) { ++ if (mdio_ctrl->base) { ++ iounmap(mdio_ctrl->base); ++ } ++ devm_kfree(dev, mdio_ctrl); ++ } ++ if (mdio_bus_data) { ++ devm_kfree(dev, mdio_bus_data); ++ } ++ devm_kfree(dev, mdio_bus_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id cmicx_mdio_dt_ids[] = { ++ { .compatible = "brcm,iproc-cmicx-mdio"}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, cmicx_mdio_dt_ids); ++ ++static struct platform_driver iproc_cmicx_mdiobus_driver = ++{ ++ .driver = { ++ .name = "iproc_cmicx_mdio", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(cmicx_mdio_dt_ids), ++ }, ++ .probe = cmicx_mdiobus_probe, ++ .remove = cmicx_mdiobus_remove, ++}; ++ ++static int __init cmicx_mdio_init(void) ++{ ++ return platform_driver_register(&iproc_cmicx_mdiobus_driver); ++} ++ ++static void __exit cmicx_mdio_exit(void) ++{ ++ platform_driver_unregister(&iproc_cmicx_mdiobus_driver); ++} ++ ++subsys_initcall(cmicx_mdio_init); ++module_exit(cmicx_mdio_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc CMICx mdio driver"); ++MODULE_LICENSE("GPL"); ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/mdio-xgs-iproc.h b/drivers/net/phy/mdio-xgs-iproc.h +--- a/drivers/net/phy/mdio-xgs-iproc.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/mdio-xgs-iproc.h 2018-05-10 11:31:32.085402292 +0800 +@@ -0,0 +1,55 @@ ++/* ++ * $Copyright Open Broadcom Corporation$ ++ */ ++ ++ ++#ifndef _XGS_IPROC_MDIO_H_ ++#define _XGS_IPROC_MDIO_H_ ++ ++enum { ++ MII_OP_MODE_READ, ++ MII_OP_MODE_WRITE, ++ MII_OP_MODE_MAX ++}; ++ ++/* iProc General Interface for mdio bus support */ ++struct iproc_mdiobus_data { ++ /* required for cmicd mdio controller supports several buses */ ++ u32 phybus_num; ++ u32 phybus_type; ++}; ++ ++/* ++ * struct iproc_mdio_ctrl ++ * @base: base address of cmic_common ++ * @iproc_mdio_enable_reg: register addr of mdio bus enable ++ * @iproc_mdio_sel_bit: bit position in register for enabling mdio bus access ++ * @lock: spin lock protecting io access ++ */ ++struct iproc_mdio_ctrl { ++ void __iomem *base; ++ void __iomem *iproc_mdio_enable_reg; ++ u32 iproc_mdio_sel_bit; ++ spinlock_t lock; ++ int ref_cnt; ++}; ++ ++struct iproc_mdiobus_private { ++ struct iproc_mdiobus_data *bus_data; ++ struct iproc_mdio_ctrl *hw_ctrl; ++}; ++ ++#define SET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ ++ (reg_value) = ((reg_value) & ~((fmask) << (fshift))) | \ ++ (((fvalue) & (fmask)) << (fshift)) ++#define ISET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ ++ (reg_value) = (reg_value) | (((fvalue) & (fmask)) << (fshift)) ++#define GET_REG_FIELD(reg_value, fshift, fmask) \ ++ (((reg_value) & ((fmask) << (fshift))) >> (fshift)) ++ ++#define MII_OP_MAX_HALT_USEC 500 ++ ++#define IPROC_MDIOBUS_TYPE_INTERNAL 0 ++#define IPROC_MDIOBUS_TYPE_EXTERNAL 1 ++ ++#endif /* _XGS_IPROC_MDIO_H_ */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +--- a/drivers/net/phy/phy.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/net/phy/phy.c 2018-05-10 11:31:32.085402292 +0800 +@@ -42,6 +42,11 @@ + case PHY_##_state: \ + return __stringify(_state); \ + ++#if IS_ENABLED(CONFIG_MDIO_XGS_IPROC) ++#define MAX_IPROC_PHY_ADDR 4 ++extern bool xgs_mdio_bus_release(void); ++#endif ++ + static const char *phy_state_to_str(enum phy_state st) + { + switch (st) { +@@ -889,6 +894,9 @@ void phy_state_machine(struct work_struc + enum phy_state old_state; + int err = 0; + int old_link; ++#if IS_ENABLED(CONFIG_MDIO_XGS_IPROC) ++ static u32 schedule_cnt[MAX_IPROC_PHY_ADDR]= {0}; ++#endif + + mutex_lock(&phydev->lock); + +@@ -1078,9 +1086,32 @@ void phy_state_machine(struct work_struc + * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving + * between states from phy_mac_interrupt() + */ ++#if IS_ENABLED(CONFIG_MDIO_XGS_IPROC) ++ if (phydev->irq == PHY_POLL) { ++ /* Re-schedule PHY state machine change if mdio_bus_release=0 */ ++ if (!xgs_mdio_bus_release()) { ++ queue_delayed_work(system_power_efficient_wq, ++ &phydev->state_queue, PHY_STATE_TIME * HZ); ++ } ++ /* If mdio_bus_release=1, stop re-schedule of PHY state machine ++ * change after 5 * PHY_STATE_TIME seconds for HX4/KT2 ++ * which shares the mdio bus between iProc and CMICd. ++ */ ++ else { ++ schedule_cnt[phydev->mdio.addr] += 1; ++ if (schedule_cnt[phydev->mdio.addr] > 5) { ++ schedule_cnt[phydev->mdio.addr] = 0; ++ return; ++ } ++ queue_delayed_work(system_power_efficient_wq, ++ &phydev->state_queue, PHY_STATE_TIME * HZ); ++ } ++ } ++#else + if (phydev->irq == PHY_POLL) + queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, + PHY_STATE_TIME * HZ); ++#endif + } + + /** +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/xgs-iproc-serdes.c b/drivers/net/phy/xgs-iproc-serdes.c +--- a/drivers/net/phy/xgs-iproc-serdes.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/xgs-iproc-serdes.c 2018-05-10 11:31:32.089402296 +0800 +@@ -0,0 +1,644 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 "xgs_iproc_serdes_def.h" ++ ++/* the SERDES PHY ID for HX4/KT2/SB2/GH2/WH2 is the same */ ++#define PHY_ID_XGS_AMAC_SERDES 0x0143bff0 ++ ++#define SERDES_ID_HX4_AMAC 0x828f4e00 ++#define SERDES_ID_KT2_AMAC 0x42814fc0 ++/* The amac serdes id (id0,id1) of SB2/GH2/WH2 is the same */ ++#define SERDES_ID_SB2_AMAC 0x02cf1a00 ++#define SERDES_ID_GH2_AMAC 0x02cf1a00 /* apply to WH2 */ ++/* When ID is the same, use id2 for further identification */ ++#define SERDES_ID2_HX4_AMAC 0x000f ++#define SERDES_ID2_KT2_AMAC 0x03ff ++#define SERDES_ID2_SB2_AMAC 0x8007 ++#define SERDES_ID2_GH2_AMAC 0x800f /* apply to WH2 */ ++ ++#define PHY_REG_BLK_ADDR 0x001f ++#define PHY_REG_AER_BLK 0xffd0 ++#define PHY_REG_AER_OFFSET 0x001e ++#define PHY_REG_BLK_ADDR_MASK 0x7ff0 ++#define PHY_REG_ADDR_MASK 0xf ++#define PHY_REG_ADDR_32_MASK 0x8000 ++ ++#define PHY_AER_REG_ADDR_AER(_addr) (((_addr) >> XGXS16G_SERDES_LANE_SHIFT) \ ++ & 0xFFFF) ++#define PHY_REG_ADDR_BLK(_addr) ((_addr) & PHY_REG_BLK_ADDR_MASK) ++#define PHY_REG_ADDR_REGAD(_addr) (((_addr & PHY_REG_ADDR_32_MASK) >> 11) \ ++ | (_addr & PHY_REG_ADDR_MASK)) ++ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define SERDES_ERROR(args) pr_err args ++#define SERDES_TRACE(args) pr_info args ++#elif defined(BCMDBG_ERR) ++#define SERDES_ERROR(args) pr_err args ++#define SERDES_TRACE(args) ++#else ++#define SERDES_ERROR(args) ++#define SERDES_TRACE(args) ++#endif /* BCMDBG */ ++ ++/* For pcie/usb serdes and phy write */ ++void xgs_phy_wr_reg(struct phy_device *phydev, u32 regnum, u16 data) ++{ ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ ++ phy_reg_blk = regnum & PHY_REG_BLK_ADDR_MASK; ++ phy_reg_addr = regnum & PHY_REG_ADDR_MASK; ++ phy_reg_addr |= (regnum & PHY_REG_ADDR_32_MASK) ? 0x10 : 0x0; ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ phy_write(phydev, phy_reg_addr, data); ++} ++ ++/* For pcie/usb serdes and phy read */ ++u16 xgs_phy_rd_reg(struct phy_device *phydev, u32 regnum) ++{ ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ int data; ++ ++ phy_reg_blk = regnum & PHY_REG_BLK_ADDR_MASK; ++ phy_reg_addr = regnum & PHY_REG_ADDR_MASK; ++ phy_reg_addr |= (regnum & PHY_REG_ADDR_32_MASK) ? 0x10 : 0x0; ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ data = phy_read(phydev, phy_reg_addr); ++ ++ return (u16)data; ++} ++ ++/* for SB2 USB PHY write */ ++void xgs_sb2_usb_phy_wr_reg(struct phy_device *phydev, u32 regnum, u16 data) ++{ ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ ++ phy_reg_blk = regnum & 0xfff0; ++ phy_reg_addr = regnum & 0xf; ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ phy_write(phydev, phy_reg_addr, data); ++} ++ ++/* for SB2 USB PHY read */ ++u16 xgs_sb2_usb_phy_rd_reg(struct phy_device *phydev, u32 regnum) ++{ ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ int data; ++ ++ phy_reg_blk = regnum & 0xfff0; ++ phy_reg_addr = regnum & 0xf; ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ data = phy_read(phydev, phy_reg_addr); ++ ++ return (u16)data; ++} ++ ++/* SB2/GH2/WH2 amac serdes supports AER */ ++static u16 xgs_serdes_rd_reg(struct phy_device *phydev, u32 regnum) ++{ ++ int data; ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ u32 phy_reg_aer=0; ++ ++ phy_reg_aer = PHY_AER_REG_ADDR_AER(regnum); ++ phy_reg_blk = PHY_REG_ADDR_BLK(regnum); ++ phy_reg_addr = PHY_REG_ADDR_REGAD(regnum); ++ ++ if (phy_reg_aer) { ++ phy_write(phydev, PHY_REG_BLK_ADDR, PHY_REG_AER_BLK); ++ phy_write(phydev, PHY_REG_AER_OFFSET, phy_reg_aer); ++ } ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ data = phy_read(phydev, phy_reg_addr); ++ ++ if (phy_reg_aer) { ++ phy_write(phydev, PHY_REG_BLK_ADDR, PHY_REG_AER_BLK); ++ phy_write(phydev, PHY_REG_AER_OFFSET, 0x0); ++ } ++ ++ return (u16)data; ++} ++ ++static void xgs_serdes_wr_reg(struct phy_device *phydev, u32 regnum, u16 data) ++{ ++ u16 phy_reg_blk=0; ++ u32 phy_reg_addr=0; ++ u32 phy_reg_aer=0; ++ ++ phy_reg_aer = PHY_AER_REG_ADDR_AER(regnum); ++ phy_reg_blk = PHY_REG_ADDR_BLK(regnum); ++ phy_reg_addr = PHY_REG_ADDR_REGAD(regnum); ++ ++ if (phy_reg_aer) { ++ phy_write(phydev, PHY_REG_BLK_ADDR, PHY_REG_AER_BLK); ++ phy_write(phydev, PHY_REG_AER_OFFSET, phy_reg_aer); ++ } ++ ++ phy_write(phydev, PHY_REG_BLK_ADDR, phy_reg_blk); ++ phy_write(phydev, phy_reg_addr, data); ++ ++ if (phy_reg_aer) { ++ phy_write(phydev, PHY_REG_BLK_ADDR, PHY_REG_AER_BLK); ++ phy_write(phydev, PHY_REG_AER_OFFSET, 0x0); ++ } ++} ++ ++static u32 serdes_get_id(struct phy_device *phy_dev) ++{ ++ u16 serdes_id0, serdes_id1; ++ u32 serdes_id; ++ struct phy_device *phydev = phy_dev; ++ ++ serdes_id0 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID0r); ++ serdes_id1 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID1r); ++ serdes_id = (serdes_id0 << 16) | serdes_id1; ++ ++ return serdes_id; ++} ++ ++void xgs_serdes_set_lane(struct phy_device *phy_dev, u32 lane) ++{ ++ xgs_serdes_info_t *serdes_info; ++ ++ serdes_info = devm_kzalloc(&phy_dev->mdio.dev, sizeof(*serdes_info), ++ GFP_KERNEL); ++ if (!serdes_info) { ++ dev_err(&phy_dev->mdio.dev, "Fail to allocate xgs_serdes_info\n"); ++ return; ++ } ++ ++ serdes_info->lane = lane; ++ phy_dev->priv = serdes_info; ++} ++ ++static inline u32 xgs_serdes_get_lane(struct phy_device *phy_dev) ++{ ++ xgs_serdes_info_t *lane_info = (xgs_serdes_info_t *) phy_dev->priv; ++ ++ return lane_info->lane; ++} ++ ++bool xgs_serdes_hx4_amac(struct phy_device *phy_dev) ++{ ++ return (serdes_get_id(phy_dev) == SERDES_ID_HX4_AMAC); ++} ++ ++bool xgs_serdes_kt2_amac(struct phy_device *phy_dev) ++{ ++ return (serdes_get_id(phy_dev) == SERDES_ID_KT2_AMAC); ++} ++ ++/* Needed for HX4/KT2/GH2/WH2, WH2 has the same ID as GH2 */ ++static void xgs_serdes_reset_core(struct phy_device *phy_dev) ++{ ++ u16 data16; ++ u32 serdes_id; ++ u16 serdes_id2; ++ static u32 serdes_core_reset = 0; ++ struct phy_device *phydev = phy_dev; ++ ++ if (phydev->phy_id != PHY_ID_XGS_AMAC_SERDES) ++ return; ++ ++ /* Only reset once */ ++ if (serdes_core_reset) ++ return; ++ ++ serdes_id = serdes_get_id(phydev); ++ serdes_id2 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID2r); ++ SERDES_TRACE(("-----SERDESID2: 0x%x\n", serdes_id2)); ++ ++ if (!((serdes_id == SERDES_ID_HX4_AMAC) || ++ (serdes_id == SERDES_ID_KT2_AMAC) || ++ (serdes_id == SERDES_ID_GH2_AMAC))) ++ return; ++ ++ /* GH2/WH2 specific code */ ++ if (serdes_id == SERDES_ID_GH2_AMAC) { ++ if (serdes_id2 != SERDES_ID2_GH2_AMAC) ++ return; ++ ++ /* Disable pll start sequencer */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 &= ~XGXSBLK0_CONTROL_PLL_SEQUENCER_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ serdes_core_reset = 1; ++ return; ++ } ++ ++ /* The following is HX4/KT2 related */ ++ /* unlock lane */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_WC40_DIGITAL4_MISC3r); ++ data16 &= ~(DIGITAL4_MISC3_LANEDISABLE_MASK); ++ xgs_serdes_wr_reg(phydev, XGXS16G_WC40_DIGITAL4_MISC3r, data16); ++ ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* ++ * Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in IEEE address space. ++ */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_MISCCONTROL1r); ++ data16 &= ~(XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ if (!XGXS16G_2p5G_ID(serdes_id2) && (serdes_id == SERDES_ID_HX4_AMAC)) ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_MISCCONTROL1r, data16); ++ ++ /* disable in-band MDIO. PHY-443 */ ++ data16 = xgs_serdes_rd_reg(phydev, 0x8111); ++ /* rx_inBandMdio_rst */ ++ data16 |= 1 << 3; ++ xgs_serdes_wr_reg(phydev, 0x8111, data16); ++ ++ serdes_core_reset = 1; ++} ++ ++static void xgs_serdes_reset(struct phy_device *phy_dev) ++{ ++ u16 ctrl; ++ struct phy_device *phydev = phy_dev; ++ u32 serdes_id; ++ u16 serdes_id2; ++ u32 aer = 0; ++ u32 aer_blk_reg = 0; ++ ++ if (phydev->phy_id != PHY_ID_XGS_AMAC_SERDES) ++ return; ++ ++ serdes_id = serdes_get_id(phydev); ++ serdes_id2 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID2r); ++ ++ /* AER required for GH2/WH2 serdes */ ++ if ((serdes_id == SERDES_ID_GH2_AMAC) && ++ (serdes_id2 == SERDES_ID2_GH2_AMAC)) ++ aer = xgs_serdes_get_lane(phy_dev) << XGXS16G_SERDES_LANE_SHIFT; ++ ++ /* de-assert reset */ ++ aer_blk_reg = aer | XGXS16G_IEEE0BLK_IEEECONTROL0r; ++ ctrl = xgs_serdes_rd_reg(phydev, aer_blk_reg); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ xgs_serdes_wr_reg(phydev, aer_blk_reg, ctrl); ++ udelay(100); ++ ++ /* check if out of reset */ ++ if (xgs_serdes_rd_reg(phydev, aer_blk_reg) & ++ IEEE0BLK_IEEECONTROL0_RST_HW_MASK) ++ SERDES_ERROR(("amac serdes reset not completed.\n")); ++} ++ ++static void xgs_serdes_init(struct phy_device *phy_dev) ++{ ++ u16 data16; ++ u32 serdes_id; ++ u16 serdes_id2; ++ u32 __maybe_unused aer_blk_reg, aer; ++ struct phy_device *phydev = phy_dev; ++ ++#ifdef BCMDBG ++ u16 tmp0, tmp1; ++ tmp0 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID0r); ++ tmp1 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID1r); ++ SERDES_TRACE(("-----SERDESID0: 0x%x; SERDESID1: 0x%x\n", tmp0, tmp1)); ++ ++ tmp0 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID2r); ++ tmp1 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID3r); ++ SERDES_TRACE(("-----SERDESID2: 0x%x;SERDESID3: 0x%x\n", tmp0, tmp1)); ++#endif /* BCMDBG */ ++ ++ SERDES_TRACE(("%s: phyaddr %d\n",__FUNCTION__, phydev->mdio.addr)); ++ ++ if (phydev->phy_id != PHY_ID_XGS_AMAC_SERDES) ++ return; ++ ++ serdes_id = serdes_get_id(phydev); ++ serdes_id2 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID2r); ++ ++ if ((serdes_id == SERDES_ID_SB2_AMAC) && ++ (serdes_id2 == SERDES_ID2_SB2_AMAC)) { ++ /* Auto Negotiation 10M/100M/1G ¡V SGMII Slave */ ++ /* Disable pll start sequencer */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 &= ~XGXSBLK0_CONTROL_PLL_SEQUENCER_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* Set SGMII slave mode */ ++ xgs_serdes_wr_reg(phydev, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, ++ SERDESDIGITAL_CONTROL1000X1_SLAVE_MODE); ++ ++ /* Enable AN 10M/100M/1G */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_IEEE0BLK_IEEECONTROL0r); ++ data16 |= IEEE0BLK_IEEECONTROL0_ENABLE_AN_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_IEEE0BLK_IEEECONTROL0r, data16); ++ ++ /* Enable pll start sequencer */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 |= XGXSBLK0_CONTROL_PLL_SEQUENCER_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ } else if ((serdes_id == SERDES_ID_GH2_AMAC) && ++ (serdes_id2 == SERDES_ID2_GH2_AMAC)) { ++ aer = xgs_serdes_get_lane(phydev) << XGXS16G_SERDES_LANE_SHIFT; ++ ++ /* Disable IEEE block select auto-detect */ ++ data16 = 0; ++ aer_blk_reg = (aer | XGXS16G_XGXSBLK0_MISCCONTROL1r); ++ xgs_serdes_wr_reg(phydev, aer_blk_reg, data16); ++ ++ /* Disable lmtcal (broadcast to all lanes) */ ++ data16 = 0x83f8; ++ aer_blk_reg = (aer | XGXS16G_RX3_CONTROL2r); ++ xgs_serdes_wr_reg(phydev, aer_blk_reg, data16); ++ ++ /* Set SGMII slave mode */ ++ aer_blk_reg = (aer | XGXS16G_SERDESDIGITAL_CONTROL1000X1r); ++ xgs_serdes_wr_reg(phydev, aer_blk_reg, ++ SERDESDIGITAL_CONTROL1000X1_SLAVE_MODE); ++ ++ /* Enable AN 10M/100M/1G */ ++ aer_blk_reg = (aer | XGXS16G_IEEE0BLK_IEEECONTROL0r); ++ data16 = xgs_serdes_rd_reg(phydev, aer_blk_reg); ++ data16 |= IEEE0BLK_IEEECONTROL0_ENABLE_AN_MASK; ++ xgs_serdes_wr_reg(phydev, aer_blk_reg, data16); ++ } else if ((serdes_id == SERDES_ID_HX4_AMAC) || ++ (serdes_id == SERDES_ID_KT2_AMAC)) { ++ /* unlock lane */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_WC40_DIGITAL4_MISC3r); ++ data16 &= ~(DIGITAL4_MISC3_LANEDISABLE_MASK); ++ xgs_serdes_wr_reg(phydev, XGXS16G_WC40_DIGITAL4_MISC3r, data16); ++ ++ /* disable CL73 BAM */ ++ data16 = xgs_serdes_rd_reg(phydev, ++ XGXS16G_CL73_USERB0_CL73_BAMCTRL1r); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ xgs_serdes_wr_reg(phydev, XGXS16G_CL73_USERB0_CL73_BAMCTRL1r, ++ data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | ++ MII_ANA_C37_ASYM_PAUSE; ++ xgs_serdes_wr_reg(phydev, XGXS16G_COMBO_IEEE0_AUTONEGADVr, data16); ++ ++ /* Disable BAM in Independent Lane mode. Over 1G AN not supported */ ++ data16 = 0; ++ xgs_serdes_wr_reg(phydev, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, ++ data16); ++ xgs_serdes_wr_reg(phydev, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; ++ /* Set SGMII mode */ ++ xgs_serdes_wr_reg(phydev, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, ++ data16); ++ ++ /* Set autoneg */ ++ data16 = IEEE0BLK_IEEECONTROL0_ENABLE_AN_MASK | ++ IEEE0BLK_IEEECONTROL0_RESTART_AN_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ xgs_serdes_wr_reg(phydev, XGXS16G_AN73_PDET_PARDET10GCONTROLr, ++ data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ xgs_serdes_wr_reg(phydev, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, ++ data16); ++ ++ /* Enable lanes */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK1_LANECTRL0r); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK1_LANECTRL0r, data16); ++ ++ /* Set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ data16 = xgs_serdes_rd_reg(phydev, ++ XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ xgs_serdes_wr_reg(phydev, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, ++ data16); ++ ++ /* Enable LPI passthru' for native mode EEE */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_REMOTEPHY_MISC5r); ++ data16 |= XGXS16G_REMOTEPHY_MISC5_LPI_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_REMOTEPHY_MISC5r, data16); ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK7_EEECONTROLr); ++ data16 |= 0x0007; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK7_EEECONTROLr, data16); ++ } ++} ++ ++/* Needed for HX4/KT2/GH2/WH2 */ ++static void xgs_serdes_start_pll(struct phy_device *phy_dev) ++{ ++ u16 data16; ++ u32 serdes_id; ++ u16 serdes_id2; ++ u32 count = 100; ++ struct phy_device *phydev = phy_dev; ++ static u32 serdes_pll_started = 0; ++ ++ if (phydev->phy_id != PHY_ID_XGS_AMAC_SERDES) ++ return; ++ ++ /* PLL started or not */ ++ if (serdes_pll_started) ++ return; ++ ++ serdes_id = serdes_get_id(phydev); ++ serdes_id2 = xgs_serdes_rd_reg(phydev, XGXS16G_SERDESID_SERDESID2r); ++ ++ if (!((serdes_id == SERDES_ID_HX4_AMAC) || ++ (serdes_id == SERDES_ID_KT2_AMAC) || ++ (serdes_id == SERDES_ID_GH2_AMAC))) ++ return; ++ ++ /* Change PLL calibration threshold to 0xc for GH2/WH2*/ ++ if ((serdes_id == SERDES_ID_GH2_AMAC) && ++ (serdes_id2 == SERDES_ID2_GH2_AMAC)) { ++ data16 = 0xc << XGXS16G_PLL2_CTRL_CAL_TH_SHIFT; ++ xgs_serdes_wr_reg(phydev, XGXS16G_PLL2_CTRL1r, data16); ++ } ++ ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ xgs_serdes_wr_reg(phydev, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* wait for PLL to lock */ ++ while (count--) { ++ data16 = xgs_serdes_rd_reg(phydev, XGXS16G_XGXSBLK0_XGXSSTATUSr); ++ if (data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) ++ break; ++ udelay(10); ++ } ++ if (!count) ++ SERDES_ERROR(("amac serdes TXPLL did not lock\n")); ++ else ++ serdes_pll_started = 1; ++} ++ ++static int xgs_serdes_config_init(struct phy_device *phydev) ++{ ++ xgs_serdes_reset_core(phydev); ++ xgs_serdes_reset(phydev); ++ xgs_serdes_init(phydev); ++ xgs_serdes_start_pll(phydev); ++ ++ return 0; ++} ++ ++/* ++ * REGADDR: 0x8304 ++ * DESC: 1000X status 1 register ++ * SGMII_MODE 1 = sgmii mode0 = fiber mode (1000-X) ++ * LINK_STATUS 1 = link is up0 = link is down ++ * DUPLEX_STATUS 1 = full-duplex0 = half-duplex ++ * SPEED_STATUS 11 = 2.5G10 = gigabit01 = 100 mbps00 = 10 mbps ++ */ ++static int xgs_serdes_read_status(struct phy_device *phydev) ++{ ++ u16 link_stat; ++ u32 serdes_lane; ++ u32 reg; ++ ++ serdes_lane = xgs_serdes_get_lane(phydev); ++ reg = (serdes_lane << XGXS16G_SERDES_LANE_SHIFT) | ++ XGXS16G_SERDESDIGITAL_STATUS1000X1r; ++ link_stat = xgs_serdes_rd_reg(phydev, reg); ++ ++ if (link_stat & 0x2) ++ phydev->link = 1; ++ else ++ phydev->link = 0; ++ ++ if (link_stat & 0x4) ++ phydev->duplex = 1; ++ else ++ phydev->duplex = 0; ++ ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++/* ++ link_stat >>= 3; ++ link_stat &= 0x3; ++*/ ++ link_stat >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; ++ link_stat &= ((1 << SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS) - 1); ++ switch(link_stat) { ++ case 0: ++ phydev->speed = SPEED_10; ++ break; ++ case 1: ++ phydev->speed = SPEED_100; ++ break; ++ case 2: ++ phydev->speed = SPEED_1000; ++ break; ++ case 3: ++ phydev->speed = SPEED_2500; ++ break; ++ }; ++ ++ return 0; ++} ++ ++static int xgs_serdes_config_aneg(struct phy_device *phydev) ++{ ++ u32 serdes_lane; ++ u32 reg; ++ u16 data16; ++ ++ if (AUTONEG_ENABLE != phydev->autoneg) ++ return 0; ++ ++ serdes_lane = xgs_serdes_get_lane(phydev); ++ ++ /* Enable AN 10M/100M/1G */ ++ reg = (serdes_lane << XGXS16G_SERDES_LANE_SHIFT) | ++ XGXS16G_IEEE0BLK_IEEECONTROL0r; ++ data16 = xgs_serdes_rd_reg(phydev, reg); ++ //data16 |= IEEE0BLK_IEEECONTROL0_ENABLE_AN_MASK; ++ data16 |= IEEE0BLK_IEEECONTROL0_RESTART_AN_MASK; ++ xgs_serdes_wr_reg(phydev, reg, data16); ++ ++ return 0; ++} ++ ++static int xgs_serdes_aneg_done(struct phy_device *phydev) ++{ ++ u16 link_stat; ++ u32 serdes_lane; ++ u32 reg; ++ ++ serdes_lane = xgs_serdes_get_lane(phydev); ++ reg = (serdes_lane << XGXS16G_SERDES_LANE_SHIFT) | ++ XGXS16G_SERDESDIGITAL_STATUS1000X2r; ++ link_stat = xgs_serdes_rd_reg(phydev, reg); ++ if (link_stat & XGXS16G_SERDES_ANEG_MASK) ++ return 1; ++ ++ return 0; ++} ++ ++static struct mdio_device_id __maybe_unused xgs_serdes_tbl[] = { ++ { PHY_ID_XGS_AMAC_SERDES, 0xfffffff0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(mdio, xgs_serdes_tbl); ++ ++static struct phy_driver xgs_serdes_drivers[] = { ++ { ++ .phy_id = PHY_ID_XGS_AMAC_SERDES, ++ .phy_id_mask = 0xfffffff0, ++ .name = "Broadcom XGS AMAC SERDES", ++ .config_init = xgs_serdes_config_init, ++ .read_status = xgs_serdes_read_status, ++ .config_aneg = xgs_serdes_config_aneg, ++ .aneg_done = xgs_serdes_aneg_done, ++ } ++}; ++ ++module_phy_driver(xgs_serdes_drivers); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("XGS iProc AMAC serdes driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/net/phy/xgs_iproc_serdes_def.h b/drivers/net/phy/xgs_iproc_serdes_def.h +--- a/drivers/net/phy/xgs_iproc_serdes_def.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/net/phy/xgs_iproc_serdes_def.h 2018-05-10 11:31:32.089402296 +0800 +@@ -0,0 +1,339 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. ++ * ++ * These are serdes defines ++ * ++ */ ++ ++#ifndef _PHY_XGXS16G_H_ ++#define _PHY_XGXS16G_H_ ++ ++/* macros */ ++ ++/* Macros ONLY used after initialization */ ++#define XGXS16G_2p5G_ID(id2) ((id2 & 0xff) == 0xf) ++ ++/****************************************************************************/ ++/***** Starting below is auto-generated register macros from RDB files *****/ ++/****************************************************************************/ ++ ++/**************************************************************************** ++ * Core Enums. ++ ***************************************************************************/ ++ ++#define XGXS16G_IEEE0BLK_IEEECONTROL0r 0x00000000 ++#define XGXS16G_XGXSBLK0_XGXSCONTROLr 0x00008000 ++#define XGXS16G_XGXSBLK0_XGXSSTATUSr 0x00008001 ++#define XGXS16G_XGXSBLK0_MMDSELECTr 0x0000800d ++#define XGXS16G_XGXSBLK0_MISCCONTROL1r 0x0000800e ++#define XGXS16G_XGXSBLK1_LANECTRL0r 0x00008015 ++#define XGXS16G_XGXSBLK1_LANECTRL1r 0x00008016 ++#define XGXS16G_XGXSBLK1_LANECTRL3r 0x00008018 ++#define XGXS16G_TX0_TX_ACONTROL0r 0x00008061 ++#define XGXS16G_RX0_RX_CONTROLr 0x000080b1 ++#define XGXS16G_AN73_PDET_PARDET10GCONTROLr 0x00008131 ++#define XGXS16G_XGXSBLK7_EEECONTROLr 0x00008150 ++#define XGXS16G_TX_LN_SWAP1r 0x00008169 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X1r 0x00008300 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X2r 0x00008301 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X3r 0x00008302 ++#define XGXS16G_SERDESDIGITAL_STATUS1000X1r 0x00008304 ++#define XGXS16G_SERDESDIGITAL_MISC1r 0x00008308 ++#define XGXS16G_SERDESID_SERDESID0r 0x00008310 ++#define XGXS16G_SERDESID_SERDESID1r 0x00008311 ++#define XGXS16G_SERDESID_SERDESID2r 0x00008312 ++#define XGXS16G_SERDESID_SERDESID3r 0x00008313 ++#define XGXS16G_REMOTEPHY_MISC3r 0x0000833c ++#define XGXS16G_REMOTEPHY_MISC5r 0x0000833e ++#define XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr 0x00008350 ++#define XGXS16G_BAM_NEXTPAGE_UD_FIELDr 0x00008357 ++#define XGXS16G_COMBO_IEEE0_MIICNTLr 0x0000ffe0 ++#define XGXS16G_COMBO_IEEE0_AUTONEGADVr 0x0000ffe4 ++#define XGXS16G_WC40_DIGITAL4_MISC3r 0x0000833c ++ ++/* Digital4 :: Misc3 :: laneDisable [06:06] */ ++#define DIGITAL4_MISC3_LANEDISABLE_MASK 0x0040 ++#define DIGITAL4_MISC3_LANEDISABLE_ALIGN 0 ++#define DIGITAL4_MISC3_LANEDISABLE_BITS 1 ++#define DIGITAL4_MISC3_LANEDISABLE_SHIFT 6 ++ ++ ++/**************************************************************************** ++ * XGXS16G_IEEE_ieee0Blk ++ ***************************************************************************/ ++/**************************************************************************** ++ * ieee0Blk :: ieeeControl0 ++ ***************************************************************************/ ++/* ieee0Blk :: ieeeControl0 :: rst_hw [15:15] */ ++#define IEEE0BLK_IEEECONTROL0_RST_HW_MASK 0x8000 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_SHIFT 15 ++ ++/* ieee0Blk :: ieeeControl0 :: gloopback [14:14] */ ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK 0x4000 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_SHIFT 14 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsControl ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsControl :: start_sequencer [13:13] */ ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK 0x2000 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_SHIFT 13 ++ ++/* XgxsBlk0 :: xgxsControl :: mode_10g [11:08] */ ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_MASK 0x0f00 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_BITS 4 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noCC 1 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane 6 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss_noCC 9 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass 10 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass_noDsk 11 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode 12 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ClocksOff 15 ++ ++/* XgxsBlk0 :: xgxsControl :: hstl [05:05] */ ++#define XGXSBLK0_XGXSCONTROL_HSTL_MASK 0x0020 ++#define XGXSBLK0_XGXSCONTROL_HSTL_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_HSTL_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_HSTL_SHIFT 5 ++ ++/* XgxsBlk0 :: xgxsControl :: cdet_en [03:03] */ ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_MASK 0x0008 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_SHIFT 3 ++ ++/* XgxsBlk0 :: xgxsControl :: eden [02:02] */ ++#define XGXSBLK0_XGXSCONTROL_EDEN_MASK 0x0004 ++#define XGXSBLK0_XGXSCONTROL_EDEN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_EDEN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_EDEN_SHIFT 2 ++ ++/* XgxsBlk0 :: xgxsControl :: afrst_en [01:01] */ ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK 0x0002 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_SHIFT 1 ++ ++/* XgxsBlk0 :: xgxsControl :: txcko_div [00:00] */ ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK 0x0001 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsStatus ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsStatus :: txpll_lock [11:11] */ ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK 0x0800 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_ALIGN 0 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_BITS 1 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_SHIFT 11 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: miscControl1 ++ ***************************************************************************/ ++/* XgxsBlk0 :: miscControl1 :: PCS_dev_en_override [10:10] */ ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK 0x0400 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_SHIFT 10 ++ ++/* XgxsBlk0 :: miscControl1 :: PMD_dev_en_override [09:09] */ ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK 0x0200 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_SHIFT 9 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_autodet [01:01] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK 0x0002 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_SHIFT 1 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_val [00:00] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK 0x0001 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk1 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk1 :: laneCtrl0 ++ ***************************************************************************/ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_rx [07:04] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK 0x00f0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_SHIFT 4 ++ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_tx [03:00] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK 0x000f ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_TX0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * TX0 :: Tx_AControl0 ++ ***************************************************************************/ ++/* TX0 :: Tx_AControl0 :: txpol_flip [05:05] */ ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_MASK 0x0020 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_ALIGN 0 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_BITS 1 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_SHIFT 5 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_dsc_2_0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * dsc_2_0 :: dsc_ctrl0 ++ ***************************************************************************/ ++/* dsc_2_0 :: dsc_ctrl0 :: rxSeqStart [15:15] */ ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK 0x8000 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_ALIGN 0 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_BITS 1 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_SerdesDigital ++ ***************************************************************************/ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X1 :: crc_checker_disable [07:07] */ ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK 0x0080 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_SHIFT 7 ++ ++/* SerdesDigital :: Control1000X1 :: disable_pll_pwrdwn [06:06] */ ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK 0x0040 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_SHIFT 6 ++ ++/* SerdesDigital :: Control1000X1 :: fiber_mode_1000X [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X3 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X3 :: fifo_elasicity_tx_rx [02:01] */ ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK 0x0006 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_BITS 2 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_SHIFT 1 ++ ++/* SerdesDigital :: Control1000X3 :: tx_fifo_rst [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Status1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Status1000X1 :: speed_status [04:03] */ ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK 0x0018 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_ALIGN 0 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS 2 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT 3 ++ ++/**************************************************************************** ++ * SerdesDigital :: Misc1 ++ ***************************************************************************/ ++/* SerdesDigital :: Misc1 :: refclk_sel [15:13] */ ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_MASK 0xe000 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_ALIGN 0 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_BITS 3 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_SHIFT 13 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_25MHz 0 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_100MHz 1 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_125MHz 2 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_156p25MHz 3 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_187p5MHz 4 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_161p25Mhz 5 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_50Mhz 6 ++#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_106p25Mhz 7 ++ ++/* SerdesDigital :: Misc1 :: force_speed_sel [04:04] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK 0x0010 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_BITS 1 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_SHIFT 4 ++ ++/* SerdesDigital :: Misc1 :: force_speed [03:00] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_MASK 0x000f ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_BITS 4 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * CL73_UserB0 :: CL73_BAMCtrl1 ++ ***************************************************************************/ ++/* CL73_UserB0 :: CL73_BAMCtrl1 :: CL73_bamEn [15:15] */ ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK 0x8000 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_ALIGN 0 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_BITS 1 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_SHIFT 15 ++ ++/* Definitions required in addition to the above auto-generated */ ++#define XGXS16G_REMOTEPHY_MISC5_LPI_MASK 0xc000 ++#define IEEE0BLK_IEEECONTROL0_ENABLE_AN_MASK BIT(12) ++#define IEEE0BLK_IEEECONTROL0_RESTART_AN_MASK BIT(9) ++#define XGXSBLK0_CONTROL_PLL_SEQUENCER_MASK BIT(13) ++#define SERDESDIGITAL_CONTROL1000X1_SLAVE_MODE BIT(8) ++#define XGXS16G_PLL2_CTRL1r 0x00008081 ++#define XGXS16G_SERDESDIGITAL_STATUS1000X2r 0x00008305 ++#define XGXS16G_CL73_USERB0_CL73_BAMCTRL1r 0x00008372 ++#define XGXS16G_RX3_CONTROL2r 0x00008482 ++#define XGXS16G_PLL2_CTRL_CAL_TH_SHIFT 7 ++#define XGXS16G_SERDES_LANE_SHIFT 16 ++#define XGXS16G_SERDES_ANEG_MASK BIT(4) ++#define MII_ANA_C37_PAUSE BIT(7) ++#define MII_ANA_C37_ASYM_PAUSE BIT(8) ++#define MII_ANA_C37_FD BIT(5) ++ ++#endif /* _PHY_XGXS16G_H_ */ ++ ++/* End of File */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig +--- a/drivers/pci/host/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/pci/host/Kconfig 2018-05-10 11:31:32.457402700 +0800 +@@ -99,6 +99,15 @@ config PCI_VERSATILE + bool "ARM Versatile PB PCI controller" + depends on ARCH_VERSATILE + ++config PCIE_XGS_IPROC ++ bool "Broadcom XGS iProc PCIe controller" ++ select PCI_DOMAINS ++ depends on ARCH_XGS_IPROC ++ default n ++ help ++ This enables the XGS iProc PCIe core controller support for Broadcom's ++ iProc family of SoCs. ++ + config PCIE_IPROC + tristate + select PCI_DOMAINS +@@ -129,7 +138,7 @@ config PCIE_IPROC_BCMA + + config PCIE_IPROC_MSI + bool "Broadcom iProc PCIe MSI support" +- depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA ++ depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA || PCIE_XGS_IPROC + depends on PCI_MSI_IRQ_DOMAIN + default ARCH_BCM_IPROC + help +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile +--- a/drivers/pci/host/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/pci/host/Makefile 2018-05-10 11:31:32.457402700 +0800 +@@ -16,6 +16,7 @@ obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o + obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o + obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o + obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o ++obj-$(CONFIG_PCIE_XGS_IPROC) += pcie-xgs-iproc.o + obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o + obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o + obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h +--- a/drivers/pci/host/pcie-iproc.h 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/pci/host/pcie-iproc.h 2018-05-10 11:31:32.461402704 +0800 +@@ -93,6 +93,9 @@ struct iproc_pcie { + struct resource mem; + struct pci_bus *root_bus; + struct phy *phy; ++#ifdef CONFIG_PCIE_XGS_IPROC ++ struct phy_device *mdio_phy; ++#endif + int (*map_irq)(const struct pci_dev *, u8, u8); + bool ep_is_internal; + bool has_apb_err_disable; +@@ -108,9 +111,11 @@ struct iproc_pcie { + struct iproc_msi *msi; + }; + ++#ifndef CONFIG_PCIE_XGS_IPROC + int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); + int iproc_pcie_remove(struct iproc_pcie *pcie); + int iproc_pcie_shutdown(struct iproc_pcie *pcie); ++#endif + + #ifdef CONFIG_PCIE_IPROC_MSI + int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/pci/host/pcie-xgs-iproc.c b/drivers/pci/host/pcie-xgs-iproc.c +--- a/drivers/pci/host/pcie-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/pci/host/pcie-xgs-iproc.c 2018-05-10 11:31:32.461402704 +0800 +@@ -0,0 +1,541 @@ ++/* ++ * Copyright (C) 2014 Hauke Mehrtens ++ * Copyright (C) 2015 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pcie-iproc.h" ++ ++#define CLK_CONTROL_OFFSET 0x000 ++ ++#define CFG_IND_ADDR_OFFSET 0x120 ++#define CFG_IND_ADDR_MASK 0x00001ffc ++#define CFG_IND_DATA_OFFSET 0x124 ++ ++#define CFG_ADDR_OFFSET 0x1f8 ++#define CFG_ADDR_BUS_NUM_SHIFT 20 ++#define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 ++#define CFG_ADDR_DEV_NUM_SHIFT 15 ++#define CFG_ADDR_DEV_NUM_MASK 0x000f8000 ++#define CFG_ADDR_FUNC_NUM_SHIFT 12 ++#define CFG_ADDR_FUNC_NUM_MASK 0x00007000 ++#define CFG_ADDR_REG_NUM_SHIFT 2 ++#define CFG_ADDR_REG_NUM_MASK 0x00000ffc ++#define CFG_ADDR_CFG_TYPE_SHIFT 0 ++#define CFG_ADDR_CFG_TYPE_MASK 0x00000003 ++ ++#define CFG_DATA_OFFSET 0x1fc ++ ++#define SYS_RC_INTX_EN 0x330 ++#define SYS_RC_INTX_MASK 0xf ++ ++#define IPROC_PCI_EXP_CAP 0xac ++ ++struct pcie_sw_wa { ++ const char *wa_name; ++ void (*wa_func)(struct iproc_pcie *pcie); ++}; ++ ++extern void xgs_phy_wr_reg(struct phy_device *phydev, u32 regnum, u16 data); ++ ++static inline struct iproc_pcie *iproc_pcie_data(struct pci_bus *bus) ++{ ++ struct iproc_pcie *pcie; ++#ifdef CONFIG_ARM ++ struct pci_sys_data *sys = bus->sysdata; ++ ++ pcie = sys->private_data; ++#else ++ pcie = bus->sysdata; ++#endif ++ return pcie; ++} ++ ++/** ++ * Note access to the configuration registers are protected at the higher layer ++ * by 'pci_lock' in drivers/pci/access.c ++ */ ++static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie, ++ int busno, unsigned int devfn, ++ int where) ++{ ++ u32 slot = PCI_SLOT(devfn); ++ u32 fn = PCI_FUNC(devfn); ++ u32 val; ++ ++ /* root complex access */ ++ if (busno == 0) { ++ if (slot >= 1) ++ return NULL; ++ writel(where & CFG_IND_ADDR_MASK, ++ pcie->base + CFG_IND_ADDR_OFFSET); ++ return (pcie->base + CFG_IND_DATA_OFFSET); ++ } ++ ++ if (fn > 1) ++ return NULL; ++ ++ /* EP device access */ ++ val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | ++ (slot << CFG_ADDR_DEV_NUM_SHIFT) | ++ (fn << CFG_ADDR_FUNC_NUM_SHIFT) | ++ (where & CFG_ADDR_REG_NUM_MASK) | ++ (1 & CFG_ADDR_CFG_TYPE_MASK); ++ writel(val, pcie->base + CFG_ADDR_OFFSET); ++ ++ return (pcie->base + CFG_DATA_OFFSET); ++} ++ ++static void __iomem *iproc_pcie_bus_map_cfg_bus(struct pci_bus *bus, ++ unsigned int devfn, ++ int where) ++{ ++ return iproc_pcie_map_cfg_bus(iproc_pcie_data(bus), bus->number, devfn, ++ where); ++} ++ ++static int iproc_pci_raw_config_read32(struct iproc_pcie *pcie, ++ unsigned int devfn, int where, ++ int size, u32 *val) ++{ ++ void __iomem *addr; ++ ++ addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3); ++ if (!addr) { ++ *val = ~0; ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ } ++ ++ *val = readl(addr); ++ ++ if (size <= 2) ++ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int iproc_pci_raw_config_write32(struct iproc_pcie *pcie, ++ unsigned int devfn, int where, ++ int size, u32 val) ++{ ++ void __iomem *addr; ++ u32 mask, tmp; ++ ++ addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3); ++ if (!addr) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ if (size == 4) { ++ writel(val, addr); ++ return PCIBIOS_SUCCESSFUL; ++ } ++ ++ mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); ++ tmp = readl(addr) & mask; ++ tmp |= val << ((where & 0x3) * 8); ++ writel(tmp, addr); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static struct pci_ops iproc_pcie_ops = { ++ .map_bus = iproc_pcie_bus_map_cfg_bus, ++ .read = pci_generic_config_read32, ++ .write = pci_generic_config_write32, ++}; ++ ++static inline void pcie_wrong_gen2_wa(struct iproc_pcie * pcie) ++{ ++ xgs_phy_wr_reg(pcie->mdio_phy, 0x8633, 0x190); ++ xgs_phy_wr_reg(pcie->mdio_phy, 0x8639, 0x191); ++} ++ ++static void iproc_pcie_reset(struct iproc_pcie *pcie) ++{ ++ /* configured as RC and send a downstream reset */ ++ writel(0, pcie->base + CLK_CONTROL_OFFSET); ++ mdelay(1); ++ writel(1, pcie->base + CLK_CONTROL_OFFSET); ++ msleep(100); ++} ++ ++static void pcie_rc_wa(struct iproc_pcie * pcie) ++{ ++ /* Setting for PCIe Serdes PLL output */ ++ xgs_phy_wr_reg(pcie->mdio_phy, 0x2103, 0x2b1c); ++ xgs_phy_wr_reg(pcie->mdio_phy, 0x1300, 0x000b); ++ msleep(100); ++} ++ ++/* currently for Greyhound */ ++static void pcie_tx_de_emp_wa(struct iproc_pcie * pcie) ++{ ++ u32 tmp32; ++ ++ iproc_pci_raw_config_read32(pcie, 0, 0xdc, 4, &tmp32); ++ tmp32 |= (0x1 << 6); ++ iproc_pci_raw_config_write32(pcie, 0, 0xdc, 4, tmp32); ++ iproc_pci_raw_config_read32(pcie, 0, 0xdc, 4, &tmp32); ++} ++ ++static const struct pcie_sw_wa pcie_wa_tab[] = { ++ { ++ .wa_name = "pcie_wrong_gen2", ++ .wa_func = pcie_wrong_gen2_wa, ++ }, ++ { ++ .wa_name = "pcie_rc", ++ .wa_func = pcie_rc_wa, ++ }, ++ { ++ .wa_name = "pcie_perst", ++ .wa_func = iproc_pcie_reset, ++ }, ++ { ++ .wa_name = "pcie_tx_de_emp", ++ .wa_func = pcie_tx_de_emp_wa, ++ }, ++}; ++ ++/* ++ * Run the specific pcie workaround function specified in "pcie_wa_tab", ++ * if "wa_name" is found on the "wa-list" property of pcie node. ++ */ ++static void pcie_sw_wa_func(const char *wa_name, struct iproc_pcie *pcie) ++{ ++ struct device_node *np = pcie->dev->of_node; ++ int wa_num_max = ARRAY_SIZE(pcie_wa_tab); ++ int wa_num = of_property_count_strings(np, "wa-list"); ++ const char *wa_name_dts; ++ int i; ++ ++ /* workaround required? */ ++ if (wa_num <= 0) ++ return; ++ ++ for (i = 0; i < wa_num; i++) { ++ of_property_read_string_index(np, "wa-list", i, &wa_name_dts); ++ if (!strcmp(wa_name, wa_name_dts)) ++ break; ++ } ++ ++ /* The wa_name is found on wa-list of pcie node? */ ++ if (i == wa_num) ++ return; ++ ++ for (i = 0; i < wa_num_max; i++) ++ if (!strcmp(pcie_wa_tab[i].wa_name, wa_name)) { ++ pcie_wa_tab[i].wa_func(pcie); ++ break; ++ } ++} ++ ++static int iproc_pcie_check_link(struct iproc_pcie *pcie) ++{ ++ struct device *dev = pcie->dev; ++ u32 hdr_type, link_ctrl, link_status, class; ++ bool link_is_active = false; ++ ++ /* make sure we are not in EP mode */ ++ iproc_pci_raw_config_read32(pcie, 0, PCI_HEADER_TYPE, 1, &hdr_type); ++ if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { ++ dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type); ++ return -EFAULT; ++ } ++ ++ /* SB2/GH/HR3/GH2 */ ++ pcie_sw_wa_func("pcie_rc", pcie); ++ ++ /* GH/HR3/GH2 */ ++ pcie_sw_wa_func("pcie_perst", pcie); ++ ++ /* Not enabled in DT file currently */ ++ pcie_sw_wa_func("pcie_tx_de_emp", pcie); ++ ++ /* Force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ ++#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c ++#define PCI_CLASS_BRIDGE_MASK 0xffff00 ++#define PCI_CLASS_BRIDGE_SHIFT 8 ++ iproc_pci_raw_config_read32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET, ++ 4, &class); ++ class &= ~PCI_CLASS_BRIDGE_MASK; ++ class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); ++ iproc_pci_raw_config_write32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET, ++ 4, class); ++ ++ /* check link status to see if link is active */ ++ iproc_pci_raw_config_read32(pcie, 0, IPROC_PCI_EXP_CAP + PCI_EXP_LNKSTA, ++ 2, &link_status); ++ if (link_status & PCI_EXP_LNKSTA_NLW) ++ link_is_active = true; ++ ++ if (!link_is_active) { ++ /* try GEN 1 link speed */ ++#define PCI_TARGET_LINK_SPEED_MASK 0xf ++#define PCI_TARGET_LINK_SPEED_GEN2 0x2 ++#define PCI_TARGET_LINK_SPEED_GEN1 0x1 ++ iproc_pci_raw_config_read32(pcie, 0, ++ IPROC_PCI_EXP_CAP + PCI_EXP_LNKCTL2, ++ 4, &link_ctrl); ++ if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == ++ PCI_TARGET_LINK_SPEED_GEN2) { ++ link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; ++ link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; ++ iproc_pci_raw_config_write32(pcie, 0, ++ IPROC_PCI_EXP_CAP + PCI_EXP_LNKCTL2, ++ 4, link_ctrl); ++ msleep(100); ++ ++ iproc_pci_raw_config_read32(pcie, 0, ++ IPROC_PCI_EXP_CAP + PCI_EXP_LNKSTA, ++ 2, &link_status); ++ if (link_status & PCI_EXP_LNKSTA_NLW) ++ link_is_active = true; ++ } ++ } ++ ++ dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); ++ ++ return link_is_active ? 0 : -ENODEV; ++} ++ ++static void iproc_pcie_enable(struct iproc_pcie *pcie) ++{ ++ writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); ++} ++ ++static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) ++{ ++ struct device_node *msi_node; ++ ++ msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); ++ if (!msi_node) ++ return -ENODEV; ++ ++ /* ++ * If another MSI controller is being used, the call below should fail ++ * but that is okay ++ */ ++ return iproc_msi_init(pcie, msi_node); ++} ++ ++static void iproc_pcie_msi_disable(struct iproc_pcie *pcie) ++{ ++ iproc_msi_exit(pcie); ++} ++ ++static int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) ++{ ++ struct device *dev; ++ int ret; ++ void *sysdata; ++ struct pci_bus *child; ++ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); ++ ++ if (!pcie || !pcie->dev || !pcie->base) ++ return -EINVAL; ++ ++ dev = pcie->dev; ++ ++ ret = devm_request_pci_bus_resources(dev, res); ++ if (ret) ++ return ret; ++ ++ ret = phy_init(pcie->phy); ++ if (ret) { ++ dev_err(pcie->dev, "unable to initialize PCIe PHY\n"); ++ return ret; ++ } ++ ++ ret = phy_power_on(pcie->phy); ++ if (ret) { ++ dev_err(pcie->dev, "unable to power on PCIe PHY\n"); ++ goto err_exit_phy; ++ } ++ ++ iproc_pcie_reset(pcie); ++ ++#ifdef CONFIG_ARM ++ pcie->sysdata.private_data = pcie; ++ sysdata = &pcie->sysdata; ++#else ++ sysdata = pcie; ++#endif ++ ++ ret = iproc_pcie_check_link(pcie); ++ if (ret) { ++ dev_err(pcie->dev, "no PCIe EP device detected\n"); ++ goto err_power_off_phy; ++ } ++ ++ iproc_pcie_enable(pcie); ++ ++ if (IS_ENABLED(CONFIG_PCI_MSI)) ++ if (iproc_pcie_msi_enable(pcie)) ++ dev_info(pcie->dev, "not using iProc MSI\n"); ++ ++ list_splice_init(res, &host->windows); ++ host->busnr = 0; ++ host->dev.parent = dev; ++ host->ops = &iproc_pcie_ops; ++ host->sysdata = sysdata; ++ host->map_irq = pcie->map_irq; ++ host->swizzle_irq = pci_common_swizzle; ++ ++ ret = pci_scan_root_bus_bridge(host); ++ if (ret < 0) { ++ dev_err(dev, "failed to scan host: %d\n", ret); ++ goto err_power_off_phy; ++ } ++ ++ pci_assign_unassigned_bus_resources(host->bus); ++ ++ pcie->root_bus = host->bus; ++ ++ list_for_each_entry(child, &host->bus->children, node) ++ pcie_bus_configure_settings(child); ++ ++ pci_bus_add_devices(host->bus); ++ ++ return 0; ++ ++err_power_off_phy: ++ phy_power_off(pcie->phy); ++err_exit_phy: ++ phy_exit(pcie->phy); ++ ++ return ret; ++} ++ ++static int iproc_pcie_probe(struct platform_device *pdev) ++{ ++ struct iproc_pcie *pcie; ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *mdio_phy_np = NULL; ++ struct resource reg; ++ struct pci_host_bridge *bridge; ++ resource_size_t iobase = 0; ++ LIST_HEAD(res); ++ int ret; ++ ++ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie)); ++ if (!bridge) ++ return -ENOMEM; ++ ++ pcie = pci_host_bridge_priv(bridge); ++ ++ pcie->dev = &pdev->dev; ++ platform_set_drvdata(pdev, pcie); ++ ++ pcie->type = (enum iproc_pcie_type)np->data; ++ ++ ret = of_address_to_resource(np, 0, ®); ++ if (ret < 0) { ++ dev_err(pcie->dev, "unable to obtain controller resources\n"); ++ return ret; ++ } ++ ++ pcie->base = devm_ioremap_resource(pcie->dev, ®); ++ if (IS_ERR(pcie->base)) ++ return PTR_ERR(pcie->base); ++ ++ /* MSI message base addr*/ ++ pcie->base_addr = reg.start; ++ ++ /* PHY use is optional */ ++ pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy"); ++ if (IS_ERR(pcie->phy)) { ++ if (PTR_ERR(pcie->phy) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ pcie->phy = NULL; ++ } ++ ++ /* PHY controlled through MDIO for HX4/KT2 */ ++ mdio_phy_np = of_parse_phandle(np, "mdio-phy-handle", 0); ++ if (mdio_phy_np) ++ pcie->mdio_phy = of_phy_find_device(mdio_phy_np); ++ ++ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &iobase); ++ if (ret) { ++ dev_err(pcie->dev, ++ "unable to get PCI host bridge resources\n"); ++ return ret; ++ } ++ ++ /* HX4/KT2/HR2 */ ++ pcie_sw_wa_func("pcie_wrong_gen2", pcie); ++ ++ pcie->map_irq = of_irq_parse_and_map_pci; ++ ++ ret = iproc_pcie_setup(pcie, &res); ++ if (ret) ++ dev_err(pcie->dev, "PCIe controller setup failed\n"); ++ ++ pci_free_resource_list(&res); ++ ++ return ret; ++} ++ ++static int iproc_pcie_remove(struct platform_device *pdev) ++{ ++ struct iproc_pcie *pcie = platform_get_drvdata(pdev); ++ ++ pci_stop_root_bus(pcie->root_bus); ++ pci_remove_root_bus(pcie->root_bus); ++ ++ iproc_pcie_msi_disable(pcie); ++ ++ phy_power_off(pcie->phy); ++ phy_exit(pcie->phy); ++ ++ return 0; ++} ++ ++static const struct of_device_id iproc_pcie_of_match_table[] = { ++ { ++ .compatible = "brcm,iproc-pcie", ++ .data = (int *)IPROC_PCIE_PAXB, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table); ++ ++static struct platform_driver iproc_pcie_pltfm_driver = { ++ .driver = { ++ .name = "iproc-pcie", ++ .of_match_table = of_match_ptr(iproc_pcie_of_match_table), ++ }, ++ .probe = iproc_pcie_probe, ++ .remove = iproc_pcie_remove, ++}; ++ ++module_platform_driver(iproc_pcie_pltfm_driver); ++ ++MODULE_DESCRIPTION("Broadcom XGS iProc PCIe driver"); ++MODULE_LICENSE("GPL v2"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile +--- a/drivers/soc/bcm/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/soc/bcm/Makefile 2018-05-10 11:31:33.013403309 +0800 +@@ -1,2 +1,3 @@ + obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o + obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ ++obj-$(CONFIG_ARCH_XGS_IPROC) += xgs_iproc/ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/Makefile b/drivers/soc/bcm/xgs_iproc/Makefile +--- a/drivers/soc/bcm/xgs_iproc/Makefile 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/Makefile 2018-05-10 11:31:33.017403314 +0800 +@@ -0,0 +1 @@ ++obj-$(CONFIG_ARCH_XGS_IPROC) += xgs-iproc-misc-setup.o xgs-iproc-idm.o xgs-iproc.o iproc-cmic.o iproc-cmicx.o iproc-cmicd.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/iproc-cmic.c b/drivers/soc/bcm/xgs_iproc/iproc-cmic.c +--- a/drivers/soc/bcm/xgs_iproc/iproc-cmic.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/iproc-cmic.c 2018-05-10 11:31:33.017403314 +0800 +@@ -0,0 +1,161 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++ ++extern const struct sbus_ops cmicx_sbus_ops; ++extern const struct sbus_ops cmicd_sbus_ops; ++ ++static struct iproc_cmic *cmic; ++ ++int iproc_cmic_schan_reg32_write(u32 blk_type, u32 addr, u32 val) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->reg32_write) { ++ return cmic->sbus_ops->reg32_write(cmic, blk_type, addr, val); ++ } ++ } ++ return -EINVAL; ++} ++ ++u32 iproc_cmic_schan_reg32_read(u32 blk_type, u32 addr) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->reg32_read) { ++ return cmic->sbus_ops->reg32_read(cmic, blk_type, addr); ++ } ++ } ++ return 0; ++} ++ ++int iproc_cmic_schan_reg64_write(u32 blk_type, u32 addr, u64 val) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->reg64_write) { ++ return cmic->sbus_ops->reg64_write(cmic, blk_type, addr, val); ++ } ++ } ++ return -EINVAL; ++} ++ ++u64 iproc_cmic_schan_reg64_read(u32 blk_type, u32 addr) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->reg64_read) { ++ return cmic->sbus_ops->reg64_read(cmic, blk_type, addr); ++ } ++ } ++ return 0; ++} ++ ++int iproc_cmic_schan_ucmem_write(u32 blk_type, u32 *mem) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->ucmem_write) { ++ return cmic->sbus_ops->ucmem_write(cmic, blk_type, mem); ++ } ++ } ++ return -EINVAL; ++} ++ ++int iproc_cmic_schan_ucmem_read(u32 blk_type, u32 *mem) ++{ ++ if (cmic && cmic->sbus_ops) { ++ if (cmic->sbus_ops->ucmem_read) { ++ return cmic->sbus_ops->ucmem_read(cmic, blk_type, mem); ++ } ++ } ++ return -EINVAL; ++} ++ ++void inline __iomem *iproc_cmic_base_get(void) ++{ ++ if (cmic && cmic->base) { ++ return cmic->base; ++ } ++ return NULL; ++} ++ ++/**************************************************************************** ++ ***************************************************************************/ ++static int cmic_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ ++ cmic = devm_kzalloc(&pdev->dev, sizeof(*cmic), GFP_KERNEL); ++ if (!cmic) { ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, cmic); ++ cmic->dev = &pdev->dev; ++ ++ cmic->base = (void *)of_iomap(np, 0); ++ if (IS_ERR(cmic->base)) { ++ dev_err(&pdev->dev, "Unable to iomap CMIC resource\n"); ++ return PTR_ERR(cmic->base); ++ } ++ ++ if (of_device_is_compatible(np, "brcm,iproc-cmicx")) { ++ cmic->sbus_ops = &cmicx_sbus_ops; ++ } else if (of_device_is_compatible(np, "brcm,iproc-cmicd")) { ++ cmic->sbus_ops = &cmicd_sbus_ops; ++ } ++ ++ if (cmic->sbus_ops) { ++ if (cmic->sbus_ops->init) { ++ /* Initial cmic */ ++ cmic->sbus_ops->init(cmic); ++ } ++ } ++ ++ return 0; ++} ++ ++static int cmic_remove(struct platform_device *pdev) ++{ ++ if (cmic->base) { ++ iounmap(cmic->base); ++ } ++ ++ devm_kfree(&pdev->dev, cmic); ++ cmic = NULL; ++ ++ return 0; ++} ++ ++static const struct of_device_id iproc_cmic_of_match[] = { ++ {.compatible = "brcm,iproc-cmicx",}, ++ {.compatible = "brcm,iproc-cmicd",}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, iproc_cmic_of_match); ++ ++static struct platform_driver iproc_cmic_driver = { ++ .driver = { ++ .name = "iproc_cmic", ++ .of_match_table = iproc_cmic_of_match, ++ }, ++ .probe = cmic_probe, ++ .remove = cmic_remove, ++}; ++ ++module_platform_driver(iproc_cmic_driver); ++MODULE_LICENSE("GPL"); ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/iproc-cmicd.c b/drivers/soc/bcm/xgs_iproc/iproc-cmicd.c +--- a/drivers/soc/bcm/xgs_iproc/iproc-cmicd.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/iproc-cmicd.c 2018-05-10 11:31:33.017403314 +0800 +@@ -0,0 +1,166 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++#define CMICD_SBUS_RING_MAP_0_7(base) (base + 0x10098) ++#define CMICD_SBUS_RING_MAP_8_15(base) (base + 0x1009C) ++#define CMICD_SBUS_RING_MAP_16_23(base) (base + 0x100A0) ++#define CMICD_SBUS_RING_MAP_24_31(base) (base + 0x100A4) ++#define CMICD_SCHAN_CH0_CTRL(base) (base + 0x10000) ++#define CMICD_SCHAN_CH0_MESSAGE(base) (base + 0x1000c) ++ ++#define READ_MEMORY_CMD_MSG 0x07 ++#define READ_MEMORY_ACK_MSG 0x08 ++#define WRITE_MEMORY_CMD_MSG 0x09 ++#define WRITE_MEMORY_ACK_MSG 0x0a ++#define READ_REGISTER_CMD_MSG 0x0b ++#define READ_REGISTER_ACK_MSG 0x0c ++#define WRITE_REGISTER_CMD_MSG 0x0d ++#define WRITE_REGISTER_ACK_MSG 0x0e ++#define SBUSV4_REGTYPE_SHIFT 25 ++#define SBUSV4_REGADDR_SHIFT 8 ++#define SBUSV4_OPCODE_SHIFT 26 ++#define SBUSV4_BLOCKID_SHIFT 19 ++#define SBUSV4_DLEN_SHIFT 7 ++ ++#define CMICD_XLPORT_WC_UCMEM_DATA 0x0 ++#define REG32_DATA_LEN 4 ++#define REG64_DATA_LEN 8 ++#define UCMEM_DATA_LEN 16 ++ ++#define CMICD_BLOCK_ID_TOP 16 ++ ++ ++#define CMICD_CMD(mode, blk, len) ((mode << SBUSV4_OPCODE_SHIFT) | \ ++ (blk << SBUSV4_BLOCKID_SHIFT) | \ ++ (len << SBUSV4_DLEN_SHIFT)) ++ ++static int __cmicd_schan_write(struct iproc_cmic *cmic, ++ u32 cmd, u32 addr, u32 *val, int len) ++{ ++ u32 read = 0x0; ++ void __iomem *msg_addr; ++ int i; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ msg_addr = CMICD_SCHAN_CH0_MESSAGE(cmic->base); ++ writel(cmd, msg_addr); ++ ++ msg_addr += 4; ++ writel(addr, msg_addr); ++ ++ for (i = 0; i < len; i++) { ++ msg_addr += 4; ++ writel(val[i], msg_addr); ++ } ++ ++ writel(0x1, CMICD_SCHAN_CH0_CTRL(cmic->base)); ++ ++ // FIXME, should set timeout ++ while (read != 0x2) { ++ read = readl(CMICD_SCHAN_CH0_CTRL(cmic->base)); ++ } ++ return read; ++} ++ ++static int __cmicd_schan_read(struct iproc_cmic *cmic, ++ u32 cmd, u32 addr, u32 *val, int len) ++{ ++ u32 read = 0x0; ++ void __iomem *msg_addr; ++ int i; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ read = __cmicd_schan_write(cmic, cmd, addr, NULL, 0); ++ if (read != 0x02) { ++ return read; ++ } ++ ++ msg_addr = CMICD_SCHAN_CH0_MESSAGE(cmic->base); ++ for (i = 0; i < len; i++) { ++ msg_addr += 4; ++ val[i] = readl(msg_addr); ++ } ++ return val[0]; ++} ++ ++static int iproc_cmicd_schan_reg32_write(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr, u32 val) ++{ ++ u32 cmd, block; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICD_BLOCK_ID_TOP; ++ } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICD_CMD(WRITE_REGISTER_CMD_MSG, block, REG32_DATA_LEN); ++ return __cmicd_schan_write(cmic, cmd, addr, &val, 1); ++} ++ ++static u32 iproc_cmicd_schan_reg32_read(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr) ++{ ++ u32 cmd, block, val; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICD_BLOCK_ID_TOP; ++ } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICD_CMD(READ_REGISTER_CMD_MSG, block, REG32_DATA_LEN); ++ return __cmicd_schan_read(cmic, cmd, addr, &val, 1); ++} ++ ++static int iproc_cmicd_init(struct iproc_cmic *cmic) ++{ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ /* Configure SBUS Ring Map for TOP, block id = 16, ring number = 4 */ ++ writel(0x11112200, CMICD_SBUS_RING_MAP_0_7(cmic->base)); ++ writel(0x00430001, CMICD_SBUS_RING_MAP_8_15(cmic->base)); ++ writel(0x00005064, CMICD_SBUS_RING_MAP_16_23(cmic->base)); ++ writel(0x00000000, CMICD_SBUS_RING_MAP_24_31(cmic->base)); ++ ++ return 0; ++} ++ ++const struct sbus_ops cmicd_sbus_ops = { ++ .init = iproc_cmicd_init, ++ .reg32_write = iproc_cmicd_schan_reg32_write, ++ .reg32_read = iproc_cmicd_schan_reg32_read, ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/iproc-cmicx.c b/drivers/soc/bcm/xgs_iproc/iproc-cmicx.c +--- a/drivers/soc/bcm/xgs_iproc/iproc-cmicx.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/iproc-cmicx.c 2018-05-30 15:50:51.032753168 +0800 +@@ -0,0 +1,269 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++#define CMICX_TOP_SBUS_TIMEOUT(base) (base + 0x00000) ++#define CMICX_TOP_SBUS_RING_MAP_0_7(base) (base + 0x0000c) ++#define CMICX_TOP_SBUS_RING_MAP_32_39(base) (base + 0x0001c) ++#define CMICX_SCHAN_CH0_CTRL(base) (base + 0x10000) ++#define CMICX_SCHAN_CH0_MESSAGE(base) (base + 0x1000c) ++ ++#define READ_MEMORY_CMD_MSG 0x07 ++#define READ_MEMORY_ACK_MSG 0x08 ++#define WRITE_MEMORY_CMD_MSG 0x09 ++#define WRITE_MEMORY_ACK_MSG 0x0a ++#define READ_REGISTER_CMD_MSG 0x0b ++#define READ_REGISTER_ACK_MSG 0x0c ++#define WRITE_REGISTER_CMD_MSG 0x0d ++#define WRITE_REGISTER_ACK_MSG 0x0e ++#define SBUSV4_REGTYPE_SHIFT 25 ++#define SBUSV4_REGADDR_SHIFT 8 ++#define SBUSV4_OPCODE_SHIFT 26 ++#define SBUSV4_BLOCKID_SHIFT 19 ++#define SBUSV4_DLEN_SHIFT 7 ++ ++#define CMICX_XLPORT_WC_UCMEM_DATA 0x0 ++#define REG32_DATA_LEN 4 ++#define REG64_DATA_LEN 8 ++#define UCMEM_DATA_LEN 16 ++ ++#define CMICX_BLOCK_ID_TOP 7 ++#define CMICX_BLOCK_ID_XLPORT7 38 ++ ++ ++#define CMICX_CMD(mode, blk, len) ((mode << SBUSV4_OPCODE_SHIFT) | \ ++ (blk << SBUSV4_BLOCKID_SHIFT) | \ ++ (len << SBUSV4_DLEN_SHIFT)) ++ ++static int __cmicx_schan_write(struct iproc_cmic *cmic, ++ u32 cmd, u32 addr, u32 *val, int len) ++{ ++ u32 read = 0x0; ++ void __iomem *msg_addr; ++ int i; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ msg_addr = CMICX_SCHAN_CH0_MESSAGE(cmic->base); ++ writel(cmd, msg_addr); ++ ++ msg_addr += 4; ++ writel(addr, msg_addr); ++ ++ for (i = 0; i < len; i++) { ++ msg_addr += 4; ++ writel(val[i], msg_addr); ++ } ++ ++ writel(0x1, CMICX_SCHAN_CH0_CTRL(cmic->base)); ++ ++ // FIXME, should set timeout ++ while (read != 0x2) { ++ read = readl(CMICX_SCHAN_CH0_CTRL(cmic->base)); ++ } ++ return read; ++} ++ ++static int __cmicx_schan_read(struct iproc_cmic *cmic, ++ u32 cmd, u32 addr, u32 *val, int len) ++{ ++ u32 read = 0; ++ void __iomem *msg_addr; ++ int i; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ msg_addr = CMICX_SCHAN_CH0_MESSAGE(cmic->base); ++ writel(cmd, msg_addr); ++ ++ msg_addr += 4; ++ writel(addr, msg_addr); ++ ++ writel(0x1, CMICX_SCHAN_CH0_CTRL(cmic->base)); ++ ++ // FIXME, should set timeout ++ while (read != 0x2) { ++ read = readl(CMICX_SCHAN_CH0_CTRL(cmic->base)); ++ } ++ ++ msg_addr = CMICX_SCHAN_CH0_MESSAGE(cmic->base); ++ for (i = 0; i < len; i++) { ++ msg_addr += 4; ++ val[i] = readl(msg_addr); ++ } ++ ++ if (len == 1) ++ return val[0]; ++ else ++ return val[1]; ++} ++ ++static int iproc_cmicx_schan_reg32_write(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr, u32 val) ++{ ++ u32 cmd, block; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(WRITE_REGISTER_CMD_MSG, block, REG32_DATA_LEN); ++ return __cmicx_schan_write(cmic, cmd, addr, &val, 1); ++} ++ ++static u32 iproc_cmicx_schan_reg32_read(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr) ++{ ++ u32 cmd, block, val; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(READ_REGISTER_CMD_MSG, block, REG32_DATA_LEN); ++ return __cmicx_schan_read(cmic, cmd, addr, &val, 1); ++} ++ ++static int iproc_cmicx_schan_reg64_write(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr, u64 val) ++{ ++ u32 cmd, block; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(WRITE_REGISTER_CMD_MSG, block, REG64_DATA_LEN); ++ return __cmicx_schan_write(cmic, cmd, addr, (u32 *)&val, 2); ++} ++ ++static u64 iproc_cmicx_schan_reg64_read(struct iproc_cmic *cmic, ++ u32 blk_type, u32 addr) ++{ ++ u32 cmd, block; ++ u64 val; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(READ_REGISTER_CMD_MSG, block, REG64_DATA_LEN); ++ __cmicx_schan_read(cmic, cmd, addr, (u32 *)&val, 2); ++ return val; ++} ++ ++static int iproc_cmicx_schan_ucmem_write(struct iproc_cmic *cmic, ++ u32 blk_type, u32 *mem) ++{ ++ u32 cmd, block; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(WRITE_MEMORY_CMD_MSG, block, UCMEM_DATA_LEN); ++ return __cmicx_schan_write(cmic, cmd, CMICX_XLPORT_WC_UCMEM_DATA, mem, 4); ++} ++ ++static int iproc_cmicx_schan_ucmem_read(struct iproc_cmic *cmic, ++ u32 blk_type, u32 *mem) ++{ ++ u32 cmd, block; ++ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ if (blk_type == CMIC_BLOCK_TYPE_TOP) { ++ block = CMICX_BLOCK_ID_TOP; ++ } else if (blk_type == CMIC_BLOCK_TYPE_APM) { ++ block = CMICX_BLOCK_ID_XLPORT7; } else { ++ return -EINVAL; ++ } ++ ++ cmd = CMICX_CMD(READ_MEMORY_CMD_MSG, block, UCMEM_DATA_LEN); ++ return __cmicx_schan_read(cmic, cmd, CMICX_XLPORT_WC_UCMEM_DATA, mem, 2); ++} ++ ++static int iproc_cmicx_init(struct iproc_cmic *cmic) ++{ ++ if (!cmic || !cmic->base) { ++ return -EINVAL; ++ } ++ ++ /* ++ * SBUS ring and block number: ++ * ring 5: TOP(7) ++ * ring 7: XLPORT7(38) ++ */ ++ writel(0x52222100, CMICX_TOP_SBUS_RING_MAP_0_7(cmic->base)); ++ writel(0x07500066, CMICX_TOP_SBUS_RING_MAP_32_39(cmic->base)); ++ writel(0x5000, CMICX_TOP_SBUS_TIMEOUT(cmic->base)); ++ ++ return 0; ++} ++ ++const struct sbus_ops cmicx_sbus_ops = { ++ .init = iproc_cmicx_init, ++ .reg32_write = iproc_cmicx_schan_reg32_write, ++ .reg32_read = iproc_cmicx_schan_reg32_read, ++ .reg64_write = iproc_cmicx_schan_reg64_write, ++ .reg64_read = iproc_cmicx_schan_reg64_read, ++ .ucmem_write = iproc_cmicx_schan_ucmem_write, ++ .ucmem_read = iproc_cmicx_schan_ucmem_read, ++}; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/xgs-iproc-idm.c b/drivers/soc/bcm/xgs_iproc/xgs-iproc-idm.c +--- a/drivers/soc/bcm/xgs_iproc/xgs-iproc-idm.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/xgs-iproc-idm.c 2018-05-10 11:31:33.017403314 +0800 +@@ -0,0 +1,309 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++ ++#define IPROC_IDM_COMPATIBLE "brcm,iproc-idm" ++ ++#define IDM_ERROR_LOG_ENABLE 0x33A ++#define IDM_ERROR_LOG_CLEAR 0x3 ++ ++#define IDM_ERROR_LOG_CONTROL_REG(base) (base + 0x900) ++#define IDM_ERROR_LOG_COMPLETE_REG(base) (base + 0x904) ++#define IDM_ERROR_LOG_STATUS_REG(base) (base + 0x908) ++#define IDM_ERROR_LOG_ADDR_LSB_REG(base) (base + 0x90c) ++#define IDM_ERROR_LOG_ID_REG(base) (base + 0x914) ++#define IDM_ERROR_LOG_FLAGS_REG(base) (base + 0x91c) ++#define IDM_INTERRUPT_STATUS_REG(base) (base + 0xa00) ++ ++enum support_dev_ids { ++ XGS_IPROC_HX4 = 0, ++ XGS_IPROC_KT2, ++ XGS_IPROC_HR2, ++ XGS_IPROC_GH, ++ XGS_IPROC_SB2, ++ XGS_IPROC_HR3, ++ XGS_IPROC_GH2, ++ XGS_IPROC_WH2, ++ XGS_IPROC_HX5, ++ XGS_IPROC_MAX_DEVS, ++}; ++ ++static struct xgs_iproc_dev_infos_s { ++ char dt_compat_str[32]; ++ u32 dev_id; ++ u32 dmac_reset_offset; ++} xgs_iproc_dev_infos[] = { ++ { "brcm,helix4", XGS_IPROC_HX4, 0x14800 }, ++ { "brcm,katana2", XGS_IPROC_KT2, 0x14800 }, ++ { "brcm,hurricane2", XGS_IPROC_HR2, 0x14800 }, ++ { "brcm,greyhound", XGS_IPROC_GH, 0x14800 }, ++ { "brcm,saber2", XGS_IPROC_SB2, 0xf800 }, ++ { "brcm,hurricane3", XGS_IPROC_HR3, 0xf800 }, ++ { "brcm,greyhound2", XGS_IPROC_GH2, 0xf800 }, ++ { "brcm,wolfhound2", XGS_IPROC_WH2, 0xf800 }, ++ { "brcm,helix5", XGS_IPROC_HX5, 0x10800 }, ++ { "", 0, 0 } ++}; ++ ++#define IDM_BASE_ADDR_NUM 2 ++#define IDM_BASE_ADDR_MASK 0x10000000 ++#define IDM_BASE_ADDR_AREA(val) ((val & IDM_BASE_ADDR_MASK) >> 28) ++#define IDM_OFFSET_MASK 0x0FFFFFFF ++ ++static struct xgs_iproc_idm_err_offset_s { ++ u32 ihost_s1[XGS_IPROC_MAX_DEVS]; ++ u32 ihost_s0[XGS_IPROC_MAX_DEVS]; ++ u32 axi_pcie_s0[XGS_IPROC_MAX_DEVS]; ++ u32 ddr_s1[XGS_IPROC_MAX_DEVS]; ++ u32 ddr_s2[XGS_IPROC_MAX_DEVS]; ++ u32 cmic_s0[XGS_IPROC_MAX_DEVS]; ++ u32 apby_s0[XGS_IPROC_MAX_DEVS]; ++ u32 rom_s0[XGS_IPROC_MAX_DEVS]; ++ u32 nand_idm[XGS_IPROC_MAX_DEVS]; ++ u32 qspi_idm[XGS_IPROC_MAX_DEVS]; ++ u32 a9jtag_s0[XGS_IPROC_MAX_DEVS]; ++ u32 sram_s0[XGS_IPROC_MAX_DEVS]; ++ u32 apbz_s0[XGS_IPROC_MAX_DEVS]; ++ u32 axiic_ds_3[XGS_IPROC_MAX_DEVS]; ++ u32 apbw_idm[XGS_IPROC_MAX_DEVS]; ++ u32 apbx_idm[XGS_IPROC_MAX_DEVS]; ++ u32 axiic_ds_0[XGS_IPROC_MAX_DEVS]; ++ u32 periph_s0[XGS_IPROC_MAX_DEVS]; ++ u32 genres_s0[XGS_IPROC_MAX_DEVS]; ++} xgs_iproc_idm_err_offset = { ++ /* HX4, KT2, HR2, GH, SB2, HR3, ++ GH2, WH2, HX5 */ ++ { 0x00007000, 0x00007000, 0x00007000, 0x00006000, 0x00006000, 0x00006000, ++ 0x00006000, 0x00006000, 0x0 }, /* IHOST_S1_IDM */ ++ { 0x00008000, 0x00008000, 0x00008000, 0x00007000, 0x00007000, 0x00007000, ++ 0x00007000, 0x00007000, 0x00014000 }, /* IHOST_S0_IDM */ ++ { 0x0000b000, 0x0000b000, 0x0000b000, 0x00008000, 0x00008000, 0x00008000, ++ 0x00008000, 0x00008000, 0x0000a000 }, /* AXI_PCIE_S0_IDM */ ++ { 0x00009000, 0x00009000, 0x00009000, 0x10002000, 0x10002000, 0x00004000, ++ 0x10002000, 0x00004000, 0x0001a000 }, /* DDR_S1_IDM */ ++ { 0x0000a000, 0x0000a000, 0x0000a000, 0x10003000, 0x10003000, 0x00005000, ++ 0x10003000, 0x00005000, 0x0001b000 }, /* DDR_S2_IDM */ ++ { 0x0000d000, 0x0000d000, 0x0000d000, 0x0000a000, 0x0000a000, 0x0000a000, ++ 0x0000a000, 0x0000a000, 0x0000b000 }, /* CMICD_S0_IDM */ ++ { 0x0000f000, 0x0000f000, 0x0000f000, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0000c000 }, /* APBY_S0_IDM */ ++ { 0x0001a000, 0x0001a000, 0x0001a000, 0x10004000, 0x10004000, 0x0001a000, ++ 0x10004000, 0x0001a000, 0x0 }, /* ROM_S0_IDM */ ++ { 0x0001b000, 0x0001b000, 0x0001b000, 0x10005000, 0x10005000, 0x0001d000, ++ 0x10005000, 0x0001d000, 0x0 }, /* NAND_IDM */ ++ { 0x0001c000, 0x0001c000, 0x0001c000, 0x10006000, 0x10006000, 0x0001f000, ++ 0x10006000, 0x0001f000, 0x0 }, /* QSPI_IDM */ ++ { 0x0001d000, 0x0001d000, 0x0001d000, 0x00019000, 0x00019000, 0x00019000, ++ 0x00019000, 0x00019000, 0x0 }, /* A9JTAG_S0_IDM */ ++ { 0x00020000, 0x00020000, 0x00020000, 0x0001b000, 0x0001b000, 0x0, ++ 0x0001b000, 0x0, 0x0 }, /* SRAM_S0_IDM */ ++ { 0x00021000, 0x00021000, 0x00021000, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x00017000 }, /* APBZ_S0_IDM */ ++ { 0x00023000, 0x00023000, 0x00023000, 0x0001e000, 0x0001e000, 0x0, ++ 0x0001e000, 0x0, 0x0 }, /* AXIIC_DS_3_IDM */ ++ { 0x00031000, 0x00031000, 0x00031000, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0 }, /* APBW_IDM */ ++ { 0x00032000, 0x00032000, 0x00032000, 0x00030000, 0x00030000, 0x00030000, ++ 0x00030000, 0x00030000, 0x0 }, /* APBX_IDM */ ++ { 0x00041000, 0x00041000, 0x00041000, 0x00020000, 0x00020000, 0x00020000, ++ 0x00020000, 0x00020000, 0x00053000 }, /* AXIIC_DS_0_IDM */ ++ { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x00018000 }, /* PERIPH_S0_IDM */ ++ { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x00019000 }, /* GENRES_S0_IDM */ ++}; ++ ++struct xgs_iproc_idm { ++ u32 curr_dev; ++ void __iomem *idm_base[IDM_BASE_ADDR_NUM]; ++ u32 dmac_reset_offset; ++}; ++ ++static struct xgs_iproc_idm xgs_iproc_idm = { 0 }; ++ ++/********************************************************************************** ++***********************************************************************************/ ++void inline __iomem *get_iproc_idm_base(int idx) ++{ ++ if (idx >= IDM_BASE_ADDR_NUM) ++ return NULL; ++ ++ return xgs_iproc_idm.idm_base[idx]; ++} ++ ++int xgs_iproc_idm_dmac_reset(void) ++{ ++ void __iomem *reset_base = NULL; ++ ++ if (xgs_iproc_idm.idm_base[0] == NULL || ++ xgs_iproc_idm.dmac_reset_offset == 0) { ++ return -EINVAL; ++ } ++ ++ reset_base = xgs_iproc_idm.idm_base[0] + xgs_iproc_idm.dmac_reset_offset; ++ writel(readl(reset_base) & ~0x1, reset_base); ++ ++ return 0; ++} ++ ++static int idm_error_log_dump(void __iomem *idm_addr) ++{ ++ void __iomem *reg_addr; ++ u32 val; ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_STATUS_REG(idm_addr); ++ if ((val = readl(reg_addr)) > 0) { ++ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, val); ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_ADDR_LSB_REG(idm_addr); ++ val = readl(reg_addr); ++ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, val); ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_ID_REG(idm_addr); ++ val = readl(reg_addr); ++ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, val); ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_FLAGS_REG(idm_addr); ++ val = readl(reg_addr); ++ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, val); ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_COMPLETE_REG(idm_addr); ++ writel(IDM_ERROR_LOG_CLEAR, reg_addr); ++ ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_STATUS_REG(idm_addr); ++ val = readl(reg_addr); ++ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, val); ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t idm_timeout_handler(int val, void *ptr) ++{ ++ u32 idx, offset; ++ void __iomem *idm_addr; ++ u32 i, cnt, *idm_item; ++ ++ if (xgs_iproc_idm.curr_dev == XGS_IPROC_MAX_DEVS) ++ return IRQ_HANDLED; ++ ++ cnt = sizeof(struct xgs_iproc_idm_err_offset_s) / (sizeof(u32) * XGS_IPROC_MAX_DEVS); ++ for (i = 0; i < cnt; i++) { ++ idm_item = (u32*)((u32*)(&xgs_iproc_idm_err_offset) + i * XGS_IPROC_MAX_DEVS); ++ offset = idm_item[xgs_iproc_idm.curr_dev]; ++ if (offset != 0) { ++ idx = IDM_BASE_ADDR_AREA(offset); ++ if (xgs_iproc_idm.idm_base[idx]) { ++ idm_addr = xgs_iproc_idm.idm_base[idx] + (offset & IDM_OFFSET_MASK); ++ idm_error_log_dump(idm_addr); ++ } ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int init_request_idm_timeout(void) ++{ ++ void __iomem *idm_addr; ++ void __iomem *reg_addr; ++ u32 i, cnt, *idm_item; ++ u32 idx, offset; ++ ++ if (xgs_iproc_idm.curr_dev == XGS_IPROC_MAX_DEVS) ++ return IRQ_HANDLED; ++ ++ /* clear all pending idm interrupts */ ++ idm_timeout_handler(0, NULL); ++ ++ /* enable idm error log for all slaves */ ++ cnt = sizeof(struct xgs_iproc_idm_err_offset_s) / (sizeof(u32) * XGS_IPROC_MAX_DEVS); ++ for (i = 0; i < cnt; i++) { ++ idm_item = (u32*)((u32*)(&xgs_iproc_idm_err_offset) + i * XGS_IPROC_MAX_DEVS); ++ offset = idm_item[xgs_iproc_idm.curr_dev]; ++ if (offset != 0) { ++ idx = IDM_BASE_ADDR_AREA(offset); ++ if (xgs_iproc_idm.idm_base[idx]) { ++ idm_addr = xgs_iproc_idm.idm_base[idx] + (offset & IDM_OFFSET_MASK); ++ reg_addr = (void __iomem *)IDM_ERROR_LOG_CONTROL_REG(idm_addr); ++ writel(IDM_ERROR_LOG_ENABLE, reg_addr); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int xgs_iproc_idm_init(void) ++{ ++ struct device_node *np; ++ int idx, ret = 0; ++ int irq, irqs_total; ++ ++ /* Get IDM base addr */ ++ np = of_find_compatible_node(NULL, NULL, IPROC_IDM_COMPATIBLE); ++ if (!np) { ++ pr_err("%s: No IDM node found\n", __func__); ++ return -ENODEV; ++ } ++ ++ xgs_iproc_idm.idm_base[0] = of_iomap(np, 0); ++ if (!xgs_iproc_idm.idm_base[0]) { ++ return -ENOMEM; ++ } ++ ++ /* ++ * Second IDM base addr required for GH/SB2/GH2 IDM timeout handling. ++ * For other devices, the second IDM base addr is not used. So, it is ++ * fine even the addr is NULL. ++ */ ++ xgs_iproc_idm.idm_base[1] = of_iomap(np, 1); ++ ++ /* Get the current platform */ ++ idx = 0; ++ while(1) { ++ if (strlen(xgs_iproc_dev_infos[idx].dt_compat_str) == 0) ++ return -EINVAL; ++ if (of_machine_is_compatible(xgs_iproc_dev_infos[idx].dt_compat_str)) ++ break; ++ idx++; ++ } ++ xgs_iproc_idm.curr_dev = xgs_iproc_dev_infos[idx].dev_id; ++ xgs_iproc_idm.dmac_reset_offset = xgs_iproc_dev_infos[idx].dmac_reset_offset; ++ ++ /* Setup idm timeout handler for debug purpose */ ++ init_request_idm_timeout(); ++ ++ irqs_total = of_irq_count(np); ++ if (!irqs_total) ++ return -EINVAL; ++ ++ for (idx = 0; idx < irqs_total; idx++) { ++ irq = of_irq_get(np, idx); ++ ret = request_irq(irq, (irq_handler_t)idm_timeout_handler, ++ IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk(KERN_WARNING "%s: request_irq return = %d\n", __func__, ret); ++ } ++ ++ return ret; ++} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/xgs-iproc-misc-setup.c b/drivers/soc/bcm/xgs_iproc/xgs-iproc-misc-setup.c +--- a/drivers/soc/bcm/xgs_iproc/xgs-iproc-misc-setup.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/xgs-iproc-misc-setup.c 2018-05-10 11:31:33.017403314 +0800 +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; 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 ++ ++#define IPROC_DMU_PCU_COMPATIBLE "brcm,iproc-dmu-pcu" ++#define IPROC_WRAP_CTRL_COMPATIBLE "brcm,iproc-wrap-ctrl" ++#define KT2_WRAP_MISC_COMPATIBLE "brcm,kt2-wrap-misc" ++ ++static void __iomem *iproc_dmu_pcu_base = NULL; ++static void __iomem *iproc_wrap_ctrl_base = NULL; ++ ++extern void request_idm_timeout_interrupts(struct platform_device *); ++ ++void inline __iomem *get_iproc_dmu_pcu_base(void) ++{ ++ return iproc_dmu_pcu_base; ++} ++ ++void inline __iomem *get_iproc_wrap_ctrl_base(void) ++{ ++ return iproc_wrap_ctrl_base; ++} ++ ++int inline is_wh2_amac_sgmii(void) ++{ ++ return readl(get_iproc_wrap_ctrl_base() + 0xa8) & 0x04; ++} ++ ++int xgs_iproc_misc_setup(void) ++{ ++ struct device_node *np; ++ void __iomem *wrap_misc_reg = NULL; ++ u32 tmp; ++ u32 wrap_misc_offset, serdes_ctrl_sel, serdes_mdio_sel; ++ ++ /* Get DMU/PCU base addr */ ++ np = of_find_compatible_node(NULL, NULL, IPROC_DMU_PCU_COMPATIBLE); ++ if (!np) { ++ pr_err("%s: No dmu/pcu node found\n", __func__); ++ return -ENODEV ; ++ } ++ ++ iproc_dmu_pcu_base = of_iomap(np, 0); ++ if (!iproc_dmu_pcu_base) ++ return -ENOMEM; ++ ++ /* Get WRAP CTRL base addr */ ++ np = of_find_compatible_node(NULL, NULL, IPROC_WRAP_CTRL_COMPATIBLE); ++ if (!np) { ++ pr_err("%s: No wrap ctrl node found\n", __func__); ++ return -ENODEV; ++ } ++ ++ iproc_wrap_ctrl_base = of_iomap(np, 0); ++ if (!iproc_wrap_ctrl_base) ++ return -ENOMEM; ++ ++ /* Enable AMAC SERDES MDIO SEL/CTRL for HX4/KT2 */ ++ if (!of_property_read_u32_index(np, "amac-serdes-mdio-ctrl-sel", 0, ++ &wrap_misc_offset)) { ++ of_property_read_u32_index(np, "amac-serdes-mdio-ctrl-sel", 1, ++ &serdes_ctrl_sel); ++ of_property_read_u32_index(np, "amac-serdes-mdio-ctrl-sel", 2, ++ &serdes_mdio_sel); ++ ++ wrap_misc_reg = (void __iomem *)(iproc_wrap_ctrl_base + ++ wrap_misc_offset); ++ tmp = readl(wrap_misc_reg); ++ tmp |= (1 << serdes_ctrl_sel) | (1 << serdes_mdio_sel); ++ writel(tmp, wrap_misc_reg); ++ } ++ ++ return 1; ++} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs_iproc/xgs-iproc.c b/drivers/soc/bcm/xgs_iproc/xgs-iproc.c +--- a/drivers/soc/bcm/xgs_iproc/xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/soc/bcm/xgs_iproc/xgs-iproc.c 2018-05-10 11:31:33.021403318 +0800 +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* Currently, this driver is only support for Helix5. As for the other ++ * XGS IProc chips, the initial code and reset handler are defined in ++ * mach-iproc/board_bu.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define DMU_CRU_RESET_OFFSET 0x200 ++ ++static int xgs_iproc_restart(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ void * __iomem reg_addr; ++ u32 val; ++ ++ /* CRU_RESET register */ ++ reg_addr = get_iproc_dmu_pcu_base() + DMU_CRU_RESET_OFFSET; ++ ++ /* set iproc_reset_n to 0 */ ++ val = readl(reg_addr); ++ val &= ~((u32) 1 << 1); ++ ++ writel(val, reg_addr); ++ ++ /* Wait for reset */ ++ while (1) { ++ cpu_do_idle(); ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block xgs_iproc_nb = { ++ .notifier_call = xgs_iproc_restart, ++ .priority = 192, ++}; ++ ++static char * xgs_iproc_dt_compat_str[] = { ++ "brcm,helix5", ++ "", ++}; ++ ++static int __init xgs_iproc_init(void) ++{ ++ int ret; ++ int idx = 0; ++ ++ while(1) { ++ if (strlen(xgs_iproc_dt_compat_str[idx]) == 0) { ++ return -EINVAL; ++ } ++ if (of_machine_is_compatible(xgs_iproc_dt_compat_str[idx])) { ++ break; ++ } ++ idx++; ++ } ++ ++ ret = xgs_iproc_misc_setup(); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ /* Init idm and setup idm timeout handler for debug purpose */ ++ /* xgs_iproc_idm_init should be init before reset dmac */ ++ ret = xgs_iproc_idm_init(); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ /* FIXME, need confirm whether we need reset the DMAC or not */ ++ xgs_iproc_idm_dmac_reset(); ++ ++ /* Populate platform devices */ ++ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++ ++ if (register_reboot_notifier(&xgs_iproc_nb)) { ++ printk("Register reboot handler failed\n"); ++ } ++ ++ return 0; ++} ++arch_initcall(xgs_iproc_init); ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/spi/Kconfig b/drivers/spi/Kconfig +--- a/drivers/spi/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/spi/Kconfig 2018-05-10 11:31:33.033403332 +0800 +@@ -162,8 +162,8 @@ config SPI_BCM63XX_HSSPI + config SPI_BCM_QSPI + tristate "Broadcom BSPI and MSPI controller support" + depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || \ +- BMIPS_GENERIC || COMPILE_TEST +- default ARCH_BCM_IPROC ++ ARCH_XGS_IPROC || BMIPS_GENERIC || COMPILE_TEST ++ default ARCH_BCM_IPROC || ARCH_XGS_IPROC + help + Enables support for the Broadcom SPI flash and MSPI controller. + Select this option for any one of BRCMSTB, iProc NSP and NS2 SoCs +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c +--- a/drivers/spi/spi-bcm-qspi.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/spi/spi-bcm-qspi.c 2018-05-10 11:31:33.033403332 +0800 +@@ -88,7 +88,7 @@ + #define BSPI_BPP_MODE_SELECT_MASK BIT(8) + #define BSPI_BPP_ADDR_SELECT_MASK BIT(16) + +-#define BSPI_READ_LENGTH 512 ++//#define BSPI_READ_LENGTH 512 + + /* MSPI register offsets */ + #define MSPI_SPCR0_LSB 0x000 +@@ -118,6 +118,8 @@ + + #define MSPI_MSPI_STATUS_SPIF BIT(0) + ++#define CRU_CTRL_REG 0x0 ++ + #define INTR_BASE_BIT_SHIFT 0x02 + #define INTR_COUNT 0x07 + +@@ -171,6 +173,7 @@ enum base_type { + MSPI, + BSPI, + CHIP_SELECT, ++ CRU_CTRL, + BASEMAX, + }; + +@@ -195,12 +197,14 @@ struct bcm_qspi_dev_id { + struct qspi_trans { + struct spi_transfer *trans; + int byte; ++ int slots; + bool mspi_last_trans; + }; + + struct bcm_qspi { + struct platform_device *pdev; + struct spi_master *master; ++ struct spi_device *spi_dev; + struct clk *clk; + u32 base_clk; + u32 max_speed_hz; +@@ -453,11 +457,12 @@ static int bcm_qspi_bspi_set_mode(struct + qspi->xfer_mode.flex_mode = true; + + if (!bcm_qspi_bspi_ver_three(qspi)) { +- u32 val, mask; ++ u32 val, mask, endian; + +- val = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL); ++ val = qspi->s3_strap_override_ctrl; + mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE; +- if (val & mask || qspi->s3_strap_override_ctrl & mask) { ++ endian = BSPI_STRAP_OVERRIDE_CTRL_ENDAIN_MODE; ++ if ((val & mask) && (val & ~(mask | endian))) { + qspi->xfer_mode.flex_mode = false; + bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, 0); + error = bcm_qspi_bspi_set_override(qspi, msg, hp); +@@ -570,6 +575,8 @@ static void bcm_qspi_update_parms(struct + static int bcm_qspi_setup(struct spi_device *spi) + { + struct bcm_qspi_parms *xp; ++ struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); ++ u32 tmp; + + if (spi->bits_per_word > 16) + return -EINVAL; +@@ -581,8 +588,20 @@ static int bcm_qspi_setup(struct spi_dev + return -ENOMEM; + spi_set_ctldata(spi, xp); + } +- xp->speed_hz = spi->max_speed_hz; ++ + xp->mode = spi->mode; ++ xp->speed_hz = spi->max_speed_hz; ++ ++ /* Set BSPI clock rate */ ++ tmp = bcm_qspi_read(qspi, CRU_CTRL, CRU_CTRL_REG); ++ tmp &= ~0x6; ++ if (spi->max_speed_hz >= 62500000) ++ tmp |= 0x6; ++ else if (spi->max_speed_hz >= 50000000) ++ tmp |= 0x2; ++ else if (spi->max_speed_hz >= 31250000) ++ tmp |= 0x4; ++ bcm_qspi_write(qspi, CRU_CTRL, CRU_CTRL_REG, tmp); + + if (spi->bits_per_word) + xp->bits_per_word = spi->bits_per_word; +@@ -674,22 +693,25 @@ static void read_from_hw(struct bcm_qspi + tp = qspi->trans_pos; + + for (slot = 0; slot < slots; slot++) { ++ if (tp.trans->rx_buf) { + if (tp.trans->bits_per_word <= 8) { + u8 *buf = tp.trans->rx_buf; + + if (buf) +- buf[tp.byte] = read_rxram_slot_u8(qspi, slot); ++ buf[tp.byte] = ++ read_rxram_slot_u8(qspi, slot); + dev_dbg(&qspi->pdev->dev, "RD %02x\n", + buf ? buf[tp.byte] : 0xff); + } else { + u16 *buf = tp.trans->rx_buf; + + if (buf) +- buf[tp.byte / 2] = read_rxram_slot_u16(qspi, +- slot); ++ buf[tp.byte / 2] = ++ read_rxram_slot_u16(qspi, slot); + dev_dbg(&qspi->pdev->dev, "RD %04x\n", + buf ? buf[tp.byte] : 0xffff); + } ++ } + + update_qspi_trans_byte_count(qspi, &tp, + TRANS_STATUS_BREAK_NONE); +@@ -767,6 +789,9 @@ static int write_to_hw(struct bcm_qspi * + slot++; + } + ++ /* save slot number for read_from_hw() */ ++ qspi->trans_pos.slots = slot; ++ + if (!slot) { + dev_err(&qspi->pdev->dev, "%s: no data to send?", __func__); + goto done; +@@ -798,9 +823,9 @@ static int bcm_qspi_bspi_flash_read(stru + struct spi_flash_read_message *msg) + { + struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); +- u32 addr = 0, len, rdlen, len_words; ++ u32 addr = 0, len, len_words; + int ret = 0; +- unsigned long timeo = msecs_to_jiffies(100); ++ unsigned long timeo = msecs_to_jiffies(1000); + struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; + + if (bcm_qspi_bspi_ver_three(qspi)) +@@ -825,30 +850,20 @@ static int bcm_qspi_bspi_flash_read(stru + else + addr = msg->from & 0x00ffffff; + +- if (bcm_qspi_bspi_ver_three(qspi) == true) +- addr = (addr + 0xc00000) & 0xffffff; +- +- /* +- * read into the entire buffer by breaking the reads +- * into RAF buffer read lengths +- */ + len = msg->len; +- qspi->bspi_rf_msg_idx = 0; + +- do { +- if (len > BSPI_READ_LENGTH) +- rdlen = BSPI_READ_LENGTH; +- else +- rdlen = len; ++ if (bcm_qspi_bspi_ver_three(qspi) == true) ++ addr = (addr + 0xc00000) & 0xffffff; + + reinit_completion(&qspi->bspi_done); + bcm_qspi_enable_bspi(qspi); +- len_words = (rdlen + 3) >> 2; ++ len_words = (len + 3) >> 2; + qspi->bspi_rf_msg = msg; + qspi->bspi_rf_msg_status = 0; +- qspi->bspi_rf_msg_len = rdlen; +- dev_dbg(&qspi->pdev->dev, +- "bspi xfr addr 0x%x len 0x%x", addr, rdlen); ++ qspi->bspi_rf_msg_idx = 0; ++ qspi->bspi_rf_msg_len = len; ++ dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len); ++ + bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); + bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); + bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); +@@ -867,15 +884,11 @@ static int bcm_qspi_bspi_flash_read(stru + if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { + dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); + ret = -ETIMEDOUT; +- break; ++ } else { ++ /* set the return length for the caller */ ++ msg->retlen = len; + } + +- /* set msg return length */ +- msg->retlen += rdlen; +- addr += rdlen; +- len -= rdlen; +- } while (len); +- + return ret; + } + +@@ -884,25 +897,22 @@ static int bcm_qspi_transfer_one(struct + struct spi_transfer *trans) + { + struct bcm_qspi *qspi = spi_master_get_devdata(master); +- int slots; +- unsigned long timeo = msecs_to_jiffies(100); ++ unsigned long timeo = msecs_to_jiffies(1000); + + bcm_qspi_chip_select(qspi, spi->chip_select); + qspi->trans_pos.trans = trans; + qspi->trans_pos.byte = 0; ++ qspi->spi_dev = spi; + +- while (qspi->trans_pos.byte < trans->len) { + reinit_completion(&qspi->mspi_done); + +- slots = write_to_hw(qspi, spi); ++ write_to_hw(qspi, spi); ++ + if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) { + dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n"); + return -ETIMEDOUT; + } + +- read_from_hw(qspi, slots); +- } +- + return 0; + } + +@@ -1012,7 +1022,24 @@ static irqreturn_t bcm_qspi_mspi_l2_isr( + bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status); + if (qspi->soc_intc) + soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_DONE); ++ ++ if (qspi->trans_pos.trans->tx_buf && ++ (qspi->trans_pos.trans->len <= MSPI_NUM_CDRAM)) { + complete(&qspi->mspi_done); ++ spi_finalize_current_transfer(qspi->master); ++ return IRQ_HANDLED; ++ } ++ ++ read_from_hw(qspi, qspi->trans_pos.slots); ++ ++ if (qspi->trans_pos.trans) { ++ write_to_hw(qspi, qspi->spi_dev); ++ } ++ else { ++ complete(&qspi->mspi_done); ++ spi_finalize_current_transfer(qspi->master); ++ } ++ + return IRQ_HANDLED; + } + +@@ -1031,6 +1058,8 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_i + if (qspi->bspi_rf_msg_len == 0) { + qspi->bspi_rf_msg = NULL; + if (qspi->soc_intc) { ++ /* Ack BSPI done interrupt */ ++ soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_DONE); + /* disable soc BSPI interrupt */ + soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, + false); +@@ -1042,11 +1071,12 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_i + bcm_qspi_bspi_lr_clear(qspi); + else + bcm_qspi_bspi_flush_prefetch_buffers(qspi); +- } +- ++ } else { + if (qspi->soc_intc) +- /* clear soc BSPI interrupt */ +- soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_DONE); ++ /* Ack FIFO full interrupt */ ++ soc_intc->bcm_qspi_int_ack(soc_intc, ++ BSPI_FIFO_FULL); ++ } + } + + status &= INTR_BSPI_LR_SESSION_DONE_MASK; +@@ -1233,8 +1263,6 @@ int bcm_qspi_probe(struct platform_devic + master->dev.of_node = dev->of_node; + master->num_chipselect = NUM_CHIPSELECT; + +- qspi->big_endian = of_device_is_big_endian(dev->of_node); +- + if (!of_property_read_u32(dev->of_node, "num-cs", &val)) + master->num_chipselect = val; + +@@ -1276,6 +1304,26 @@ int bcm_qspi_probe(struct platform_devic + } + } + ++ /* iProc BSPI clock is set through CRU control */ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cru_ctrl"); ++ if (res) { ++ qspi->base[CRU_CTRL] = devm_ioremap_resource(dev, res); ++ if (IS_ERR(qspi->base[CRU_CTRL])) { ++ ret = PTR_ERR(qspi->base[CRU_CTRL]); ++ goto qspi_probe_err; ++ } ++ } ++ ++ qspi->big_endian = of_device_is_big_endian(dev->of_node); ++ ++ val = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL); ++ if (qspi->big_endian == 0 && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) { ++ val |= BSPI_STRAP_OVERRIDE_CTRL_ENDAIN_MODE; ++ val |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE; ++ bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, val); ++ } ++ qspi->s3_strap_override_ctrl = val; ++ + qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id), + GFP_KERNEL); + if (!qspi->dev_ids) { +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/spi/spi-bcm-qspi.h b/drivers/spi/spi-bcm-qspi.h +--- a/drivers/spi/spi-bcm-qspi.h 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/spi/spi-bcm-qspi.h 2018-05-10 11:31:33.033403332 +0800 +@@ -59,7 +59,8 @@ enum { + MSPI_DONE = 0x1, + BSPI_DONE = 0x2, + BSPI_ERR = 0x4, +- MSPI_BSPI_DONE = 0x7 ++ MSPI_BSPI_DONE = 0x7, ++ BSPI_FIFO_FULL = 0x8 + }; + + struct bcm_qspi_soc_intc { +@@ -95,6 +96,8 @@ static inline u32 get_qspi_mask(int type + return INTR_MSPI_DONE_MASK; + case BSPI_DONE: + return BSPI_LR_INTERRUPTS_ALL; ++ case BSPI_FIFO_FULL: ++ return INTR_BSPI_LR_FULLNESS_REACHED_MASK; + case MSPI_BSPI_DONE: + return QSPI_INTERRUPTS_ALL; + case BSPI_ERR: +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/spi/spi-iproc-qspi.c b/drivers/spi/spi-iproc-qspi.c +--- a/drivers/spi/spi-iproc-qspi.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/spi/spi-iproc-qspi.c 2018-05-10 11:31:33.041403341 +0800 +@@ -143,6 +143,7 @@ static int bcm_iproc_remove(struct platf + static const struct of_device_id bcm_iproc_of_match[] = { + { .compatible = "brcm,spi-nsp-qspi" }, + { .compatible = "brcm,spi-ns2-qspi" }, ++ { .compatible = "brcm,spi-xgs-iproc-qspi" }, + {}, + }; + MODULE_DEVICE_TABLE(of, bcm_iproc_of_match); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c +--- a/drivers/usb/gadget/legacy/serial.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/gadget/legacy/serial.c 2018-05-10 11:31:33.753404129 +0800 +@@ -250,7 +250,7 @@ static int __init init(void) + */ + if (use_acm) { + serial_config_driver.label = "CDC ACM config"; +- serial_config_driver.bConfigurationValue = 2; ++ serial_config_driver.bConfigurationValue = 1; + device_desc.bDeviceClass = USB_CLASS_COMM; + device_desc.idProduct = + cpu_to_le16(GS_CDC_PRODUCT_ID); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig +--- a/drivers/usb/gadget/udc/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/gadget/udc/Kconfig 2018-05-10 11:31:33.753404129 +0800 +@@ -439,6 +439,17 @@ config USB_GADGET_XILINX + dynamically linked module called "udc-xilinx" and force all + gadget drivers to also be dynamically linked. + ++config USB_XGS_IPROC_UDC ++ tristate "Broadcom XGS IPROC USB Device driver" ++ depends on ARCH_XGS_IPROC && USB_GADGET ++ default n ++ help ++ USB peripheral controller driver for Broadcom XGS IPROC USB 2 device. ++ ++ Say "y" to link the driver statically, or "m" to build a dynamically ++ linked module called "xgs_iproc_udc" and force all gadget drivers to ++ also be dynamically linked. ++ + # + # LAST -- dummy/emulated controller + # +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile +--- a/drivers/usb/gadget/udc/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/gadget/udc/Makefile 2018-05-10 11:31:33.753404129 +0800 +@@ -38,5 +38,6 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210 + obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o + obj-$(CONFIG_USB_GR_UDC) += gr_udc.o + obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o ++obj-$(CONFIG_USB_XGS_IPROC_UDC) += xgs_iproc_udc.o + obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o + obj-$(CONFIG_USB_BDC_UDC) += bdc/ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig +--- a/drivers/usb/gadget/udc/bdc/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/gadget/udc/bdc/Kconfig 2018-05-10 11:31:33.757404134 +0800 +@@ -16,7 +16,21 @@ comment "Platform Support" + config USB_BDC_PCI + tristate "BDC support for PCIe based platforms" + depends on USB_PCI +- default USB_BDC_UDC ++ default n + help + Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. ++ ++config USB_BDC_XGS_IPROC ++ tristate "BDC support for broadcom XGS IPROC platforms" ++ depends on ARCH_XGS_IPROC && USB_GADGET ++ default n ++ ++ help ++ Enable support for Broadcom XGS IPROC platforms which have BDC, such ++ as Helix 5 platform. ++ ++ Say "y" to link the driver statically, or "m" to build a dynamically ++ linked module called "xgs_iproc_udc" and force all gadget drivers to ++ also be dynamically linked. ++ + endif +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/bdc/Makefile b/drivers/usb/gadget/udc/bdc/Makefile +--- a/drivers/usb/gadget/udc/bdc/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/gadget/udc/bdc/Makefile 2018-05-10 11:31:33.757404134 +0800 +@@ -7,3 +7,5 @@ ifneq ($(CONFIG_USB_GADGET_VERBOSE),) + endif + + obj-$(CONFIG_USB_BDC_PCI) += bdc_pci.o ++obj-$(CONFIG_USB_BDC_XGS_IPROC) += bdc_xgs_iproc.o ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/bdc/bdc_xgs_iproc.c b/drivers/usb/gadget/udc/bdc/bdc_xgs_iproc.c +--- a/drivers/usb/gadget/udc/bdc/bdc_xgs_iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/gadget/udc/bdc/bdc_xgs_iproc.c 2018-05-10 11:31:33.761404138 +0800 +@@ -0,0 +1,126 @@ ++/* ++ * bdc_xgs_iproc.c - BDC platform driver for Broadco XGS IPROC platforms. ++ * ++ * Copyright (C) 2014-2016, Broadcom Corporation. All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bdc.h" ++ ++struct bdc_xgs_iproc { ++ struct device *dev; ++ struct platform_device *bdc; ++}; ++ ++static int bdc_xgs_iproc_probe(struct platform_device *pdev) ++{ ++ struct resource res[2]; ++ struct platform_device *bdc; ++ struct bdc_xgs_iproc *data; ++ struct device_node *np = pdev->dev.of_node; ++ int irq; ++ int ret = -ENOMEM; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) { ++ return -ENOMEM; ++ } ++ data->dev = &pdev->dev; ++ ++ bdc = platform_device_alloc(BRCM_BDC_NAME, PLATFORM_DEVID_AUTO); ++ if (!bdc) { ++ return -ENOMEM; ++ } ++ ++ memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); ++ ++ if (of_address_to_resource(np, 0, &res[0]) < 0) { ++ dev_err(&pdev->dev, ++ "failed to get BDC registers\n"); ++ of_node_put(np); ++ return -ENXIO; ++ } ++ res[0].name = BRCM_BDC_NAME; ++ res[0].flags = IORESOURCE_MEM; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, ++ "failed to get BDC IRQ\n"); ++ return -ENXIO; ++ } ++ res[1].start = irq; ++ res[1].name = BRCM_BDC_NAME; ++ res[1].flags = IORESOURCE_IRQ; ++ ++ ret = platform_device_add_resources(bdc, res, ARRAY_SIZE(res)); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "couldn't add resources to bdc device\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, data); ++ ++ dma_set_coherent_mask(&bdc->dev, pdev->dev.coherent_dma_mask); ++ bdc->dev.dma_mask = pdev->dev.dma_mask; ++ bdc->dev.dma_parms = pdev->dev.dma_parms; ++ bdc->dev.parent = &pdev->dev; ++ data->bdc = bdc; ++ ++ ret = platform_device_add(bdc); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register bdc device\n"); ++ platform_device_put(bdc); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bdc_xgs_iproc_remove(struct platform_device *pdev) ++{ ++ struct bdc_xgs_iproc *data = platform_get_drvdata(pdev); ++ ++ platform_device_unregister(data->bdc); ++ devm_kfree(&pdev->dev, data); ++ ++ return 0; ++} ++ ++static const struct of_device_id bdc_xgs_iproc_ids[] = { ++ { .compatible = "brcm,bdc,hx5", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bdc_xgs_iproc_ids); ++ ++static struct platform_driver bdc_xgs_iproc_driver = { ++ .probe = bdc_xgs_iproc_probe, ++ .remove = bdc_xgs_iproc_remove, ++ .driver = { ++ .name = "bdc-xgs-iproc", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(bdc_xgs_iproc_ids), ++ }, ++}; ++ ++module_platform_driver(bdc_xgs_iproc_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("BDC platform driver for Broadcom XGS IPROC platforms"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_iproc_udc.c b/drivers/usb/gadget/udc/xgs_iproc_udc.c +--- a/drivers/usb/gadget/udc/xgs_iproc_udc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/gadget/udc/xgs_iproc_udc.c 2018-05-10 11:31:33.789404169 +0800 +@@ -0,0 +1,2039 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 bcm_dwc_udc.c ++* ++* @brief Broadcom Linux driver for DWC USB 2.0 Device Controller (UDC) ++* ++* This driver implements the Linux Gadget driver API as defined in usb_gadget.h ++* ++* @note ++* ++* This driver was written with the intent of being able to support any ++* variations on how this block is integrated into different Broadcom chips. ++* ++* There is a requirement on how the DWC UDC is configured. In particular, this ++* driver requires that the following options be defined and enabled in the ++* UDC core. ++* ++* UDC20AHB_CNAK_CLR_ENH_CC ++* UDC20AHB_STALL_SET_ENH_CC ++* UDC20AHB_SNAK_ENH_CC ++* ++* Some other UDC attributes can be supported by setting compile time options ++* or with some minor modifications to the source code. Ideally these would ++* be run-time info that is provided by the device instance to the driver. ++* These attributes include the following. ++* ++* IPROC_UDC_EP_CNT ++* IPROC_UDC_EP_MAX_PKG_SIZE ++* Type of each endpoint: Control, IN, OUT, or Bidirectional ++*/ ++/****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xgs_iproc_udc.h" ++ ++#define XGS_IPROC_UDC_NAME "xgs-iproc-udc" ++ ++#define DMA_ADDR_INVALID (~(dma_addr_t)0) ++/* ++ * FRAME_NUM_INVALID is used for ISOC IN transfers for frame alignment. ++ * The device specifies the interval at which it wants to do transfers, ++ * but the host initiates all transfers. If the interval is some multiple ++ * number of frames, the device has no idea which frame in an interval ++ * window the host is going to start transfers. This could even be at a ++ * point many frames beyond the current window, as the starting point ++ * can be very application dependant and subject to an indeterminate ++ * amount of latency. ++ */ ++#define FRAME_NUM_INVALID (~(u32)0) ++#define ENOERROR 0 ++ ++/* ---- Private Function Prototypes -------------------------------------- */ ++#ifdef IPROC_UDC_DEBUG ++static void iproc_dbg_dma_dump(struct iproc_udc *udc); ++static void iproc_dbg_dma_dump_desc(char *label, struct iproc_udc_dma_desc *virt, ++ struct iproc_udc_dma_desc *phys); ++static void iproc_dbg_dma_dump_ep(struct iproc_ep *ep); ++#endif /* IPROC_UDC_DEBUG */ ++ ++/* ---- Private Variables ------------------------------------------------ */ ++static const struct { ++ const char *name; ++ const int type; ++ const int msize; ++ const struct usb_ep_caps caps; ++} xgs_iproc_ep_info[] = { ++#define EP_INFO(_name, _type, _size, _caps) \ ++ { \ ++ .name = _name, \ ++ .type = _type, \ ++ .msize = _size, \ ++ .caps = _caps, \ ++ } ++ ++ EP_INFO("ep0", USB_ENDPOINT_XFER_CONTROL, IPROC_UDC_CTRL_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), ++ EP_INFO("ep1in", USB_ENDPOINT_XFER_ISOC, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), ++ EP_INFO("ep2out", USB_ENDPOINT_XFER_ISOC, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), ++ EP_INFO("ep3in", USB_ENDPOINT_XFER_BULK, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), ++ EP_INFO("ep4out", USB_ENDPOINT_XFER_BULK, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), ++ EP_INFO("ep5in", USB_ENDPOINT_XFER_INT, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), ++ EP_INFO("ep6out", USB_ENDPOINT_XFER_INT, IPROC_UDC_EP_MAX_PKG_SIZE, ++ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)), ++#undef EP_INFO ++}; ++ ++/*********************************************************************** ++ * Convenience functions ++ ***********************************************************************/ ++static inline struct iproc_udc *gadget_to_udc(struct usb_gadget *g) ++{ ++ return container_of(g, struct iproc_udc, gadget); ++} ++ ++static inline struct iproc_ep *our_ep(struct usb_ep *ep) ++{ ++ return container_of(ep, struct iproc_ep, usb_ep); ++} ++ ++static inline struct iproc_ep_req *our_req(struct usb_request *req) ++{ ++ return container_of(req, struct iproc_ep_req, usb_req); ++} ++ ++/**************************************************************************** ++ * DMA descriptor chain routines. ++ * ++ * dma_desc_chain_reset - Initialize chain in preparation for transfer ++ * dma_desc_chain_full - Indicates if no descriptors in chain for available for use. ++ * dma_desc_chain_alloc - Get next free descriptor for use. Have to check if chain not full first. ++ * dma_desc_chain_empty - Indicates if no descriptors in the chain are being used. ++ * dma_desc_chain_head - Pointer to 1st entry in chain. Have to check if chain not empty first. ++ * dma_desc_chain_free - Frees up 1st entry for use. Only do this if DMA for this descriptor has completed. ++ * ++ ***************************************************************************/ ++static inline struct iproc_udc_dma_desc *dma_desc_chain_alloc(struct iproc_ep *ep) ++{ ++ u32 idx; ++ ++ idx = ep->dma.add_idx++; ++ ++ return &ep->dma.vir_addr->desc[IPROC_EP_DMA_DESC_IDX(idx)]; ++} ++ ++static inline int dma_desc_chain_empty(struct iproc_ep *ep) ++{ ++ return ep->dma.add_idx == ep->dma.rm_idx; ++} ++ ++static inline void dma_desc_chain_free(struct iproc_ep *ep) ++{ ++ ep->dma.rm_idx++; ++} ++ ++static inline int dma_desc_chain_full(struct iproc_ep *ep) ++{ ++ return (!dma_desc_chain_empty(ep) && (IPROC_EP_DMA_DESC_IDX(ep->dma.add_idx) == IPROC_EP_DMA_DESC_IDX(ep->dma.rm_idx))); ++} ++ ++static inline struct iproc_udc_dma_desc *dma_desc_chain_head(struct iproc_ep *ep) ++{ ++ return (&ep->dma.vir_addr->desc[IPROC_EP_DMA_DESC_IDX(ep->dma.rm_idx)]); ++} ++ ++static inline void dma_desc_chain_reset(struct iproc_ep *ep) ++{ ++ ep->dma.add_idx = 0; ++ ep->dma.rm_idx = 0; ++} ++ ++/**************************************************************************** ++ * ++ * Platform device level alloc / free of memory used for DMA descriptors. ++ * A single block of memory static in size is used for DMA descriptors. ++ * Each endpoint has a small number of descriptors for its exclusive use. ++ * These are chained in a loop. See bcm_udc_dwc.h and iproc_dma_ep_init() ++ * for more details. ++ * ++ ***************************************************************************/ ++static int iproc_platform_dma_alloc(struct platform_device *platformDevP, ++ struct iproc_udc *udc) ++{ ++ udc->dma.vir_addr = dma_alloc_coherent(&platformDevP->dev, ++ sizeof(struct iproc_udc_dma), ++ (dma_addr_t *)&udc->dma.phy_addr, GFP_KERNEL); ++ ++ if (!udc->dma.vir_addr) { ++ dev_err(udc->dev, "dma_alloc_coherent() failed\n"); ++ return -ENOMEM; ++ } ++ ++ return ENOERROR; ++} ++ ++static void iproc_platform_dma_free(struct platform_device *platformDevP, ++ struct iproc_udc *udc) ++{ ++ int idx; ++ ++ dma_free_coherent(&platformDevP->dev, sizeof(struct iproc_udc_dma), ++ udc->dma.vir_addr, (dma_addr_t)udc->dma.phy_addr); ++ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx ++) { ++ if (udc->ep[idx].dma.align_buff) { ++ dma_free_coherent(NULL, udc->ep[idx].dma.align_len, ++ udc->ep[idx].dma.align_buff, ++ udc->ep[idx].dma.align_addr); ++ udc->ep[idx].dma.align_buff = NULL; ++ } ++ } ++} ++ ++/*************************************************************************** ++ * Routines for debug dump of DMA descriptors ++ **************************************************************************/ ++#ifdef IPROC_UDC_DEBUG ++static void iproc_dbg_dma_dump(struct iproc_udc *udc) ++{ ++ int idx; ++ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) ++ iproc_dbg_dma_dump_ep(&udc->ep[idx]); ++} ++ ++static void iproc_dbg_dma_dump_desc(char *label, struct iproc_udc_dma_desc *virt, ++ struct iproc_udc_dma_desc *phys) ++{ ++ printk("%s virt=0x%p phys=0x%p: 0x%08x 0x%08x 0x%08x", ++ label, virt, phys, virt->status, virt->reserved, virt->buf_addr); ++} ++ ++static void iproc_dbg_dma_dump_ep(struct iproc_ep *ep) ++{ ++ int idx; ++ ++ printk("EP %d DMA\n", ep->num); ++ printk(" setup\n"); ++ iproc_dbg_dma_dump_desc(" ", ++ (struct iproc_udc_dma_desc *)&ep->dma.vir_addr->setup, ++ (struct iproc_udc_dma_desc *)&ep->dma.phy_addr->setup); ++ printk(" desc\n"); ++ ++ for (idx = 0; idx < IPROC_EP_DMA_DESC_CNT; idx++) { ++ iproc_dbg_dma_dump_desc(" ", &ep->dma.vir_addr->desc[idx], ++ &ep->dma.phy_addr->desc[idx]); ++ ++ /* Don't bother displaying entries beyond the last. */ ++ if (IPROC_USBD_READ(ep->dma.vir_addr->desc[idx].status) & ++ REG_DMA_STAT_LAST_DESC) ++ break; ++ } ++} ++#endif /* IPROC_UDC_DEBUG */ ++ ++/**************************************************************************** ++ * Initialization of DMA descriptors at the endpoint level. ++ ***************************************************************************/ ++static void iproc_dma_ep_init(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ int idx; ++ ++ /** @todo shorten names to virtAddr physAddr?? */ ++ ep->dma.vir_addr = &udc->dma.vir_addr->ep[ep->num]; ++ ep->dma.phy_addr = &udc->dma.phy_addr->ep[ep->num]; ++ ++ /* ++ * Control endpoints only do setup in the OUT direction, so only need to set the ++ * buffer address for that direction. The buffer is set, even if not a control ++ * endpoint, just to simplify things. There's no harm with this. ++ */ ++ ep->dma.vir_addr->setup.status = cpu_to_le32(REG_DMA_STAT_BUF_HOST_BUSY); ++ wmb(); ++ iproc_usbd_ep_dma_buf_addr_set(udc->usbd_regs, ep->num, USB_DIR_OUT, &ep->dma.phy_addr->setup); ++ ++ /* ++ * Take ownership of the DMA descriptors, and chain them in a loop. This allows a small number ++ * descriptors to be used for requests. Need to have the DWC DMA Descriptor Update option enabled ++ * in the device control register in order to do this. When a transfer for a descriptor completes, ++ * the descriptor will get re-used if there's still data left in a request to transfer. See the ++ * iproc_dma_data_rm_done() and iproc_dma_data_add_ready() routines. ++ */ ++ /** @todo Put these in endpoint context?? */ ++ for (idx = 0; idx < IPROC_EP_DMA_DESC_CNT; idx++) { ++ ep->dma.vir_addr->desc[idx].status = ++ cpu_to_le32(REG_DMA_STAT_BUF_HOST_BUSY); ++ wmb(); ++ ep->dma.vir_addr->desc[idx].next_addr = ++ cpu_to_le32((u32)&ep->dma.phy_addr->desc[idx+1]); ++ } ++ ep->dma.vir_addr->desc[(IPROC_EP_DMA_DESC_CNT - 1)].next_addr = ++ cpu_to_le32((u32)&ep->dma.phy_addr->desc[0]); ++ ++ /* ++ * To simplify things, register the descriptor chain in both directions. Control endpoints are the ++ * only type that will be transferring in both directions, but they will only be transferring in one ++ * direction at a time, so should not be any issues with using the same descriptor set for both directions. ++ * For single direction endpoints, the other direction will not be used. ++ */ ++ ++ iproc_usbd_ep_dma_desc_addr_set(udc->usbd_regs, ep->num, USB_DIR_OUT, ++ &ep->dma.phy_addr->desc[0]); ++ iproc_usbd_ep_dma_desc_addr_set(udc->usbd_regs, ep->num, USB_DIR_IN, ++ &ep->dma.phy_addr->desc[0]); ++} ++ ++/**************************************************************************** ++ * DMA data routines. ++ * ++ * A gadget usb_request buf is used for the data. The entire buf contents may ++ * or may not fit into the descriptor chain at once. When the DMA transfer ++ * associated with a descriptor completes, the descriptor is re-used to add ++ * more segments of the usb_request to the chain as necessary. ++ * ++ * iproc_dma_data_init - Initialization in preparation for DMA of usb_request. ++ * iproc_dma_data_add_ready - Adds usb_request segments into DMA chain until full or no segments left ++ * iproc_dma_data_rm_done - Removes usb_request segments from DMA chain that have completed transfer ++ * iproc_dma_data_finish - Final stage of DMA of the usb_request ++ * ++ ***************************************************************************/ ++static void iproc_dma_data_init(struct iproc_ep *ep) ++{ ++ struct iproc_ep_req *req; ++ struct iproc_udc *udc = ep->udc; ++ ++ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); ++ ++ if (req->dma_aligned) { ++ /* ++ * This buffer needs to be aligned in order to DMA. We do this by copying into a special buffer we ++ * have for this purpose. Save the original DMA physical address so it can be restored later. ++ * This may not be used, but we'll do it anyways. Then set the DMA address to the aligned buffer ++ * address. Only the DMA physical address is used for the transfers, so the original buffer virtual ++ * address does not need to be changed. Then copy the data into the aligned buffer. ++ */ ++ /** @todo Really only need to do the memcpy for IN data */ ++ ++ req->orig_dma_addr = req->usb_req.dma; ++ req->usb_req.dma = ep->dma.align_addr; ++ memcpy(ep->dma.align_buff, req->usb_req.buf, req->usb_req.length); ++ } ++ ++ ep->dma.done = 0; ++ ep->dma.done_len = 0; ++ ep->dma.todo_len = ep->dma.usb_req->length; ++ ep->dma.buf_addr = ep->dma.usb_req->dma; ++ ep->dma.status = REG_DMA_STAT_RX_SUCCESS; ++ ++ if ((ep->dir == USB_DIR_IN) && (ep->type != USB_ENDPOINT_XFER_ISOC)) { ++ /* ++ * For IN transfers, do not need to segment the buffer into max packet portions ++ * for the DMA descriptors. The hardware will automatically segment into max ++ * packet sizes as necessary. ++ */ ++ ep->dma.max_buf_len = ep->usb_ep.maxpacket; ++ ++ /* ++ * If the request is of zero length, then force the zero flag so iproc_dma_data_add_ready() ++ * will queue the request. Conversely, if the gadget has set the zero flag, leave ++ * it set only if it is needed (request length is a multiple of maxpacket) ++ */ ++ if (ep->dma.usb_req->length == 0) ++ ep->dma.usb_req->zero = 1; ++ else if (ep->dma.usb_req->zero) ++ ep->dma.usb_req->zero = ++ (ep->dma.usb_req->length % ep->usb_ep.maxpacket)? 0 : 1; ++ } else { ++ ep->dma.max_buf_len = ep->usb_ep.maxpacket; ++ } ++ ++ dma_desc_chain_reset(ep); ++ ++ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, ep->dir); ++} ++ ++static void iproc_dma_data_finish(struct iproc_ep *ep) ++{ ++ struct iproc_ep_req *req; ++ struct iproc_udc *udc = ep->udc; ++ ++ iproc_usbd_ep_irq_dis(udc->usbd_regs, ep->num, ep->dir); ++ iproc_usbd_ep_dma_dis(udc->usbd_regs, ep->num, ep->dir); ++ ++ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); ++ ++ if (req->dma_aligned) { ++ /* ++ * The original request buffer was not aligned properly, so a special buffer was used ++ * for the transfer. Copy the aligned buffer contents into the original. Also restore ++ * the original dma physical address. ++ */ ++ /** @todo Really only need to do the memcpy for OUT setup/data */ ++ memcpy(req->usb_req.buf, ep->dma.align_buff, req->usb_req.length); ++ req->usb_req.dma = req->orig_dma_addr; ++ } ++} ++ ++static void iproc_dma_data_add_ready(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ volatile struct iproc_udc_dma_desc *dma_desc = NULL; ++ u32 status; ++ u32 len; ++ int enable_dma = 0; ++ ++ /* ++ * DMA must be disabled while this loop is running, as multi-descriptor transfers ++ * will have the descriptor chain in an intermediate state until the last descriptor ++ * is written and the chain terminated. ++ */ ++ if (iproc_usbd_dma_status(udc->usbd_regs)) { ++ enable_dma = 1; ++ iproc_usbd_dma_dis(udc->usbd_regs); ++ } ++ ++ if (!ep->dma.todo_len) ++ ep->dma.usb_req->zero = 1; ++ ++ /* ++ * Will only have one request in the chain at a time. Add request segments to the ++ * chain until all parts of the request have been put in the chain or the chain ++ * has no more room. ++ */ ++ while (!dma_desc_chain_full(ep) && (ep->dma.todo_len || ep->dma.usb_req->zero)) { ++ /* ++ * Get the next descriptor in the chain, and then fill the descriptor contents as needed. ++ * Do not set the descriptor buffer status to ready until last to ensure there's no ++ * contention with the hardware. ++ */ ++ dma_desc = dma_desc_chain_alloc(ep); ++ ++ len = ep->dma.todo_len < ep->dma.max_buf_len ? ep->dma.todo_len : ep->dma.max_buf_len; ++ ep->dma.todo_len -= len; ++ ++ status = 0; ++ ++ if (len < ep->dma.max_buf_len) { ++ /* ++ * If this segment is less than the max, then it is the last segment. There's no need to ++ * send a closing ZLP, although this segment might be a ZLP. Regardless, clear the ZLP flag ++ * to ensure that the processing of this request finishes. Also set the end of the descriptor ++ * chain. ++ */ ++ ep->dma.usb_req->zero = 0; ++ status |= REG_DMA_STAT_LAST_DESC; ++ } else if ((ep->dma.todo_len == 0) && !ep->dma.usb_req->zero) { ++ /* ++ * Segment is of the max packet length. Since there's nothing left, it has to also be the last ++ * last segment. No closing ZLP segment requested, just set the end of the descriptor chain. ++ */ ++ status |= REG_DMA_STAT_LAST_DESC; ++ } ++ ++ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)) { ++ /* ++ * Increment the frame number for transmit, then use it for the next packet. The frame number ++ * may get larger than its 13-bit size, but the mask will handle the wrap-around so we don't ++ * need to add checks for this condition. E.g. 0x7ff + 1 = 0x800. 0x800 & 0x7ff = 0 which ++ * is the next number in the sequence. ++ */ ++ /** @todo Handle ISOC PIDs and frame numbers used with HS high bandwidth transfers */ ++ /** @todo Might not need to set the last descriptor status. Currently restricting ++ * IN ISOC transfers to the max packet size. ++ */ ++ status |= REG_DMA_STAT_LAST_DESC; ++ ++ ep->dma.frame_num += ep->dma.frame_incr; ++ status |= ((ep->dma.frame_num << REG_DMA_STAT_FRAME_NUM_SHIFT) & ++ REG_DMA_STAT_FRAME_NUM_MASK); ++ } ++ ++ IPROC_USBD_WRITE(dma_desc->buf_addr, ep->dma.buf_addr); ++ status |= (len << REG_DMA_STAT_BYTE_CNT_SHIFT); ++ IPROC_USBD_WRITE(dma_desc->status, status | REG_DMA_STAT_BUF_HOST_READY); ++ wmb(); ++ ep->dma.buf_addr += len; ++ ++ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)) { ++ /* With ISOC transfers, only enable one DMA descriptors at a time. ++ */ ++ /** @todo Determine if FIFO will overflow. If it does not, then can remove this check. ++ * This may not even be an issue if the buffer size is restricted to the max packet size ++ * when a request is submitted to the endpoint. ++ */ ++ break; ++ } ++ } /* while */ ++ ++ /* Set LAST bit on last descriptor we've configured */ ++ if (dma_desc) ++ IPROC_USBD_BITS_SET(dma_desc->status, REG_DMA_STAT_LAST_DESC); ++ ++ if (enable_dma) ++ iproc_usbd_dma_en(udc->usbd_regs); ++} ++ ++static void iproc_dma_data_rm_done(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ volatile struct iproc_udc_dma_desc *dma_desc; ++ u32 status; ++ u32 len; ++ ++ /* ++ * Will only have one request in the chain at a time. Remove any completed ++ * request segments from the chain so any segments awaiting transfer can ++ * be put in the chain. ++ */ ++ while (!dma_desc_chain_empty(ep)) { ++ /* ++ * Examine the first entry in the chain. If its status is not done, then there's ++ * nothing to remove. ++ */ ++ dma_desc = dma_desc_chain_head(ep); ++ ++ if ((IPROC_USBD_READ(dma_desc->status) & REG_DMA_STAT_BUF_MASK) != ++ REG_DMA_STAT_BUF_DMA_DONE) ++ break; ++ ++ /* ++ * The transfer of this request segment has completed. Save the status info and then ++ * take ownership of the descriptor. It is simpler to do this than modifying parts of ++ * the descriptor in order to take ownership. Don't put the descriptor back in the chain ++ * until all info affected by the status has been updated, just to be safe. ++ */ ++ status = IPROC_USBD_READ(dma_desc->status); ++ IPROC_USBD_WRITE(dma_desc->status, REG_DMA_STAT_BUF_HOST_BUSY); ++ wmb(); ++ ++ len = (status & REG_DMA_STAT_NON_ISO_BYTE_CNT_MASK) >> ++ REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT; ++ ++ /* RX: For multiple descriptors, len is cumulative, not absolute. ++ * RX: So only adjust the dma fields when we get to the last descriptor ++ * TX: Each descriptor entry is absolute, count them all ++ */ ++ if ((ep->dir == USB_DIR_IN) || (status & REG_DMA_STAT_LAST_DESC)) { ++ ep->dma.done_len += len; ++ ep->dma.usb_req->actual += len; ++ } ++ ++ if ((status & REG_DMA_STAT_RX_MASK) != REG_DMA_STAT_RX_SUCCESS) { ++ ep->dma.status = status & REG_DMA_STAT_RX_MASK; ++ ep->dma.usb_req->status = -EIO; ++ dev_warn(udc->dev, "%s: DMA error: desc=0x%p status=0x%x len=%d add=0x%x remove=0x%x\n", ++ ep->usb_ep.name, dma_desc, status, len, ep->dma.add_idx, ep->dma.rm_idx); ++ } ++ ++ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)){ ++ /** @todo Determine if this special processing needs to be done. May not to do this if the ++ * buffer size is restricted to the max packet size when a request is submitted to the endpoint. ++ */ ++ if (ep->dma.usb_req->actual == ep->dma.usb_req->length) ++ ep->dma.usb_req->status = ENOERROR; ++ dma_desc_chain_reset(ep); ++ } else { ++ dma_desc_chain_free(ep); ++ } ++ } ++ ++ /* When last segment processed, update status if there has not been an error */ ++ if (!ep->dma.todo_len && (ep->dma.usb_req->status == -EINPROGRESS)) ++ ep->dma.usb_req->status = ENOERROR; ++} ++ ++/**************************************************************************** ++ * Control Endpoint SETUP related routines. ++ * ++ * iproc_ep_setup_init - Prepares for next SETUP Rx. Status indicates if STALL req'd. ++ * iproc_ep_setup_process - Handle Rx of a SETUP. ++ ***************************************************************************/ ++static void iproc_ep_setup_init(struct iproc_ep *ep, int status) ++{ ++ struct iproc_udc *udc = ep->udc; ++ ++ /* Re-enable transfers to the SETUP buffer, clear IN and OUT NAKs, and re-enable OUT interrupts. */ ++ ep->dma.vir_addr->setup.status = cpu_to_le32(REG_DMA_STAT_BUF_HOST_READY); ++ ep->dir = USB_DIR_OUT; ++ ep->stopped = 0; ++ ++ if (status == ENOERROR) { ++ /* Handling of previous SETUP was OK. Just clear any NAKs. */ ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_OUT); ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_IN); ++ } else { ++ /* ++ * Handling of previous SETUP failed. Set the STALL. This will get cleared ++ * when the next SETUP is rx'd. ++ */ ++ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_IN); ++ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_OUT); ++ } ++ ++ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, USB_DIR_OUT); ++ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, USB_DIR_OUT); ++} ++ ++void iproc_ep_setup_process(struct iproc_ep *ep, struct usb_ctrlrequest *setup) ++{ ++ struct iproc_udc *udc = ep->udc; ++ u32 value; ++ u32 index; ++ u32 length; ++ int status; ++ ++ value = le16_to_cpu(setup->wValue); ++ index = le16_to_cpu(setup->wIndex); ++ length = le16_to_cpu(setup->wLength); ++ ++ /* ++ * Any SETUP packets appearing here need to be handled by the gadget driver. Some SETUPs may have ++ * already been silently handled and acknowledged by the DWC UDC. The exceptions to this rule are the ++ * USB_REQ_SET_CONFIGURATION and USB_REQ_SET_INTERFACE, which have been only partially handled with ++ * the expectation that some additional software processing is required in order to complete these requests. ++ * Thus, they have not been acknowledged by the DWC UDC. There is no DATA stage for these requests. ++ */ ++ ++ /* ++ * Set the direction of the subsequent DATA stage of a control transfer. This is an ++ * optional stage. It may not exist for all control transfers. If there is a DATA ++ * stage, this info is used for DMA operations for any requests received from the ++ * Gadget driver. ++ */ ++ ++ ep->dir = setup->bRequestType & USB_ENDPOINT_DIR_MASK; ++ ++ if (ep->num != 0) { ++ /** @todo Make changes here if the Linux USB gadget ever supports a control endpoint other ++ * than endpoint 0. The DWC UDC supports multiple control endpoints, and this driver has ++ * been written with this in mind. To make things work, really need to change the Gadget ++ * setup() callback parameters to provide an endpoint context, or add something similar ++ * to the usb_ep structure, or possibly use a usb_request to hold a setup data packet. ++ */ ++ dev_err(udc->dev, "%s: control transfer not supported\n", ep->usb_ep.name); ++ status = -EOPNOTSUPP; ++ } else { ++ /* ++ * Forward the SETUP to the gadget driver for processing. The appropriate directional ++ * interrupt and NAK clear will happen when the DATA stage request is queued. ++ */ ++ spin_unlock(&udc->lock); ++ status = udc->gadget_driver->setup(&udc->gadget, setup); ++ spin_lock(&udc->lock); ++ } ++ ++ if (status < 0) { ++ /* ++ * Error occurred during the processing of the SETUP, so enable STALL. This condition ++ * can only be cleared with the RX of another SETUP, so prepare for that event. ++ */ ++ dev_err(udc->dev, "%s: SETUP %02x.%02x STALL; status=%d\n", ++ ep->usb_ep.name, setup->bRequestType, setup->bRequest, status); ++ ++ iproc_ep_setup_init(ep, status); ++ } else if (length == 0) { ++ /* No DATA stage. Just need to prepare for the next SETUP. */ ++ iproc_ep_setup_init(ep, ENOERROR); ++ } else { ++ /* ++ * The SETUP stage processing has completed OK, and there may or may not be a request queued ++ * for the DATA stage. When the DATA stage completes, preparation for the RX of the next ++ * SETUP will be done. ++ */ ++ } ++} ++ ++static void iproc_udc_req_xfer_done(struct iproc_ep *ep, struct iproc_ep_req *req, int status) ++{ ++ struct iproc_udc *udc = ep->udc; ++ u32 stopped; ++ ++ list_del_init(&req->list_node); ++ ++ if (req->usb_req.status == -EINPROGRESS) ++ req->usb_req.status = status; ++ ++ if (req->dma_aligned) { ++ req->dma_aligned = 0; ++ } else if (req->dma_mapped) { ++ /* ++ * A physical address was not provided for the DMA buffer. Release any resources ++ * that were requested by the driver. ++ */ ++ dma_unmap_single(udc->gadget.dev.parent, req->usb_req.dma, req->usb_req.length, ++ (ep->dir == USB_DIR_IN ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); ++ ++ req->dma_mapped = 0; ++ req->usb_req.dma = DMA_ADDR_INVALID; ++ } ++ ++ /* ++ * Disable DMA operations during completion callback. The callback may cause requests to be ++ * added to the queue, but we don't want to change the state of the queue head. ++ */ ++ stopped = ep->stopped; ++ ep->stopped = 1; ++ spin_unlock(&udc->lock); ++ req->usb_req.complete(&ep->usb_ep, &req->usb_req); ++ spin_lock(&udc->lock); ++ ep->stopped = stopped; ++} ++ ++static void iproc_udc_req_xfer_process(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ struct iproc_ep_req *req; ++ ++ /* @todo Current transfer is always the queue head. ++ * Do we need a separate pointer? Maybe just a pointer to usb_request ++ */ ++ if (!ep->dma.usb_req) { ++ dev_err(udc->dev, "%s: No request being transferred\n", ep->usb_ep.name); ++ return; ++ } ++ ++ iproc_usbd_ep_dma_dis(udc->usbd_regs, ep->num, ep->dir); ++ iproc_dma_data_rm_done(ep); ++ ++ if (ep->dma.usb_req->status != -EINPROGRESS) { ++ /* ++ * Current transfer stage has finished. This may or may not be with error. ++ * Complete the transfer as needed before starting the next one, if any. ++ */ ++ iproc_dma_data_finish(ep); ++ ++ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && (ep->dir == USB_DIR_IN) ++ && (ep->dma.usb_req->status == ENOERROR)) { ++ /* ++ * For the status phase of control IN transfers, the hardware requires that an OUT DMA transfer ++ * actually takes place. This should be just an OUT ZLP, and we will re-use the IN buffer that ++ * just completed transfer for this purpose. There should be no harm in doing this, even if the ++ * OUT status is more than a ZLP. ++ */ ++ ep->dir = USB_DIR_OUT; ++ iproc_dma_data_init(ep); ++ } else { ++ /* ++ * All transfer stages have completed. Return the request to the gadget driver, and then ++ * setup for the next transfer. ++ */ ++ iproc_udc_req_xfer_done(ep, list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node), ENOERROR); ++ ++ if (ep->type == USB_ENDPOINT_XFER_CONTROL) ++ iproc_ep_setup_init(ep, ENOERROR); ++ ++ if (list_empty(&ep->list_queue)) { ++ /** @todo Probably should more closely bind this to iproc_dma_data_finish. */ ++ ep->dma.usb_req = NULL; ++ } else { ++ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); ++ ep->dma.usb_req = &req->usb_req; ++ iproc_dma_data_init(ep); ++ } ++ } ++ } ++ ++ if (ep->dma.usb_req != NULL) { ++ iproc_dma_data_add_ready(ep); ++ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, ep->dir); ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); ++ } ++} ++ ++static void iproc_udc_req_xfer_error(struct iproc_ep *ep, int status) ++{ ++ struct iproc_udc *udc = ep->udc; ++ ++ if (!ep->dma.usb_req) { ++ dev_err(udc->dev, "%s: No request being transferred\n", ep->usb_ep.name); ++ return; ++ } ++ ++ /** @todo abort current DMA, start next transfer if there is one. */ ++ ep->dma.usb_req->status = status; ++ iproc_udc_req_xfer_process(ep); ++} ++ ++static void iproc_udc_ops_disconnect(struct iproc_udc *udc) ++{ ++ struct iproc_ep *ep; ++ int idx; ++ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { ++ ep = &udc->ep[idx]; ++ ++ if (ep->dma.usb_req) { ++ /* Flush DMA, reqeust still pending */ ++ iproc_usbd_ep_fifo_flush_en(udc->usbd_regs, 0, USB_DIR_IN); ++ iproc_usbd_ep_fifo_flush_dis(udc->usbd_regs, 0, USB_DIR_IN); ++ ++ iproc_udc_req_xfer_process(ep); ++ } ++ } ++} ++ ++static void iproc_udc_ops_shutdown(struct iproc_udc *udc) ++{ ++ struct iproc_ep *ep; ++ ++ udc->ep[0].desc = NULL; ++ list_for_each_entry(ep, &udc->gadget.ep_list, usb_ep.ep_list) ++ ep->desc = NULL; ++ ++ udc->gadget.dev.driver = NULL; ++ udc->gadget_driver = NULL; ++} ++ ++/**************************************************************************** ++ * IRQ routines. ++ * ++ * xgs_iproc_udc_isr - top level entry point. ++ * iproc_cfg_isr - device (endpoint 0) set config interrupt handler ++ * iproc_inf_isr - device (endpoint 0) set interface interrupt handler ++ * iproc_speed_isr - device speed enumeration done interrupt handler ++ * iproc_ep_in_isr - top level IN endpoint related interrupt handler ++ * iproc_ep_out_isr - top level OUT endpoint related interrupt handler ++ * iproc_ep_out_setup_isr - Control endpoint SETUP Rx handler. This may get ++ * called directly as the result of an endpoint OUT interrupt, or ++ * indirectly as the result of device SET_CFG or SET_INTF. ++ ***************************************************************************/ ++static void iproc_cfg_isr(struct iproc_udc *udc) ++{ ++ struct usb_ctrlrequest setup; ++ int idx; ++ u16 cfg; ++ ++ /* ++ * Device Configuration SETUP has been received. This is not placed in the SETUP ++ * DMA buffer. The packet has to be re-created here so it can be forwarded to the ++ * gadget driver to act upon. ++ */ ++ ++ cfg = (u16) iproc_usbd_cfg_num(udc->usbd_regs); ++ ++ setup.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; ++ setup.bRequest = USB_REQ_SET_CONFIGURATION; ++ setup.wValue = cpu_to_le16(cfg); ++ setup.wIndex = 0; ++ setup.wLength = 0; ++ ++ /* ++ * Setting the configuration number before the gadget responds is a bit presumptious, but should ++ * not be fatal. ++ */ ++ /** @todo Do not set endpoint 0? Or is it a don't care? */ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) ++ iproc_usbd_ep_cfg_set(udc->usbd_regs, idx, cfg); ++ ++ printk(KERN_INFO "SET CFG=%d\n", cfg); ++ ++ iproc_ep_setup_process(&udc->ep[0], &setup); ++ iproc_usbd_setup_done(udc->usbd_regs); ++} ++ ++static void iproc_inf_isr(struct iproc_udc *udc) ++{ ++ struct usb_ctrlrequest setup; ++ u32 idx; ++ u16 intf; ++ u16 alt; ++ ++ /* ++ * Device Interface SETUP has been received. This is not placed in the SETUP ++ * DMA buffer. The packet has to be re-created here so it can be forwarded to the ++ * gadget driver to act upon. ++ */ ++ intf = (u16)iproc_usbd_intf_num(udc->usbd_regs); ++ alt = (u16)iproc_usbd_alt_num(udc->usbd_regs); ++ ++ setup.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE; ++ setup.bRequest = USB_REQ_SET_INTERFACE; ++ setup.wValue = cpu_to_le16(alt); ++ setup.wIndex = cpu_to_le16(intf); ++ setup.wLength = 0; ++ ++ /* ++ * Setting the interface numbers before the gadget responds is a bit ++ * presumptious, but should not be fatal. ++ */ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { ++ iproc_usbd_ep_alt_set(udc->usbd_regs, idx, alt); ++ iproc_usbd_ep_intf_set(udc->usbd_regs, idx, intf); ++ } ++ ++ iproc_ep_setup_process(&udc->ep[0], &setup); ++ iproc_usbd_setup_done(udc->usbd_regs); ++} ++ ++static void iproc_speed_isr(struct iproc_udc *udc) ++{ ++ u32 speed; ++ ++ speed = udc->gadget.speed; ++ ++ switch(iproc_usbd_speed_get(udc->usbd_regs)) { ++ case USB_SPEED_HIGH: ++ printk(KERN_INFO "HIGH SPEED\n"); ++ udc->gadget.speed = USB_SPEED_HIGH; ++ break; ++ case USB_SPEED_FULL: ++ printk(KERN_INFO "FULL SPEED\n"); ++ udc->gadget.speed = USB_SPEED_FULL; ++ break; ++ case USB_SPEED_LOW: ++ dev_warn(udc->dev, "low speed not supported\n"); ++ udc->gadget.speed = USB_SPEED_LOW; ++ break; ++ default: ++ dev_err(udc->dev, "unknown speed=0x%x\n", iproc_usbd_speed_get(udc->usbd_regs)); ++ break; ++ } ++ ++ if ((speed == USB_SPEED_UNKNOWN) && (udc->gadget.speed != USB_SPEED_UNKNOWN)) { ++ /* ++ * Speed has not been enumerated before, so now we can initialize transfers on endpoint 0. ++ * Also have to disable the NAKs at a global level, which has been in place while waiting ++ * for enumeration to complete. ++ */ ++ iproc_ep_setup_init(&udc->ep[0], ENOERROR); ++ iproc_usbd_nak_response_dis(udc->usbd_regs); ++ } ++} ++ ++static void iproc_ep_in_isr(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ u32 status; ++ ++ status = iproc_usbd_ep_stat_active(udc->usbd_regs, ep->num, USB_DIR_IN); ++ iproc_usbd_ep_stat_clear(udc->usbd_regs, ep->num, USB_DIR_IN, status); ++ ++ if (!status) ++ return; ++ ++ /** @todo check might only be for direction... */ ++ if ((ep->dir != USB_DIR_IN) && (ep->type != USB_ENDPOINT_XFER_CONTROL)) { ++ dev_err(udc->dev, "%s: unexpected IN interrupt\n", ep->usb_ep.name); ++ return; ++ } ++ ++ if (ep->dir != USB_DIR_IN) ++ /* This probably should not be happening */ ++ dev_warn(udc->dev, "%s: CTRL dir OUT\n", ep->usb_ep.name); ++ ++ if ((ep->type == USB_ENDPOINT_XFER_ISOC) && ++ (status & (USBD_EP_STAT_IN_XFER_DONE | USBD_EP_STAT_DMA_BUF_UNAVAIL))) ++ dev_warn(udc->dev, "%s: ISOC IN unexpected status=0x%x\n", ep->usb_ep.name, status); ++ ++ if (status & USBD_EP_STAT_IN_TOKEN_RX) { ++ /* ++ * If there's any IN requests, the DMA should be setup and ready to go if ++ * the endpoint is not an ISOC. Nothing to do in this case. However, if ++ * this is an ISOC endpoint, then this interrupt implies there was no ++ * data available for this frame number. This will happen if the gadget ++ * does not have any data queued to send in this frame, or we have been ++ * waiting for this event to occur so we can get alignment with the host ++ * for the interval. This alignment is necessary when the interval is ++ * greater than one frame / uframe. E.g. for an audio stream sending ++ * samples @ 5ms intervals on a FS link, this corresponds to a period ++ * of 5 frames. Samples with be queued for every 5th frame number after ++ * the frame number in which this interrupt occurred. ++ */ ++ status &= ~USBD_EP_STAT_IN_TOKEN_RX; ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_IN); ++ ++ if ((ep->type == USB_ENDPOINT_XFER_ISOC)) { ++ /* Always align to the current frame number for subsequent transfers. */ ++ ep->dma.frame_num = iproc_usbd_last_rx_frame_num(udc->usbd_regs); ++ if (ep->dma.usb_req != NULL) { ++ /* ++ * Might have something queued when waiting for alignment. If something is queued, ++ * it is already too late for the current transfer point. It will also have been ++ * placed in the queue at some point before this interrupt, and it will be stale ++ * if we try to transmit at the next transfer point. ++ */ ++ ep->dma.usb_req->status = -EREMOTEIO; ++ iproc_udc_req_xfer_process(ep); ++ } ++ } ++ } ++ ++ if (status & USBD_EP_STAT_IN_DMA_DONE) { ++ /* ++ * DMA has completed, but cannot start next transfer until USBD_EP_STAT_IN_XFER_DONE. ++ * To avoid race conditions and other issues, do not release the current transfer until both ++ * interrupts have arrived. Normally this interrupt will arrive at or before the IN_XFER_DONE, ++ * but there have been situations when the system is under load that this interrupt might ++ * arrive after the IN_XFER_DONE, in which case we will need to do the processing now. ++ * The exception to this rule is for ISOC endpoints. They will only get this interrupt to ++ * indicate that DMA has completed. ++ */ ++ status &= ~USBD_EP_STAT_IN_DMA_DONE; ++ ++ if ((ep->type == USB_ENDPOINT_XFER_ISOC)) { ++ iproc_udc_req_xfer_process(ep); ++ } else if (ep->dma.done & USBD_EP_STAT_IN_XFER_DONE) { ++ /* ++ * Did not receive the IN_DMA_DONE interrupt for this request before or ++ * at the same time as the IN_XFER_DONE interrupt, so the request ++ * processing was postponed until the IN_DMA_DONE interrupt arrived. ++ * See handling of IN_XFER_DONE status below. ++ */ ++ iproc_udc_req_xfer_process(ep); ++ } else { ++ /* ++ * IN_DMA_DONE received. Save this info so request processing will be ++ * done when the IN_XFER_DONE interrupt is received. This may happen ++ * immediately, idx.e. both IN_DMA_DONE and IN_XFER_DONE status are ++ * set when the interrupt processing takes place. ++ */ ++ ep->dma.done = USBD_EP_STAT_IN_DMA_DONE; ++ } ++ } ++ ++ if (status & USBD_EP_STAT_IN_XFER_DONE) { ++ status &= ~(USBD_EP_STAT_IN_XFER_DONE); ++ status &= ~(USBD_EP_STAT_IN_FIFO_EMPTY); ++ ++ if (ep->dma.done & USBD_EP_STAT_IN_DMA_DONE) { ++ /* ++ * Have received both the IN_DMA_DONE and IN_XFER_DONE interrupts ++ * for this request. OK to process the request (remove the request ++ * and start the next one). ++ */ ++ iproc_udc_req_xfer_process(ep); ++ } else { ++ /* ++ * Have not received the IN_DMA_DONE interrupt for this request. ++ * Need to postpone processing of the request until the IN_DMA_DONE ++ * interrupt occurs. See handling of IN_DMA_DONE status above. ++ */ ++ ep->dma.done = USBD_EP_STAT_IN_XFER_DONE; ++ } ++ } ++ ++ /* Clear the FIFO EMPTY bit, not to print error message */ ++ status &= ~(USBD_EP_STAT_IN_FIFO_EMPTY); ++ ++ if (status & USBD_EP_STAT_DMA_BUF_UNAVAIL) { ++ dev_err(udc->dev, "%s: DMA BUF NOT AVAIL\n", ep->usb_ep.name); ++ status &= ~(USBD_EP_STAT_DMA_BUF_UNAVAIL); ++ iproc_udc_req_xfer_process(ep); ++ } ++ ++ if (status & USBD_EP_STAT_DMA_ERROR) { ++ status &= ~USBD_EP_STAT_DMA_ERROR; ++ dev_err(udc->dev, "%s: DMA ERROR\n", ep->usb_ep.name); ++ iproc_udc_req_xfer_error(ep, -EIO); ++ } ++ ++ if (status) ++ dev_err(udc->dev, "exit: %s %s: unknown status=0x%x\n", ++ __func__, ep->usb_ep.name, status); ++} ++ ++static void iproc_ep_out_setup_isr(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ struct iproc_udc_dma_setup *dma; ++ ++ dma = &ep->dma.vir_addr->setup; ++ if ((IPROC_USBD_READ(dma->status) & REG_DMA_STAT_BUF_MASK) != ++ REG_DMA_STAT_BUF_DMA_DONE) { ++ dev_err(udc->dev, "%s: unexpected DMA buf status=0x%x\n", ep->usb_ep.name, ++ (IPROC_USBD_READ(dma->status) & REG_DMA_STAT_BUF_MASK)); ++ iproc_ep_setup_init(ep, ENOERROR); ++ } else if ((IPROC_USBD_READ(dma->status) & REG_DMA_STAT_RX_MASK) ++ != REG_DMA_STAT_RX_SUCCESS) { ++ dev_err(udc->dev, "%s: unexpected DMA rx status=0x%x\n", ep->usb_ep.name, ++ (IPROC_USBD_READ(dma->status) & REG_DMA_STAT_RX_MASK)); ++ iproc_ep_setup_init(ep, ENOERROR); ++ } else { ++ if (ep->num != 0) { ++ /** @todo Handle the cfg / intf / alt fields of the DMA status. This will only be any issue ++ * once the Linux Gadget driver framework supports control transfers on an endpoint other ++ * than 0. ++ */ ++ dev_warn(udc->dev, "%s: CTRL xfr support not complete\n", ep->usb_ep.name); ++ } ++ /* ++ * Take ownership of the descriptor while processing the request. Ownership will be released ++ * when ready to Rx SETUP again. ++ */ ++ IPROC_USBD_BITS_MODIFY(dma->status, REG_DMA_STAT_BUF_MASK, ++ REG_DMA_STAT_BUF_HOST_BUSY); ++ iproc_ep_setup_process(ep, (struct usb_ctrlrequest *)&dma->data1); ++ } ++} ++ ++static void iproc_ep_out_isr(struct iproc_ep *ep) ++{ ++ struct iproc_udc *udc = ep->udc; ++ u32 status; ++ ++ status = iproc_usbd_ep_stat_active(udc->usbd_regs, ep->num, USB_DIR_OUT); ++ iproc_usbd_ep_stat_clear(udc->usbd_regs, ep->num, USB_DIR_OUT, status); ++ ++ /* ++ * Remove the Rx packet size field from the status. The datasheet states this field is not used ++ * in DMA mode, but that is not true. ++ */ ++ status &= USBD_EP_STAT_ALL; ++ ++ if (!status) ++ return; ++ ++ if ((ep->dir != USB_DIR_OUT) && (ep->type != USB_ENDPOINT_XFER_CONTROL)) { ++ dev_err(udc->dev, "%s: unexpected OUT interrupt\n", ep->usb_ep.name); ++ return; ++ } ++ ++ if (ep->dir != USB_DIR_OUT) ++ /* This probably should not be happening */ ++ dev_err(udc->dev, "%s: CTRL dir IN\n", ep->usb_ep.name); ++ ++ if (status & USBD_EP_STAT_OUT_DMA_DATA_DONE) { ++ status &= ~USBD_EP_STAT_OUT_DMA_DATA_DONE; ++ iproc_udc_req_xfer_process(ep); ++ } ++ ++ if (status & USBD_EP_STAT_OUT_DMA_SETUP_DONE) { ++ status &= ~USBD_EP_STAT_OUT_DMA_SETUP_DONE; ++ iproc_ep_out_setup_isr(ep); ++ } ++ ++ if (status & USBD_EP_STAT_DMA_BUF_UNAVAIL) { ++ /** @todo Verify under what situations this can happen. Should be when chain has emptied but last desc not reached */ ++ /** @todo status for desc updates */ ++ ++ status &= ~USBD_EP_STAT_DMA_BUF_UNAVAIL; ++ dev_err(udc->dev, "%s: DMA BUF NOT AVAIL\n", ep->usb_ep.name); ++ iproc_udc_req_xfer_process(ep); ++ } ++ ++ if (status & USBD_EP_STAT_DMA_ERROR) { ++ status &= ~USBD_EP_STAT_DMA_ERROR; ++ dev_err(udc->dev, "%s: DMA ERROR\n", ep->usb_ep.name); ++ /** @todo merge XferError and XferProcess?? */ ++ iproc_udc_req_xfer_error(ep, -EIO); ++ } ++ ++ if (status) ++ dev_err(udc->dev, "%s: unknown status=0x%x\n", ep->usb_ep.name, status); ++} ++ ++irqreturn_t xgs_iproc_udc_isr(int irq, void *context) ++{ ++ struct iproc_udc *udc = NULL; ++ unsigned long flags; ++ u32 stat, epin_stat, epout_stat; ++ int idx; ++ ++ udc = (struct iproc_udc *)context; ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ if (!udc || !udc->gadget_driver) { ++ dev_err(udc->dev, "Invalid context or no driver registered: irq dev=0x%x\n", ++ iproc_usbd_irq_active(udc->usbd_regs)); ++ ++ iproc_usbd_irq_clear(udc->usbd_regs, USBD_IRQ_ALL); ++ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_IN, ~0); ++ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_OUT, ~0); ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ return IRQ_HANDLED; ++ } ++ ++ stat = iproc_usbd_irq_active(udc->usbd_regs); ++ epin_stat = iproc_usbd_ep_irq_list_active(udc->usbd_regs, USB_DIR_IN); ++ epout_stat = iproc_usbd_ep_irq_list_active(udc->usbd_regs, USB_DIR_OUT); ++ ++ if (!(stat || epin_stat || epout_stat)) ++ return IRQ_NONE; ++ ++ iproc_usbd_irq_clear(udc->usbd_regs, stat); ++ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_IN, epin_stat); ++ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_OUT, epout_stat); ++ ++ /* ++ * Handle the SET_CFG and SET_INTF interrupts after the endpoint and other device interrupts. ++ * There can be some race conditions where we have an endpoint 0 interrupt pending for the ++ * completion of a previous endpoint 0 transfer (e.g. a GET config) when a SETUP arrives ++ * corresponding to the SET_CFG and SET_INTF. Need to complete the processing of the previous ++ * transfer before handling the next one, idx.e. the SET_CFG or SET_INTF. ++ */ ++ if (stat & USBD_IRQ_BUS_RESET) ++ dev_info(udc->dev, "BUS reset\n"); ++ ++ if (stat & USBD_IRQ_BUS_SUSPEND) ++ dev_dbg(udc->dev, "BUS suspend\n"); ++ ++ if (stat & USBD_IRQ_BUS_IDLE) { ++ dev_dbg(udc->dev, "BUS idle\n"); ++ iproc_udc_ops_disconnect(udc); ++ } ++ ++ if (stat & USBD_IRQ_SPEED_ENUM_DONE) { ++ dev_dbg(udc->dev, "BUS speed enum done\n"); ++ iproc_speed_isr(udc); ++ } ++ ++ /* endpoint interrupts handler */ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { ++ if (epin_stat & (1 << idx)) ++ iproc_ep_in_isr(&udc->ep[idx]); ++ if (epout_stat & (1 << idx)) ++ iproc_ep_out_isr(&udc->ep[idx]); ++ } ++ ++ /* SET_CFG and SET_INTF interrupts handler */ ++ if (stat & USBD_IRQ_SET_CFG) ++ iproc_cfg_isr(udc); ++ if (stat & USBD_IRQ_SET_INTF) ++ iproc_inf_isr(udc); ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return IRQ_HANDLED; ++} ++ ++/*************************************************************************** ++* Endpoint request operations ++***************************************************************************/ ++static void iproc_udc_req_queue_flush(struct iproc_ep *ep, int status) ++{ ++ struct iproc_udc *udc = ep->udc; ++ struct iproc_ep_req *req; ++ ++ ep->stopped = 1; ++ iproc_usbd_ep_ops_finish(udc->usbd_regs, ep->num); ++ ++ while (!list_empty(&ep->list_queue)) { ++ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); ++ iproc_udc_req_xfer_done(ep, req, status); ++ } ++ ++ ep->dma.usb_req = NULL; ++} ++ ++ ++static void iproc_udc_req_xfer_add(struct iproc_ep *ep, struct iproc_ep_req *req) ++{ ++ struct iproc_udc *udc = ep->udc; ++ list_add_tail(&req->list_node, &ep->list_queue); ++ ++ /** @todo Is this necessary?? Stopped happens as a result of a halt, complete(), dequeue(), nuke(). ++ * nuke() is called when ep disabled, during setup processing, and by udc_queisce(). The latter is ++ * called during vbus state change (cable insert/remove), USB reset interrupt, and gadget deregister. ++ */ ++ if (ep->stopped) ++ return; ++ ++ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC) && ++ ep->dma.usb_req && (ep->dma.frame_num == FRAME_NUM_INVALID)) { ++ /* ++ * Gadget has a request already queued, but still have not received an IN token from the host ++ * and the interval window is not aligned. Queued packet is now very stale, so remove it. ++ */ ++ ++ iproc_dma_data_finish(ep); ++ /** @todo Move set of ep->dma.usb_req to iproc_dma_data_init() and iproc_dma_data_finish() routines. */ ++ ep->dma.usb_req = NULL; ++ iproc_udc_req_xfer_done(ep, list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node), -EREMOTEIO); ++ } ++ ++ /** @todo Current transfer is always the queue head. Do we need a separate pointer? Maybe just a pointer to usb_request ++ * need to know if the queue head has already been loaded. Maybe that's the point of the "stopped". ++ */ ++ if (!ep->dma.usb_req) { ++ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC) && ++ (ep->dma.frame_num == FRAME_NUM_INVALID)) { ++ /* ++ * Delay any ISOC IN DMA operations until it is known what frame number the host ++ * is going to start transfers with. Normally might just return requests until ++ * this event occurs. However, the zero gadget does not submit requests based on ++ * its own timer or similar, so if the request is returned right away things are ++ * going to thrash, as another request will be immediately submitted. ++ */ ++ ep->dma.usb_req = &(list_first_entry(&ep->list_queue, ++ struct iproc_ep_req, list_node))->usb_req; ++ iproc_dma_data_init(ep); ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); ++ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, ep->dir); ++ } else { ++ req = list_first_entry(&ep->list_queue, ++ struct iproc_ep_req, list_node); ++ ep->dma.usb_req = &req->usb_req; ++ iproc_dma_data_init(ep); ++ iproc_dma_data_add_ready(ep); ++ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); ++ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, ep->dir); ++ ++ /* needed for gadget commands to complete correctly - possible locking issue */ ++ mdelay(3); ++ } ++ } ++} ++ ++/* ++ * UDC Operations routines. ++ * iproc_udc_ops_finish - Finish / terminate all UDC operations ++ * iproc_udc_ops_start - Start UDC operations. Happens after a Gadget driver attaches. ++ * iproc_udc_ops_stop - Stop UDC operations. Happens after a Gadget driver detaches. ++ */ ++static void iproc_udc_ops_finish(struct iproc_udc *udc) ++{ ++ /* do nothing */ ++ return; ++} ++ ++static void iproc_udc_ops_start(struct iproc_udc *udc) ++{ ++ int idx; ++ ++ /* ++ * Just enable interrupts for now. Endpoint 0 will get enabled once the speed enumeration ++ * has completed. The Device DMA enable is global in scope. There's endpoint specific ++ * DMA enables that will happen later. ++ */ ++ iproc_usbd_irq_en(udc->usbd_regs, (USBD_IRQ_SPEED_ENUM_DONE | ++ USBD_IRQ_BUS_SUSPEND | ++ USBD_IRQ_BUS_IDLE | ++ USBD_IRQ_BUS_RESET | ++ USBD_IRQ_SET_INTF | ++ USBD_IRQ_SET_CFG)); ++ iproc_usbd_dma_en(udc->usbd_regs); ++ ++ /* Enable interrupts for all configured endpoints */ ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; ++idx) { ++ if (udc->ep[idx].usb_ep.name) { ++ iproc_usbd_ep_irq_en(udc->usbd_regs, udc->ep[idx].num, USB_DIR_OUT); ++ iproc_usbd_ep_irq_en(udc->usbd_regs, udc->ep[idx].num, USB_DIR_IN); ++ } ++ } ++ iproc_usbd_nak_response_dis(udc->usbd_regs); ++} ++ ++static void iproc_udc_ops_stop(struct iproc_udc *udc) ++{ ++ struct iproc_ep *ep; ++ ++ iproc_usbd_dma_dis(udc->usbd_regs); ++ iproc_usbd_irq_dis(udc->usbd_regs, USBD_IRQ_ALL); ++ iproc_usbd_irq_clear(udc->usbd_regs, USBD_IRQ_ALL); ++ ++ udc->gadget.speed = USB_SPEED_UNKNOWN; ++ ++ iproc_udc_req_queue_flush(&udc->ep[0], -ESHUTDOWN); ++ ++ list_for_each_entry(ep, &udc->gadget.ep_list, usb_ep.ep_list) ++ iproc_udc_req_queue_flush(ep, -ESHUTDOWN); ++} ++ ++/* ++ * APIs used by a Gadget driver to attach / detach from the UDC driver. ++ */ ++static int xgs_iproc_udc_start(struct usb_gadget *gadget, ++ struct usb_gadget_driver *gadget_driver) ++{ ++ struct iproc_udc *udc = gadget_to_udc(gadget); ++ unsigned long flags; ++ ++ if (!udc) { ++ dev_err(udc->dev, "UDC driver not initialized\n"); ++ return -ENODEV; ++ } ++ ++ if (!gadget_driver || !gadget_driver->setup || ++ gadget_driver->max_speed < USB_SPEED_FULL) { ++ dev_err(udc->dev, "invalid gadget driver\n" ); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ if (udc->gadget_driver) { ++ spin_unlock_irqrestore(&udc->lock, flags); ++ dev_err(udc->dev, "UDC driver busy\n"); ++ return -EBUSY; ++ } ++ ++ /* Hook up the gadget driver to the UDC controller driver */ ++ gadget_driver->driver.bus = NULL; ++ udc->gadget_driver = gadget_driver; ++ udc->gadget.dev.driver = &gadget_driver->driver; ++ udc->pullup_on = 1; ++ ++ iproc_udc_ops_start(udc); ++ /* un-stop the control endpoint */ ++ udc->ep[0].stopped = 0; ++ iproc_usbd_bus_conn(udc->usbd_regs); ++ ++ iproc_usbd_setup_done(udc->usbd_regs); ++ iproc_usbd_dma_en(udc->usbd_regs); ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ENOERROR; ++} ++ ++static int xgs_iproc_udc_stop(struct usb_gadget *gadget) ++{ ++ unsigned long flags; ++ struct iproc_udc *udc = gadget_to_udc(gadget); ++ ++ if (!udc) { ++ dev_err(udc->dev, "UDC driver not initialized\n"); ++ return -ENODEV; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ udc->ep[0].stopped = 1; ++ iproc_udc_ops_stop(udc); ++ udelay(20); ++ udc->pullup_on = 0; ++ iproc_usbd_bus_disconn(udc->usbd_regs); ++ iproc_udc_ops_shutdown(udc); ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ENOERROR; ++} ++ ++/* ++ * Linux Gadget endpoint operations. See usb_ep_ops in usb_gadget.h. ++ */ ++static int xgs_iproc_ep_enable(struct usb_ep *usb_ep, const struct usb_endpoint_descriptor *desc) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ unsigned long flags; ++ u32 xferType; ++ int ret = ENOERROR; ++ ++ if (!usb_ep || (ep->beq_addr != desc->bEndpointAddress)) { ++ dev_err(udc->dev, "invalid endpoint (%p)\n", usb_ep); ++ return -EINVAL; ++ } ++ ++ if (!desc || (desc->bDescriptorType != USB_DT_ENDPOINT)) { ++ dev_err(udc->dev, "ep%d: invalid descriptor=%p type=%d\n", ep->num, desc, desc ? desc->bDescriptorType : -1); ++ return -EINVAL; ++ } ++ ++ if (desc == ep->desc) { ++ dev_warn(udc->dev, "ep%d: already enabled with same descriptor\n", ep->num); ++ return -EEXIST; ++ } ++ ++ if (ep->desc) { ++ dev_warn(udc->dev, "ep%d: already enabled with another descriptor\n", ep->num); ++ return -EBUSY; ++ } ++ ++ if (!udc->gadget_driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) { ++ dev_warn(udc->dev, "%s: invalid device state\n", ep->usb_ep.name); ++ return -ESHUTDOWN; ++ } ++ ++ xferType = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; ++ if ((ep->dir == USB_DIR_IN) && (xferType == USB_ENDPOINT_XFER_ISOC)) { ++ if ((desc->bInterval < 1) || (desc->bInterval > 16)) { ++ dev_err(udc->dev, "%s: invalid ISOC bInterval=%u\n", ep->usb_ep.name, desc->bInterval); ++ return -ERANGE; ++ } ++ ++ /* ++ * We don't know when the host will send the first ISO IN request, so we need to set up ++ * to capture that event so we can align subsequent transfers to that particular frame ++ * number. Also set the frame number increment. The endpoint descriptor specifies this ++ * as a power of 2 (2**(n-1)). Translate this into a specific number of frames. ++ */ ++ ep->dma.frame_num = FRAME_NUM_INVALID; ++ ep->dma.frame_incr = 1 << (desc->bInterval - 1); ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ ep->desc = desc; ++ ep->stopped = 0; ++ ++ /** @todo Rework the UdcEpCfg() so it includes iproc_usbd_ep_cfg_set() ... */ ++ iproc_usbd_ep_cfg_set(udc->usbd_regs, ep->num, iproc_usbd_cfg_num(udc->usbd_regs)); ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ret; ++} ++ ++static int xgs_iproc_ep_disable(struct usb_ep *usb_ep) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ unsigned long flags; ++ int ret = ENOERROR; ++ ++ if (!usb_ep) { ++ dev_err(udc->dev, "invalid endpoint\n"); ++ return -EINVAL; ++ } ++ ++ if (!ep->desc) { ++ dev_warn(udc->dev, "%s: already disabled\n", ep->usb_ep.name); ++ return ENOERROR; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ iproc_udc_req_queue_flush(ep, -ESHUTDOWN); ++ iproc_usbd_ep_irq_dis(udc->usbd_regs, ep->num, ep->dir); ++ ep->desc = NULL; ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ret; ++} ++ ++struct usb_request * xgs_iproc_ep_alloc_request(struct usb_ep *usb_ep, gfp_t gfp_flags) ++{ ++ struct iproc_ep_req *req; ++ ++ if (!usb_ep) ++ return NULL; ++ ++ if ((req = kzalloc(sizeof(*req), gfp_flags)) != NULL) { ++ /* ++ * Set the usb_req.dma to DMA_ADDR_INVALID so it can be determined if the usb_req.buf needs ++ * to be mapped when the request is subsequently queued. ++ */ ++ INIT_LIST_HEAD(&req->list_node); ++ req->usb_req.dma = DMA_ADDR_INVALID; ++ ++ return &req->usb_req; ++ } ++ ++ return NULL; ++} ++ ++static void xgs_iproc_ep_free_request(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ struct iproc_ep_req *req = our_req(usb_req); ++ ++ if (usb_req) ++ kfree(req); ++} ++ ++static int xgs_iproc_ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, gfp_t gfp_flags) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ struct iproc_ep_req *req = our_req(usb_req); ++ unsigned long flags; ++ int ret = ENOERROR; ++ ++ if (!usb_ep || !usb_req || !req->usb_req.complete || !req->usb_req.buf || !list_empty(&req->list_node)) { ++ dev_err(udc->dev, "invalid request\n"); ++ return -EINVAL; ++ } ++ ++ if (!ep->desc && (ep->num != 0)) { ++ dev_err(udc->dev, "%s: invalid EP state\n", ep->usb_ep.name); ++ return -EFAULT; ++ } ++ ++ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && !list_empty(&ep->list_queue)) { ++ dev_err(udc->dev, "%s: CTRL EP queue not empty\n", ep->usb_ep.name); ++ return -EPERM; ++ } ++ ++ if (usb_req->length > 16384 /* FSG_BUFLEN */) { ++ dev_err(udc->dev, "%s: request too big, length=%u\n", ep->usb_ep.name, usb_req->length); ++ return -E2BIG; ++ } ++ ++ /* ++ * Restrict ISOC IN requests to the max packet size. Assumption is that it does not make ++ * much sense to have more than one interval's (scheduled bandwidth's) worth of data. ++ */ ++ if ((ep->type == USB_ENDPOINT_XFER_ISOC) && (ep->dir == USB_DIR_IN) && (usb_req->length > ep->usb_ep.maxpacket)) { ++ dev_err(udc->dev, "%s: request > scheduled bandwidth, length=%u\n", ep->usb_ep.name, usb_req->length); ++ return -EFBIG; ++ } ++ ++ if (!udc->gadget_driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) { ++ dev_warn(udc->dev, "%s: invalid device state\n", ep->usb_ep.name); ++ return -ESHUTDOWN; ++ } ++ ++ if (((u32)req->usb_req.buf) & 0x3UL) { ++ /* ++ * The DMA buffer does not have the alignment required by the hardware. We keep an endpoint level ++ * buffer available to handle this situation if it arises. If we don't currently have one available ++ * for this purpose, or if the current one is not large enough, then allocate a new one. Since ++ * we only have one buffer, we won't copy into the buffer until we are ready to do the DMA transfer. ++ * Mark the request as needing this alignment (copy). ++ */ ++ if ((ep->dma.align_buff != NULL) && (ep->dma.align_len < req->usb_req.length)) { ++ dma_free_coherent(NULL, ep->dma.align_len, ep->dma.align_buff, ep->dma.align_addr); ++ ep->dma.align_buff = NULL; ++ } ++ ++ if (ep->dma.align_buff == NULL) { ++ ep->dma.align_len = req->usb_req.length; ++ ep->dma.align_buff = dma_alloc_coherent(NULL, ep->dma.align_len, &(ep->dma.align_addr), GFP_KERNEL); ++ } ++ ++ if (ep->dma.align_buff == NULL) { ++ dev_err(udc->dev, "%s: dma_alloc_coherent() failed, length=%u\n", ep->usb_ep.name, usb_req->length); ++ return -ENOMEM; ++ } ++ req->dma_aligned = 1; ++ } else if ((req->usb_req.dma == DMA_ADDR_INVALID) || (req->usb_req.dma == 0)) { ++ /* A physical address was not provided for the DMA buffer, so request it. */ ++ req->dma_mapped = 1; ++ req->usb_req.dma = dma_map_single(udc->gadget.dev.parent, ++ req->usb_req.buf, ++ req->usb_req.length, ++ ep->dir == USB_DIR_IN ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ req->usb_req.status = -EINPROGRESS; ++ req->usb_req.actual = 0; ++ ++ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && (ep->dir == USB_DIR_OUT) && (req->usb_req.length == 0)) { ++ /* ++ * This might happen if gadget driver decides to send zero length packet (ZLP) during STATUS phase ++ * of a control transfer. This may happen for the cases where there is not a DATA phase. Just consider ++ * things complete. ZLP will be issued by hardware. See the handling of SETUP packets for more details ++ * on control transfer processing. ++ */ ++ iproc_udc_req_xfer_done(ep, req, ENOERROR); ++ } else { ++ if (req->usb_req.length == 0) ++ req->usb_req.zero = 1; ++ iproc_udc_req_xfer_add(ep, req); ++ } ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ret; ++} ++ ++static int xgs_iproc_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ struct iproc_ep_req *req = our_req(usb_req); ++ unsigned long flags; ++ int ret = ENOERROR; ++ ++ if (!usb_ep || !usb_req) { ++ dev_err(udc->dev, "invalid request\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ /* Make sure it's actually queued on this endpoint */ ++ list_for_each_entry(req, &ep->list_queue, list_node) { ++ if (&req->usb_req == usb_req) ++ break; ++ } ++ ++ if (&req->usb_req != usb_req) { ++ spin_unlock_irqrestore(&udc->lock, flags); ++ dev_err(udc->dev, "%s: request not queued\n", ep->usb_ep.name); ++ return -ENOLINK; ++ } ++ ++ /** @todo Handle case where the request is in progress, or completed but not dequeued */ ++ ++ iproc_udc_req_xfer_done(ep, req, -ECONNRESET); ++ spin_unlock_irqrestore(&udc->lock, flags); ++ ++ return ret; ++} ++ ++static int xgs_iproc_ep_set_halt(struct usb_ep *usb_ep, int enable) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ unsigned long flags; ++ int ret = ENOERROR; ++ ++ if (!usb_ep) { ++ dev_err(udc->dev, "invalid request\n"); ++ return -EINVAL; ++ } ++ ++ if (ep->type == USB_ENDPOINT_XFER_ISOC) { ++ dev_warn(udc->dev, "%s: ISO HALT operations not supported\n", ep->usb_ep.name); ++ return -EOPNOTSUPP; ++ } ++ ++ if (enable && (ep->dir == USB_DIR_IN) && !list_empty(&ep->list_queue)) { ++ /* Only allow halt on an IN EP if its queue is empty */ ++ dev_err(udc->dev, "%s: IN queue not empty\n", ep->usb_ep.name); ++ return -EAGAIN; ++ } ++ ++ if (!enable && (ep->type == USB_ENDPOINT_XFER_CONTROL)) { ++ /* ++ * Halt clear for a control EP should only be handled as part of the subsequent SETUP ++ * exchange that occurs after the Halt was set. ++ */ ++ dev_warn(udc->dev, "%s: CTRL HALT clear\n", ep->usb_ep.name); ++ return -EPROTO; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ if (!enable) { ++ iproc_usbd_ep_stall_dis(udc->usbd_regs, ep->num, ep->dir); ++ } else if (ep->type != USB_ENDPOINT_XFER_CONTROL) { ++ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, ep->dir); ++ } else { ++ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_IN); ++ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_OUT); ++ } ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++ mdelay(2); ++ ++ return ret; ++} ++ ++static int xgs_iproc_ep_fifo_status(struct usb_ep *usb_ep) ++{ ++ /* ++ * The DWC UDC core doesn't have a mechanism for determining the number of bytes ++ * currently in a FIFO. The best that can be done is determine whether or not a ++ * FIFO is empty. However, for the situation where a single Rx FIFO is being ++ * used for all endpoints, if cannot be determined which OUT and CTRL EP's are ++ * affected if the Rx FIFO is not empty. ++ */ ++ return -EOPNOTSUPP; ++} ++ ++static void xgs_iproc_ep_fifo_flush(struct usb_ep *usb_ep) ++{ ++ struct iproc_ep *ep = our_ep(usb_ep); ++ struct iproc_udc *udc = ep->udc; ++ unsigned long flags; ++ ++ if (!usb_ep) { ++ dev_err(udc->dev, "invalid request\n"); ++ return; ++ } ++ ++ /* ++ * FIFO flush for a control EP does not make any sense. The SETUP protocol ++ * should eliminate the need to flush. ++ */ ++ if (ep->type == USB_ENDPOINT_XFER_CONTROL) { ++ dev_warn(udc->dev, "%s: CTRL FIFO flush\n", ep->usb_ep.name); ++ return; ++ } ++ ++ if (iproc_usbd_ep_fifo_empty(udc->usbd_regs, ep->num, ep->dir)) { ++ dev_warn(udc->dev, "%s: FIFO empty\n", ep->usb_ep.name); ++ return; ++ } ++ ++ spin_lock_irqsave(&udc->lock, flags); ++ ++ iproc_usbd_ep_fifo_flush_en(udc->usbd_regs, ep->num, ep->dir); ++ ++ spin_unlock_irqrestore(&udc->lock, flags); ++} ++ ++ ++/*************************************************************************** ++ * Linux proc file system functions ++ ***************************************************************************/ ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++#include ++ ++static const char udc_proc_file_name[] = "driver/" XGS_IPROC_UDC_NAME; ++ ++static int proc_file_show(struct seq_file *s, void *_) ++{ ++ return 0; ++} ++ ++static int proc_file_open(struct inode *inode, struct file *file) ++{ ++ return(single_open(file, proc_file_show, NULL)); ++} ++ ++static struct file_operations udc_proc_file_ops = ++{ ++ .open = proc_file_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void xgs_iproc_udc_proc_create(void) ++{ ++ proc_create(udc_proc_file_name, 0, NULL, &udc_proc_file_ops); ++} ++ ++static void xgs_iproc_udc_proc_remove(void) ++{ ++ remove_proc_entry(udc_proc_file_name, NULL); ++} ++ ++#else ++ ++static void xgs_iproc_udc_proc_create(void) {} ++static void xgs_iproc_udc_proc_remove(void) {} ++ ++#endif ++ ++static struct usb_gadget_ops xgs_iproc_udc_ops = { ++ .udc_start = xgs_iproc_udc_start, ++ .udc_stop = xgs_iproc_udc_stop, ++}; ++ ++static struct usb_ep_ops xgs_iproc_udc_ep_ops = { ++ .enable = xgs_iproc_ep_enable, ++ .disable = xgs_iproc_ep_disable, ++ .alloc_request = xgs_iproc_ep_alloc_request, ++ .free_request = xgs_iproc_ep_free_request, ++ .queue = xgs_iproc_ep_queue, ++ .dequeue = xgs_iproc_ep_dequeue, ++ .set_halt = xgs_iproc_ep_set_halt, ++ .fifo_status = xgs_iproc_ep_fifo_status, ++ .fifo_flush = xgs_iproc_ep_fifo_flush, ++}; ++ ++static const struct of_device_id xgs_iproc_udc_ids[] = { ++ { .compatible = "brcm,usbd-xgs-iproc", }, ++ { .compatible = "brcm,usbd-xgs-hx4", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, xgs_iproc_udc_ids); ++ ++static void iproc_udc_ops_init(struct iproc_udc *udc) ++{ ++ int idx; ++ struct iproc_ep *ep; ++ ++ iproc_usbd_ops_init(udc->usbd_regs); ++ ++ /* ++ * See usb/gadget/epautoconf.c for endpoint naming conventions. ++ * Control endpoints are bi-directional, but initial transfer (SETUP stage) is always OUT. ++ */ ++ /** @todo Really should make the non endpoint 0 init attributes configurable by the chip specific part ++ * of the driver, idx.e. the device instantiation. The settings below are for a chip specific DWG UDC ++ * core configuration. Also should incorporate the DWG UDC endpoint type attribute as part of this, ++ * which can be control, IN, OUT, or bidirectional. ++ */ ++ INIT_LIST_HEAD(&udc->gadget.ep_list); ++ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { ++ ep = &udc->ep[idx]; ++ ++ ep->udc = udc; ++ ep->num = idx; ++ ++ ep->dir = (xgs_iproc_ep_info[idx].caps.dir_in) ? USB_DIR_IN : USB_DIR_OUT;; ++ ep->beq_addr = idx | ep->dir; ++ ep->stopped = 0; ++ ep->type = xgs_iproc_ep_info[idx].type; ++ ++ ep->usb_ep.name = xgs_iproc_ep_info[idx].name; ++ ep->usb_ep.caps = xgs_iproc_ep_info[idx].caps; ++ ep->usb_ep.ops = &xgs_iproc_udc_ep_ops; ++ list_add_tail(&ep->usb_ep.ep_list, &udc->gadget.ep_list); ++ usb_ep_set_maxpacket_limit(&ep->usb_ep, xgs_iproc_ep_info[idx].msize); ++ ep->usb_ep.desc = NULL; ++ INIT_LIST_HEAD(&ep->list_queue); ++ ++ iproc_usbd_ep_ops_init(udc->usbd_regs, ep->num, ep->type, ++ ep->dir, xgs_iproc_ep_info[idx].msize); ++ ++ iproc_dma_ep_init(ep); ++ } ++ ++ udc->gadget.ep0 = &udc->ep[0].usb_ep; ++ list_del(&udc->ep[0].usb_ep.ep_list); ++ ++ iproc_usbd_self_pwr_en(udc->usbd_regs); ++} ++ ++ ++/**************************************************************************** ++ ***************************************************************************/ ++static int xgs_iproc_udc_probe(struct platform_device *pdev) ++{ ++ int ret = ENOERROR; ++ struct device *dev = &pdev->dev; ++ struct device_node *dn = dev->of_node; ++ struct iproc_udc *udc = NULL; ++ struct usb_phy *phy; ++ struct resource *res; ++ void __iomem *usbd_base; ++ int irq; ++ ++ phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "unable to find transceiver\n"); ++ return PTR_ERR(phy); ++ } ++ ++ /* HX4 SVK always is identified as HOST, because GPIO pin 0 is always low, ++ * even the strap setting of JP1803 is device mode. ++ */ ++ if (!of_device_is_compatible(dn, "brcm,usbd-xgs-hx4")) ++ if (phy->flags != IPROC_USB_MODE_DEVICE) ++ return -ENODEV; ++ ++ irq = platform_get_irq(pdev, 0); ++ ++ udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); ++ if (!udc) { ++ dev_err(dev, "devm_kzalloc() failed\n" ); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, udc); ++ udc->dev = dev; ++ spin_lock_init(&udc->lock); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ usbd_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(usbd_base)) { ++ dev_err(dev, "can't ioremap USB2D base addr\n"); ++ return PTR_ERR(usbd_base); ++ } ++ ++ udc->usbd_regs = (struct iproc_usbd_regs *)usbd_base; ++ ++ ret = usb_phy_init(phy); ++ if (ret < 0) { ++ dev_err(dev, "initial usb transceiver failed.\n"); ++ return ret; ++ } ++ ++ ret = iproc_platform_dma_alloc(pdev, udc); ++ if (ret < 0) { ++ dev_err(dev, "iproc_platform_dma_alloc() failed\n"); ++ return ret; ++ } ++ ++ /* gadget init */ ++ udc->gadget.name = XGS_IPROC_UDC_NAME; ++ udc->gadget.speed = USB_SPEED_UNKNOWN; ++ udc->gadget.max_speed = USB_SPEED_HIGH; ++ udc->gadget.ops = &xgs_iproc_udc_ops; ++ ++ iproc_udc_ops_init(udc); ++ ++ iproc_usbd_irq_dis(udc->usbd_regs, USBD_IRQ_ALL); ++ iproc_usbd_irq_clear(udc->usbd_regs, USBD_IRQ_ALL); ++ ++ ret = devm_request_irq(dev, irq, xgs_iproc_udc_isr, 0, ++ XGS_IPROC_UDC_NAME, (void *)udc); ++ if (ret < 0) { ++ dev_err(dev, "error requesting IRQ #%d\n", irq); ++ goto err1; ++ } ++ ++ ret = usb_add_gadget_udc(dev, &udc->gadget); ++ if (ret < 0) { ++ dev_err(dev, "usb_add_gadget_udc() failed\n"); ++ goto err1; ++ } ++ ++ xgs_iproc_udc_proc_create(); ++ ++ return ENOERROR; ++ ++err1: ++ iproc_platform_dma_free(pdev, udc); ++ ++ return ret; ++} ++ ++static int xgs_iproc_udc_remove(struct platform_device *pdev) ++{ ++ struct iproc_udc *udc = platform_get_drvdata(pdev); ++ ++ if (udc) { ++ xgs_iproc_udc_proc_remove(); ++ ++ usb_del_gadget_udc(&udc->gadget); ++ iproc_udc_ops_finish(udc); ++ ++ platform_set_drvdata(pdev, NULL); ++ iproc_platform_dma_free(pdev, udc); ++ } ++ ++ return ENOERROR; ++} ++ ++/* ++ * Generic platform device driver definition. ++ */ ++static struct platform_driver xgs_iproc_udc_driver = ++{ ++ .probe = xgs_iproc_udc_probe, ++ .remove = xgs_iproc_udc_remove, ++ .driver = { ++ .name = XGS_IPROC_UDC_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = xgs_iproc_udc_ids, ++ }, ++}; ++ ++module_platform_driver(xgs_iproc_udc_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB Device Controller(UDC) driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_iproc_udc.h b/drivers/usb/gadget/udc/xgs_iproc_udc.h +--- a/drivers/usb/gadget/udc/xgs_iproc_udc.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/gadget/udc/xgs_iproc_udc.h 2018-05-10 11:31:33.789404169 +0800 +@@ -0,0 +1,157 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 _XGS_IPROC_UDC_H_ ++#define _XGS_IPROC_UDC_H_ ++ ++#include ++#include "xgs_iproc_usbd_regs.h" ++ ++#define IPROC_UDC_EP_CNT 7 ++#define IPROC_UDC_CTRL_MAX_PKG_SIZE 64 ++#define IPROC_UDC_EP_MAX_PKG_SIZE 512 ++ ++/* ++ * Some unsigned number trickery for indexing into DMA descriptor chain. If the ++ * decriptor count is some power of 2, then we can use the mask to extract ++ * an index and not worry about wrap around as the unsigned variables are ++ * incremented. E.g. in following, IDX(0), IDX(4), IDX(8), ..., IDX(0xffffc) ++ * all produce the same result, i.e. 0. ++ */ ++#define IPROC_EP_DMA_DESC_CNT 1 ++#define IPROC_EP_DMA_DESC_IDX_MASK (IPROC_EP_DMA_DESC_CNT - 1) ++#define IPROC_EP_DMA_DESC_IDX(_idx) ((_idx) & IPROC_EP_DMA_DESC_IDX_MASK) ++ ++/* Some DWC UDC DMA descriptor layout definitions. See datasheet for details. */ ++ ++struct iproc_udc_dma_setup { ++ unsigned int status; ++ unsigned int reserved; ++ unsigned int data1; ++ unsigned int data2; ++}; ++ ++struct iproc_udc_dma_desc { ++ unsigned int status; ++ unsigned int reserved; ++ unsigned int buf_addr; ++ unsigned int next_addr; ++}; ++ ++/* ++ * Common DMA descriptor layout used for all endpoints. Only control endpoints ++ * need the setup descriptor, but in order to simply things it is defined for ++ * all. It may be possible to omit this altogether, and just use one of data ++ * descriptors for setup instead. The control transfer protocol should allow ++ * this to be done. ++ */ ++struct iproc_ep_dma { ++ struct iproc_udc_dma_setup setup; ++ struct iproc_udc_dma_desc desc[IPROC_EP_DMA_DESC_CNT]; ++}; ++ ++/* Structure used for DMA descriptor allocation. Not really necessary but convenient. */ ++struct iproc_udc_dma { ++ struct iproc_ep_dma ep[IPROC_UDC_EP_CNT]; ++}; ++ ++/* ++ * Structure used to hold endpoint specific information. There's one of these for ++ * each endpoint. ++ * ++ * The Rx/Tx FIFO sizes are used for RAM allocation purposes. Each transfer ++ * direction has its own RAM that is used for all the FIFOs in that direction. ++ * The RAM gets segmented (allocated) as each endpoint gets enabled. This dynamic ++ * allocation FIFO sizes gives flexibility, and does not require that an ++ * endpoint's size be fixed at run-time or during compilation. If there's not ++ * enough FIFO RAM as required by a gadget's endpoint definitions, then an ++ * error will occur for the enabling of any endpoints after the FIFO RAM has ++ * become exhausted. ++ * ++ * The DMA virtual address is used for all descriptor operations. The DMA ++ * physical address is for convenience (setting hardware registers, obtaining ++ * addresses for descriptor chaining, etc.). The DMA descriptors are not ++ * allocated on a per-endpoint basis. These are just pointers into the ++ * large block that was allocated for all endpoints. ++ */ ++struct iproc_ep { ++ struct usb_ep usb_ep; /* usb_gadget.h */ ++ const struct usb_endpoint_descriptor *desc; /* usb/ch9.h */ ++ struct list_head list_queue; /* active BCM_UDC_EP_REQ's for the endpoint */ ++ struct iproc_udc *udc; /* endpoint owner (UDC controller) */ ++ unsigned int num; ++ unsigned int dir; /* USB_DIR_xxx (direction) */ ++ unsigned int type; /* USB_ENDPOINT_XFER_xxx */ ++ unsigned int beq_addr; /* dirn | type */ ++ unsigned int stopped : 1; ++ struct { ++ struct iproc_ep_dma *vir_addr; ++ struct iproc_ep_dma *phy_addr; ++ struct usb_request *usb_req; /* Current request being DMA'd */ ++ ++ /** @todo Some of the below are duplicates of usb_request elements. Use usb_request instead. */ ++ unsigned int max_buf_len; /* Max buffer length to use with a descriptor */ ++ unsigned int done_len; /* Length of request DMA'd so far */ ++ unsigned int todo_len; /* Length of request left to DMA */ ++ unsigned int add_idx; /* descriptor chain index */ ++ unsigned int rm_idx; /* descriptor chain index */ ++ unsigned int buf_addr; /* Location in request to DMA */ ++ unsigned int frame_num; /* Frame number for ISOC transfers */ ++ unsigned int frame_incr; /* Frame number increment (period) */ ++ unsigned int status; ++ unsigned int done; /* DMA and USB transfer completion indication (IN_DMA_DONE and IN_XFER_DONE) */ ++ void *align_buff; /* Aligned buffer. Only used if usb_req buffer not aligned properly. */ ++ dma_addr_t align_addr; /* Aligned buffer physical address */ ++ unsigned int align_len; /* Aligned buffer length */ ++ } dma; ++}; ++ ++/* ++ * Structure used to hold controller information. There should be one of these ++ * for each controller. Most likely there's only one. ++ * ++ * The Rx/Tx FIFO space are used for RAM allocation purposes. These track how ++ * much RAM is available for use as a FIFO. When an endpoint is enabled, these ++ * are check to see if there's enough RAM for a FIFO of the desired length as ++ * implied by the max packet size. ++ */ ++struct iproc_udc { ++ struct usb_gadget gadget; /* usb_gadget.h */ ++ struct usb_gadget_driver *gadget_driver; /* usb_gadget.h */ ++ struct completion *dev_release; /* Used for coordination during device removal */ ++ spinlock_t lock; ++ struct device *dev; ++ unsigned int irq_num; ++ struct iproc_ep ep[IPROC_UDC_EP_CNT]; ++ struct iproc_usbd_regs *usbd_regs; ++ struct { ++ struct iproc_udc_dma *vir_addr; ++ struct iproc_udc_dma *phy_addr; ++ } dma; ++ unsigned int vbus_active : 1; /* Indicates if VBUS is present */ ++ unsigned int pullup_on : 1; /* Indicates if pull up is on */ ++}; ++ ++/* ++ * Structure used to hold an endpoint transfer request. Can be any number of ++ * these for an endpoint. ++ */ ++struct iproc_ep_req { ++ struct usb_request usb_req; /* usb_gadget.h */ ++ struct list_head list_node; /* For linking in the BCM_UDC_EP request queue */ ++ dma_addr_t orig_dma_addr; /* Original buffer DMA address (physical). */ ++ unsigned dma_mapped : 1; /* Indicates if address mapping req'd. See usb_gadget.h */ ++ unsigned dma_aligned : 1; /* Indicates if buffer duplication done for alignment. */ ++}; ++ ++#endif /* _XGS_IPROC_UDC_H_ */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_iproc_usbd_regs.h b/drivers/usb/gadget/udc/xgs_iproc_usbd_regs.h +--- a/drivers/usb/gadget/udc/xgs_iproc_usbd_regs.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/gadget/udc/xgs_iproc_usbd_regs.h 2018-05-10 11:31:33.789404169 +0800 +@@ -0,0 +1,969 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 _USBD_REGS_H_ ++#define _USBD_REGS_H_ ++ ++#include ++#include ++ ++#define USBD_MULTI_RX_FIFO 0 ++ ++#define USBD_EP_CFG_CNT 10 ++#define USBD_REG_EP_CNT 16 ++ ++#define USBD_IRQ_REMOTEWAKEUP_DELTA REG_INTR_REMOTE_WAKEUP_DELTA ++#define USBD_IRQ_SPEED_ENUM_DONE REG_INTR_SPD_ENUM_DONE ++#define USBD_IRQ_SOF_DETECTED REG_INTR_SOF_RX ++#define USBD_IRQ_BUS_SUSPEND REG_INTR_BUS_SUSPEND ++#define USBD_IRQ_BUS_RESET REG_INTR_BUS_RESET ++#define USBD_IRQ_BUS_IDLE REG_INTR_BUS_IDLE ++#define USBD_IRQ_SET_INTF REG_INTR_SET_INTF_RX ++#define USBD_IRQ_SET_CFG REG_INTR_SET_CFG_RX ++#define USBD_IRQ_ALL (USBD_IRQ_REMOTEWAKEUP_DELTA | \ ++ USBD_IRQ_SPEED_ENUM_DONE | \ ++ USBD_IRQ_SOF_DETECTED | \ ++ USBD_IRQ_BUS_SUSPEND | \ ++ USBD_IRQ_BUS_RESET | \ ++ USBD_IRQ_BUS_IDLE | \ ++ USBD_IRQ_SET_INTF | \ ++ USBD_IRQ_SET_CFG) ++ ++#define USBD_EP_STAT_DMA_ERROR REG_EP_FIFO_STATUS_AHB_BUS_ERROR ++#define USBD_EP_STAT_DMA_BUF_UNAVAIL REG_EP_FIFO_STATUS_DMA_BUF_NOT_AVAIL ++#define USBD_EP_STAT_IN_TOKEN_RX REG_EP_FIFO_STATUS_IN_TOKEN_RX ++#define USBD_EP_STAT_IN_DMA_DONE REG_EP_FIFO_STATUS_IN_DMA_DONE ++#define USBD_EP_STAT_IN_FIFO_EMPTY REG_EP_FIFO_STATUS_IN_FIFO_EMPTY ++#define USBD_EP_STAT_IN_XFER_DONE REG_EP_FIFO_STATUS_IN_XFER_DONE ++#define USBD_EP_STAT_OUT_DMA_DATA_DONE REG_EP_FIFO_STATUS_OUT_DMA_DATA_DONE ++#define USBD_EP_STAT_OUT_DMA_SETUP_DONE REG_EP_FIFO_STATUS_OUT_DMA_SETUP_DONE ++#define USBD_EP_STAT_ALL (USBD_EP_STAT_DMA_ERROR | \ ++ USBD_EP_STAT_DMA_BUF_UNAVAIL | \ ++ USBD_EP_STAT_IN_TOKEN_RX | \ ++ USBD_EP_STAT_IN_DMA_DONE | \ ++ USBD_EP_STAT_IN_XFER_DONE | \ ++ USBD_EP_STAT_OUT_DMA_DATA_DONE | \ ++ USBD_EP_STAT_OUT_DMA_SETUP_DONE) ++ ++ ++#define REG8_RSVD(start, end) u8 rsvd_##start[(end - start) / sizeof(u8)] ++#define REG16_RSVD(start, end) u16 rsvd_##start[(end - start) / sizeof(u16)] ++#define REG32_RSVD(start, end) u32 rsvd_##start[(end - start) / sizeof(u32)] ++ ++struct iproc_usbd_ep_fifo_regs { ++ uint ctrl; ++ uint status; ++ uint size1; ++ uint size2; /* Buf Size OUT/Max PKT SIZE */ ++ uint buf_addr; ++ uint desc_addr; ++ REG32_RSVD(0x18, 0x20); ++}; ++ ++struct iproc_usbd_regs { ++ struct iproc_usbd_ep_fifo_regs ep_fifo_in[USBD_REG_EP_CNT]; ++ struct iproc_usbd_ep_fifo_regs ep_fifo_out[USBD_REG_EP_CNT]; ++ uint dev_cfg; ++ uint dev_ctrl; ++ uint dev_status; ++ uint dev_irq_status; ++ uint dev_irq_mask; ++ uint ep_irq_status; ++ uint ep_irq_mask; ++ uint test_mode; ++ uint rel_num; ++ REG32_RSVD(0x424, 0x500); ++ REG32_RSVD(0x500, 0x504); ++ uint ep_cfg[USBD_REG_EP_CNT]; ++ REG32_RSVD(0x544, 0x800); ++ uint rx_fifo[256]; ++ uint tx_fifo[256]; ++ uint strap; ++}; ++ ++ ++struct iproc_usbd_idm_regs { ++ REG32_RSVD(0x000, 0x408); ++ uint io_ctrl; ++ REG32_RSVD(0x40C, 0x500); ++ uint io_status; ++ REG32_RSVD(0x504, 0x800); ++ uint reset_ctrl; ++ uint reset_status; ++ REG32_RSVD(0x808, 0xA00); ++ uint irq_status; ++}; ++ ++/* ++ * The endpoint type field in the FIFO control register has the same enumeration ++ * as the USB protocol. Not going to define it here. ++ */ ++#define REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE (1 << 12) ++#define REG_EP_FIFO_CTRL_OUT_CLOSE_DESC (1 << 11) ++#define REG_EP_FIFO_CTRL_IN_SEND_NULL (1 << 10) ++#define REG_EP_FIFO_CTRL_OUT_DMA_ENABLE (1 << 9) ++#define REG_EP_FIFO_CTRL_NAK_CLEAR (1 << 8) ++#define REG_EP_FIFO_CTRL_NAK_SET (1 << 7) ++#define REG_EP_FIFO_CTRL_NAK_IN_PROGRESS (1 << 6) ++#define REG_EP_FIFO_CTRL_TYPE_SHIFT 4 ++#define REG_EP_FIFO_CTRL_TYPE_MASK (3 << REG_EP_FIFO_CTRL_TYPE_SHIFT) ++#define REG_EP_FIFO_CTRL_IN_DMA_ENABLE (1 << 3) ++#define REG_EP_FIFO_CTRL_SNOOP_ENABLE (1 << 2) ++#define REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE (1 << 1) ++#define REG_EP_FIFO_CTRL_STALL_ENABLE (1 << 0) ++ ++#define REG_EP_FIFO_STATUS_CLOSE_DESC_CLEAR (1 << 28) ++#define REG_EP_FIFO_STATUS_IN_XFER_DONE (1 << 27) ++#define REG_EP_FIFO_STATUS_STALL_SET_RX (1 << 26) ++#define REG_EP_FIFO_STATUS_STALL_CLEAR_RX (1 << 25) ++#define REG_EP_FIFO_STATUS_IN_FIFO_EMPTY (1 << 24) ++#define REG_EP_FIFO_STATUS_IN_DMA_DONE (1 << 10) ++#define REG_EP_FIFO_STATUS_AHB_BUS_ERROR (1 << 9) ++#define REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY (1 << 8) ++#define REG_EP_FIFO_STATUS_DMA_BUF_NOT_AVAIL (1 << 7) ++#define REG_EP_FIFO_STATUS_IN_TOKEN_RX (1 << 6) ++#define REG_EP_FIFO_STATUS_OUT_DMA_SETUP_DONE (1 << 5) ++#define REG_EP_FIFO_STATUS_OUT_DMA_DATA_DONE (1 << 4) ++ ++#define REG_EP_FIFO_SIZE1_OUT_ISOC_PID_SHIFT 16 ++#define REG_EP_FIFO_SIZE1_OUT_ISOC_PID_MASK (3 << REG_EP_FIFO_SIZE1_OUT_ISOC_PID_SHIFT) ++#define REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT 0 ++#define REG_EP_FIFO_SIZE1_IN_DEPTH_MASK (0xffff << REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT) ++#define REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_SHIFT REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT ++#define REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_MASK REG_EP_FIFO_SIZE1_IN_DEPTH_MASK ++ ++#define REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT 16 ++#define REG_EP_FIFO_SIZE2_OUT_DEPTH_MASK (0xffff << REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT) ++#define REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT 0 ++#define REG_EP_FIFO_SIZE2_PKT_MAX_MASK (0xffff << REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT) ++ ++/* ++ * The endpoint type field in the config register has the same enumeration ++ * as the USB protocol. Not going to define it here. ++ */ ++#define REG_EP_CFG_PKT_MAX_SHIFT 19 ++#define REG_EP_CFG_PKT_MAX_MASK (0x7ff << REG_EP_CFG_PKT_MAX_SHIFT) ++#define REG_EP_CFG_ALT_NUM_SHIFT 15 ++#define REG_EP_CFG_ALT_NUM_MASK (0xf << REG_EP_CFG_ALT_NUM_SHIFT) ++#define REG_EP_CFG_INTF_NUM_SHIFT 11 ++#define REG_EP_CFG_INTF_NUM_MASK (0xf << REG_EP_CFG_INTF_NUM_SHIFT) ++#define REG_EP_CFG_CFG_NUM_SHIFT 7 ++#define REG_EP_CFG_CFG_NUM_MASK (0xf << REG_EP_CFG_CFG_NUM_SHIFT) ++#define REG_EP_CFG_TYPE_SHIFT 5 ++#define REG_EP_CFG_TYPE_MASK (0x3 << REG_EP_CFG_TYPE_SHIFT) ++#define REG_EP_CFG_DIRN_IN (1 << 4) ++#define REG_EP_CFG_DIRN_OUT 0 ++#define REG_EP_CFG_FIFO_NUM_SHIFT 0 ++#define REG_EP_CFG_FIFO_NUM_MASK (0xf << REG_EP_CFG_FIFO_NUM_SHIFT) ++ ++/* Endpoint Interrupt register definitions */ ++#define REG_EP_INTR_OUT_SHIFT 16 ++#define REG_EP_INTR_OUT_MASK (0xffff << REG_EP_INTR_OUT_SHIFT) ++#define REG_EP_INTR_IN_SHIFT 0 ++#define REG_EP_INTR_IN_MASK (0xffff << REG_EP_INTR_IN_SHIFT) ++ ++/* Device Controller register definitions */ ++#define REG_CFG_ULPI_DDR_ENABLE (1 << 19) ++#define REG_CFG_SET_DESCRIPTOR_ENABLE (1 << 18) ++#define REG_CFG_CSR_PROGRAM_ENABLE (1 << 17) ++#define REG_CFG_HALT_STALL_ENABLE (1 << 16) ++#define REG_CFG_HS_TIMEOUT_CALIB_SHIFT 13 ++#define REG_CFG_HS_TIMEOUT_CALIB_MASK (7 << REG_CFG_HS_TIMEOUT_CALIB_SHIFT) ++#define REG_CFG_FS_TIMEOUT_CALIB_SHIFT 10 ++#define REG_CFG_FS_TIMEOUT_CALIB_MASK (7 << REG_CFG_FS_TIMEOUT_CALIB_SHIFT) ++#define REG_CFG_STATUS_1_ENABLE (1 << 8) ++#define REG_CFG_STATUS_ENABLE (1 << 7) ++#define REG_CFG_UTMI_BI_DIRN_ENABLE (1 << 6) ++#define REG_CFG_UTMI_8BIT_ENABLE (1 << 5) ++#define REG_CFG_SYNC_FRAME_ENABLE (1 << 4) ++#define REG_CFG_SELF_PWR_ENABLE (1 << 3) ++#define REG_CFG_REMOTE_WAKEUP_ENABLE (1 << 2) ++#define REG_CFG_SPD_SHIFT 0 ++#define REG_CFG_SPD_MASK (3 << REG_CFG_SPD_SHIFT) ++#define REG_CFG_SPD_HS (0 << REG_CFG_SPD_SHIFT) ++#define REG_CFG_SPD_FS (1 << REG_CFG_SPD_SHIFT) ++#define REG_CFG_SPD_LS (2 << REG_CFG_SPD_SHIFT) ++#define REG_CFG_SPD_FS_48MHZ (3 << REG_CFG_SPD_SHIFT) ++ ++#define REG_CTRL_DMA_OUT_THRESHOLD_LEN_SHIFT 24 ++#define REG_CTRL_DMA_OUT_THRESHOLD_LEN_MASK (0xff << REG_CTRL_DMA_OUT_THRESHOLD_LEN_SHIFT) ++#define REG_CTRL_DMA_BURST_LEN_SHIFT 16 ++#define REG_CTRL_DMA_BURST_LEN_MASK (0xff << REG_CTRL_DMA_BURST_LEN_SHIFT) ++#define REG_CTRL_OUT_FIFO_FLUSH_ENABLE (1 << 14) ++#define REG_CTRL_CSR_DONE (1 << 13) ++#define REG_CTRL_OUT_NAK_ALL_ENABLE (1 << 12) ++#define REG_CTRL_DISCONNECT_ENABLE (1 << 10) ++#define REG_CTRL_DMA_MODE_ENABLE (1 << 9) ++#define REG_CTRL_DMA_BURST_ENABLE (1 << 8) ++#define REG_CTRL_DMA_OUT_THRESHOLD_ENABLE (1 << 7) ++#define REG_CTRL_DMA_BUFF_FILL_MODE_ENABLE (1 << 6) ++#define REG_CTRL_ENDIAN_BIG_ENABLE (1 << 5) ++#define REG_CTRL_DMA_DESC_UPDATE_ENABLE (1 << 4) ++#define REG_CTRL_DMA_IN_ENABLE (1 << 3) /*TX DMA Enable */ ++#define REG_CTRL_DMA_OUT_ENABLE (1 << 2) /*RX DMA Enable */ ++#define REG_CTRL_RESUME_SIGNAL_ENABLE (1 << 0) ++#define REG_CTRL_LE_ENABLE 0 ++ ++#define REG_STAT_SOF_FRAME_NUM_SHIFT 18 ++#define REG_STAT_SOF_FRAME_NUM_MASK (0x3fff << REG_STAT_SOF_FRAME_NUM_SHIFT) ++#define REG_STAT_REMOTE_WAKEUP_ALLOWED (1 << 17) ++#define REG_STAT_PHY_ERROR (1 << 16) ++#define REG_STAT_OUT_FIFO_EMPTY (1 << 15) ++#define REG_STAT_SPD_SHIFT 13 ++#define REG_STAT_SPD_MASK (3 << REG_STAT_SPD_SHIFT) ++#define REG_STAT_SPD_HS (0 << REG_STAT_SPD_SHIFT) ++#define REG_STAT_SPD_FS (1 << REG_STAT_SPD_SHIFT) ++#define REG_STAT_SPD_LS (2 << REG_STAT_SPD_SHIFT) ++#define REG_STAT_SPD_FS_48MHZ (3 << REG_STAT_SPD_SHIFT) ++#define REG_STAT_BUS_SUSPENDED (1 << 12) ++#define REG_STAT_ALT_NUM_SHIFT 8 ++#define REG_STAT_ALT_NUM_MASK (0xf << REG_STAT_ALT_NUM_SHIFT) ++#define REG_STAT_INTF_NUM_SHIFT 4 ++#define REG_STAT_INTF_NUM_MASK (0xf << REG_STAT_INTF_NUM_SHIFT) ++#define REG_STAT_CFG_NUM_SHIFT 0 ++#define REG_STAT_CFG_NUM_MASK (0xf << REG_STAT_CFG_NUM_SHIFT) ++ ++#define REG_INTR_REMOTE_WAKEUP_DELTA (1 << 7) /*Remote Wakeup Delta*/ ++#define REG_INTR_SPD_ENUM_DONE (1 << 6) /*ENUM Speed Completed*/ ++#define REG_INTR_SOF_RX (1 << 5) /*SOF Token Detected */ ++#define REG_INTR_BUS_SUSPEND (1 << 4) /*SUSPEND State Detected*/ ++#define REG_INTR_BUS_RESET (1 << 3) /*RESET State Detected */ ++#define REG_INTR_BUS_IDLE (1 << 2) /*IDLE State Detected*/ ++#define REG_INTR_SET_INTF_RX (1 << 1) /*Received SET_INTERFACE CMD*/ ++#define REG_INTR_SET_CFG_RX (1 << 0) /*Received SET_CONFIG CMD*/ ++ ++/* DMA Descriptor definitions */ ++#define REG_DMA_STAT_BUF_SHIFT 30 ++#define REG_DMA_STAT_BUF_HOST_READY (0 << REG_DMA_STAT_BUF_SHIFT) ++#define REG_DMA_STAT_BUF_DMA_BUSY (1 << REG_DMA_STAT_BUF_SHIFT) ++#define REG_DMA_STAT_BUF_DMA_DONE (2 << REG_DMA_STAT_BUF_SHIFT) ++#define REG_DMA_STAT_BUF_HOST_BUSY (3 << REG_DMA_STAT_BUF_SHIFT) ++#define REG_DMA_STAT_BUF_MASK (3 << REG_DMA_STAT_BUF_SHIFT) ++#define REG_DMA_STAT_RX_SHIFT 28 ++#define REG_DMA_STAT_RX_SUCCESS (0 << REG_DMA_STAT_RX_SHIFT) ++#define REG_DMA_STAT_RX_ERR_DESC (1 << REG_DMA_STAT_RX_SHIFT) ++#define REG_DMA_STAT_RX_ERR_BUF (3 << REG_DMA_STAT_RX_SHIFT) ++#define REG_DMA_STAT_RX_MASK (3 << REG_DMA_STAT_RX_SHIFT) ++#define REG_DMA_STAT_CFG_NUM_SHIFT 24 ++#define REG_DMA_STAT_CFG_NUM_MASK (0xf << REG_DMA_STAT_CFG_NUM_SHIFT) ++#define REG_DMA_STAT_INTF_NUM_SHIFT 20 ++#define REG_DMA_STAT_INTF_NUM_MASK (0xf << REG_DMA_STAT_INTF_NUM_SHIFT) ++#define REG_DMA_STAT_ALT_NUM_SHIFT 16 ++#define REG_DMA_STAT_ALT_NUM_MASK (0xf << REG_DMA_STAT_ALT_NUM_SHIFT) ++#define REG_DMA_STAT_LAST_DESC (1 << 27) ++#define REG_DMA_STAT_FRAME_NUM_SHIFT 16 ++#define REG_DMA_STAT_FRAME_NUM_MASK (0x7ff << REG_DMA_STAT_FRAME_NUM_SHIFT) ++#define REG_DMA_STAT_BYTE_CNT_SHIFT 0 ++#define REG_DMA_STAT_ISO_PID_SHIFT 14 ++#define REG_DMA_STAT_ISO_PID_MASK (0x3 << REG_DMA_STAT_ISO_PID_SHIFT) ++#define REG_DMA_STAT_ISO_BYTE_CNT_SHIFT REG_DMA_STAT_BYTE_CNT_SHIFT ++#define REG_DMA_STAT_ISO_BYTE_CNT_MASK (0x3fff << REG_DMA_STAT_ISO_BYTE_CNT_SHIFT) ++#define REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT REG_DMA_STAT_BYTE_CNT_SHIFT ++#define REG_DMA_STAT_NON_ISO_BYTE_CNT_MASK (0xffff << REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT) ++ ++/* USB2D IDM definitions */ ++#define IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE (1 << 0) ++#define IPROC_USB2D_IDM_REG_RESET_CTRL_RESET (1 << 0) ++ ++/* Inline Function Definitions */ ++static inline uint ++usbd_reg32_read(volatile uint *reg) ++{ ++ return (le32_to_cpu(*reg)); ++} ++ ++static inline void usbd_reg32_write(volatile uint *reg, uint value) ++{ ++ *reg = cpu_to_le32(value); ++} ++ ++static inline void usbd_reg32_bits_set(volatile uint *reg, uint bits) ++{ ++ uint tmp; ++ tmp = usbd_reg32_read(reg); ++ tmp |= bits; ++ usbd_reg32_write(reg, tmp); ++} ++ ++static inline void usbd_reg32_bits_clear(volatile uint *reg, uint bits) ++{ ++ uint tmp; ++ tmp = usbd_reg32_read(reg); ++ tmp &= ~bits; ++ usbd_reg32_write(reg, tmp); ++} ++ ++static inline void usbd_reg32_bits_modify(volatile uint *reg, uint mask, uint value) ++{ ++ uint tmp; ++ tmp = usbd_reg32_read(reg); ++ tmp &= ~mask; ++ tmp |= value; ++ usbd_reg32_write(reg, tmp); ++} ++ ++#define IPROC_USBD_READ(_r) usbd_reg32_read(&_r) ++#define IPROC_USBD_WRITE(_r, _v) usbd_reg32_write(&_r, _v) ++#define IPROC_USBD_BITS_SET(_r, _b) usbd_reg32_bits_set(&_r, _b) ++#define IPROC_USBD_BITS_CLEAR(_r, _b) usbd_reg32_bits_clear(&_r, _b) ++#define IPROC_USBD_BITS_MODIFY(_r, _m, _v) usbd_reg32_bits_modify(&_r, _m, _v) ++ ++/***************************************************************************** ++* @brief Connect / Disconnect to USB BUS ++*****************************************************************************/ ++static inline void iproc_usbd_bus_conn(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, REG_CTRL_DISCONNECT_ENABLE); ++} ++ ++static inline void iproc_usbd_bus_disconn(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_DISCONNECT_ENABLE); ++} ++ ++/***************************************************************************** ++* @brief USB BUS suspend status ++* @return ++* true : BUS is in suspend state ++* false : BUS is not in suspend state ++*****************************************************************************/ ++static inline bool iproc_usbd_bus_suspend(struct iproc_usbd_regs *base) ++{ ++ return (IPROC_USBD_READ(base->dev_status) & REG_STAT_BUS_SUSPENDED) ? true : false; ++} ++ ++/***************************************************************************** ++* @brief Retrieve setting numbers from last Rx'd SET_CONFIGURATION or ++* SET_INTERFACE request ++* @return ++* Setting Number ++*****************************************************************************/ ++static inline uint iproc_usbd_alt_num(struct iproc_usbd_regs *base) ++{ ++ return ((IPROC_USBD_READ(base->dev_status) & REG_STAT_ALT_NUM_MASK) >> REG_STAT_ALT_NUM_SHIFT); ++} ++ ++static inline uint iproc_usbd_cfg_num(struct iproc_usbd_regs *base) ++{ ++ return ((IPROC_USBD_READ(base->dev_status) & REG_STAT_CFG_NUM_MASK) >> REG_STAT_CFG_NUM_SHIFT); ++} ++ ++static inline uint iproc_usbd_intf_num(struct iproc_usbd_regs *base) ++{ ++ return ((IPROC_USBD_READ(base->dev_status) & REG_STAT_INTF_NUM_MASK) >> REG_STAT_INTF_NUM_SHIFT); ++} ++ ++ ++/***************************************************************************** ++* @brief Disable / Enable DMA operations at the device level (all endpoints) ++*****************************************************************************/ ++static inline void iproc_usbd_dma_dis(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, (REG_CTRL_DMA_IN_ENABLE | REG_CTRL_DMA_OUT_ENABLE)); ++} ++ ++static inline void iproc_usbd_dma_en(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_ctrl, (REG_CTRL_DMA_IN_ENABLE | REG_CTRL_DMA_OUT_ENABLE)); ++} ++ ++static inline bool iproc_usbd_dma_status(struct iproc_usbd_regs *base) ++{ ++ return (IPROC_USBD_READ(base->dev_ctrl) & REG_CTRL_DMA_OUT_ENABLE ? true : false); ++} ++ ++/***************************************************************************** ++* @brief Retrieve Frame number contained in last Rx'd SOF packet ++* @return ++* Frame Number in the following format. ++* bits[13:3] milli-second frame number ++* bits[2:0] micro-frame number ++* @note ++* For full and low speed connections, the microframe number will be zero. ++*****************************************************************************/ ++static inline uint iproc_usbd_last_rx_frame_num(struct iproc_usbd_regs *base) ++{ ++ return((IPROC_USBD_READ(base->dev_status) & REG_STAT_SOF_FRAME_NUM_MASK) >> REG_STAT_SOF_FRAME_NUM_SHIFT); ++} ++ ++/***************************************************************************** ++* @brief Device level interrupt operations ++* @note ++* Use the USBD_IRQ_xxx definitions with these routines. These ++* definitions are bit-wise, and allow operations on multiple interrupts ++* by OR'ing the definitions together. ++* DeviceIrqClear(), DeviceIrqDisable(), DeviceIrqEnable() use their mask ++* parameter to operate only on the interrupts set in the mask. E.g. ++* DeviceIrqEnable( DEVICE_IRQ_SET_INTF ); ++* DeviceIrqEnable( DEVICE_IRQ_SET_CFG ); ++* and ++* DeviceIrqEnable( DEVICE_IRQ_SET_INTF | DEVICE_IRQ_SET_CFG ); ++* are equivalent. ++* DeviceIrqMask() returns a mask of all the interrupts that are enabled. ++* DeviceIrqStatus() returns a mask of all the interrupts that have an active status. ++*****************************************************************************/ ++static inline uint iproc_usbd_irq_active(struct iproc_usbd_regs *base) ++{ ++ return(IPROC_USBD_READ(base->dev_irq_status)); ++} ++ ++static inline void iproc_usbd_irq_clear(struct iproc_usbd_regs *base, uint mask) ++{ ++ IPROC_USBD_WRITE(base->dev_irq_status, mask); ++} ++ ++static inline void iproc_usbd_irq_dis(struct iproc_usbd_regs *base, uint mask) ++{ ++ IPROC_USBD_BITS_SET(base->dev_irq_mask, mask); ++} ++ ++static inline void iproc_usbd_irq_en(struct iproc_usbd_regs *base, uint mask) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_irq_mask, mask); ++} ++static inline uint iproc_usbd_irq_mask(struct iproc_usbd_regs *base) ++{ ++ return((~IPROC_USBD_READ(base->dev_irq_mask)) & USBD_IRQ_ALL); ++} ++ ++/***************************************************************************** ++* @brief Disable / Enable NAK responses for all OUT endpoints. ++*****************************************************************************/ ++static inline void iproc_usbd_nak_response_dis(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, REG_CTRL_OUT_NAK_ALL_ENABLE); ++} ++ ++static inline void iproc_usbd_nak_response_en(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_OUT_NAK_ALL_ENABLE); ++} ++ ++/***************************************************************************** ++* @brief PHY error detected ++*****************************************************************************/ ++static inline bool iproc_usbd_phy_err_detect(struct iproc_usbd_regs *base) ++{ ++ return(IPROC_USBD_READ(base->dev_status) & REG_STAT_PHY_ERROR ? true : false); ++} ++ ++/***************************************************************************** ++* @brief Remote Wakeup operations. ++* DeviceRemoteWakeupEnable() and DeviceRemoteWakeupDisable() are used to ++* specify device if is going to attempt this. ++* DeviceRemoteWakeupAllowed() indicates if host has enabled this feature. ++* The associated DEVICE_IRQ_REMOTEWAKEUP_DELTA can be used to determine ++* changes to the status of this feature. ++* DeviceRemoteWakeupStart(); delayMsec(1); DeviceRemoteWakeupStop(); is ++* used for controlling the wakeup signalling. ++*****************************************************************************/ ++static inline bool iproc_usbd_wakeup_allow(struct iproc_usbd_regs *base) ++{ ++ return(IPROC_USBD_READ(base->dev_status) & REG_STAT_REMOTE_WAKEUP_ALLOWED ? true : false); ++} ++ ++static inline void iproc_usbd_wakeup_dis(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_cfg, REG_CFG_REMOTE_WAKEUP_ENABLE); ++} ++ ++static inline void iproc_usbd_wakeup_en(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_REMOTE_WAKEUP_ENABLE); ++} ++ ++static inline void iproc_usbd_wakeup_start(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_RESUME_SIGNAL_ENABLE); ++} ++ ++static inline void iproc_usbd_wakeup_stop(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, REG_CTRL_RESUME_SIGNAL_ENABLE); ++} ++ ++/***************************************************************************** ++* @brief Control whether or not device advertises itself as self-powered. ++*****************************************************************************/ ++static inline void iproc_usbd_self_pwr_dis(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_cfg, REG_CFG_SELF_PWR_ENABLE); ++} ++ ++static inline void iproc_usbd_self_pwr_en(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_SELF_PWR_ENABLE); ++} ++ ++/***************************************************************************** ++* @brief Control whether or not device SET DESCRIPTOR support is enabled. ++* If disabled, STALL will be issued upon receipt of a SET DESCRIPTOR request. ++*****************************************************************************/ ++static inline void iproc_usbd_set_desc_dis(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_cfg, REG_CFG_SET_DESCRIPTOR_ENABLE); ++} ++ ++static inline void iproc_usbd_set_desc_en(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_SET_DESCRIPTOR_ENABLE); ++} ++ ++/***************************************************************************** ++* @brief Device SET configuration or SET interface has completed. ++* If disabled, STALL will be issued upon receipt of a SET DESCRIPTOR request. ++*****************************************************************************/ ++static inline void iproc_usbd_setup_done(struct iproc_usbd_regs *base) ++{ ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_CSR_DONE); ++} ++ ++/***************************************************************************** ++* @brief Link speed routines. ++* Use the usbDevHw_DEVICE_SPEED_xxx definitions with these routines. These ++* DeviceSpeedRequested() indicates the desired link speed. ++* DeviceSpeedEnumerated() returns the speed negotiated with the host. ++* The associated DEVICE_IRQ_SPEED_ENUM_DONE can be used to determine ++* when speed negotiation has completed. ++*****************************************************************************/ ++static inline uint iproc_usbd_speed_get(struct iproc_usbd_regs *base) ++{ ++ switch(IPROC_USBD_READ(base->dev_status) & REG_STAT_SPD_MASK) { ++ case REG_STAT_SPD_LS: ++ return(USB_SPEED_LOW); ++ ++ case REG_STAT_SPD_HS: ++ return(USB_SPEED_HIGH); ++ ++ case REG_STAT_SPD_FS: ++ case REG_STAT_SPD_FS_48MHZ: ++ return(USB_SPEED_FULL); ++ } ++ ++ return USB_SPEED_FULL; ++} ++ ++static inline void iproc_usbd_speed_req(struct iproc_usbd_regs *base, uint speed) ++{ ++ IPROC_USBD_BITS_CLEAR(base->dev_cfg, REG_CFG_SPD_MASK); ++ ++ switch(speed) { ++ case USB_SPEED_LOW: ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_SPD_LS); ++ break; ++ ++ case USB_SPEED_HIGH: ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_SPD_HS); ++ break; ++ ++ case USB_SPEED_FULL: ++ default: ++ IPROC_USBD_BITS_SET(base->dev_cfg, REG_CFG_SPD_FS); ++ break; ++ } ++} ++ ++/***************************************************************************** ++* @brief Finalize (terminate) / Initialize Endpoint operations ++* @param num - Endpoint number ++* @param dirn - Endpoint direction. See ENDPT_DIRN_xxx definitions ++* @param dirn - Endpoint type. See ENDPT_TYPE_xxx definitions ++* @param dirn - Endpoint max packet size. ++*****************************************************************************/ ++static inline void iproc_usbd_ep_ops_finish(struct iproc_usbd_regs *base, uint num) ++{ ++} ++ ++static inline void iproc_usbd_ep_ops_init(struct iproc_usbd_regs *base, uint num, uint type, uint dirn, uint maxPktSize) ++{ ++ if ((type == USB_ENDPOINT_XFER_CONTROL) || (dirn == USB_DIR_OUT)) { ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].ctrl, (type << REG_EP_FIFO_CTRL_TYPE_SHIFT)); ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].status, IPROC_USBD_READ(base->ep_fifo_out[num].status)); ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].size1, 0); ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].size2, ((maxPktSize >> 2) << 16) | maxPktSize); ++#if USBD_MULTI_RX_FIFO ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].size2, ((maxPktSize + 3) >> 2) << REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT)); ++#endif ++ } ++ ++ if ((type == USB_ENDPOINT_XFER_CONTROL) || (dirn == USB_DIR_IN)) { ++ IPROC_USBD_WRITE(base->ep_fifo_in[num].ctrl, (type << REG_EP_FIFO_CTRL_TYPE_SHIFT)); ++ IPROC_USBD_WRITE(base->ep_fifo_in[num].size2, (maxPktSize << REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT)); ++ IPROC_USBD_WRITE(base->ep_fifo_in[num].size1, (maxPktSize >> 2)); ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, (REG_EP_FIFO_CTRL_NAK_SET | REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE)); ++ } ++ ++ IPROC_USBD_WRITE(base->ep_cfg[num], (num << REG_EP_CFG_FIFO_NUM_SHIFT) | ++ (type << REG_EP_CFG_TYPE_SHIFT) | ++ (maxPktSize << REG_EP_CFG_PKT_MAX_SHIFT) | ++ (dirn == USB_DIR_OUT ? REG_EP_CFG_DIRN_OUT : REG_EP_CFG_DIRN_IN)); ++} ++ ++/***************************************************************************** ++* @brief Endpoint Configuration / Interface / Alternate number operations ++* @param num - Endpoint number ++* @param cfg - Configuration number ++* @param intf - Interface number ++* @param alt - Alternate number ++*****************************************************************************/ ++static inline void iproc_usbd_ep_alt_set(struct iproc_usbd_regs *base, uint num, uint alt) ++{ ++ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], REG_EP_CFG_ALT_NUM_MASK, (alt << REG_EP_CFG_ALT_NUM_SHIFT)); ++} ++ ++static inline void iproc_usbd_ep_cfg_set(struct iproc_usbd_regs *base, uint num, uint cfg) ++{ ++ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], REG_EP_CFG_CFG_NUM_MASK, (cfg << REG_EP_CFG_CFG_NUM_SHIFT)); ++} ++ ++static inline void iproc_usbd_ep_intf_set(struct iproc_usbd_regs *base, uint num, uint intf) ++{ ++ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], REG_EP_CFG_INTF_NUM_MASK, (intf << REG_EP_CFG_INTF_NUM_SHIFT)); ++} ++ ++ ++/***************************************************************************** ++* @brief Endpoint DMA routines ++* @param num - Endpoint number ++* @param addr - physical address of buffer or descriptor ++*****************************************************************************/ ++static inline void iproc_usbd_ep_dma_dis(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) { ++#if USBD_MULTI_RX_FIFO ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_OUT_DMA_ENABLE); ++#else ++ /* ++ * With a single RX FIFO, do not want to do anything, as there might be another OUT capable ++ * endpoint still active and wanting DMA enabled. If theory this should be OK, as long as ++ * the DMA descriptor buffer status fields are the last thing updated before being set to ++ * HOST ready, or the first thing updated when being set to HOST busy. Hopefully no ++ * situations arise such that there's contention with the hardware with doing this. ++ */ ++#endif ++ } else { ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_IN_DMA_ENABLE); ++ } ++} ++ ++static inline void iproc_usbd_ep_dma_en(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) { ++#if USBD_MULTI_RX_FIFO ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_OUT_DMA_ENABLE); ++#else ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_DMA_OUT_ENABLE); ++#endif ++ } else { ++ /* Set the Poll bit in the control register */ ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_IN_DMA_ENABLE); ++ } ++} ++ ++static inline void iproc_usbd_ep_dma_buf_addr_set(struct iproc_usbd_regs *base, uint num, uint dirn, void *addr) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].buf_addr, (uint)addr); ++} ++ ++static inline void iproc_usbd_ep_dma_desc_addr_set(struct iproc_usbd_regs *base, uint num, uint dirn, void *addr) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].desc_addr, (uint)addr); ++ else ++ IPROC_USBD_WRITE(base->ep_fifo_in[num].desc_addr, (uint)addr); ++} ++ ++/***************************************************************************** ++* @brief Endpoint FIFO routines ++* @param num - Endpoint number ++* @note The flush operation is a state. Once enabled, FIFO contents are discared ++* until disabled. Usually enable upon endpoint termination or error, and ++* then disable once operations are to resume normally. ++*****************************************************************************/ ++static inline bool iproc_usbd_ep_fifo_empty(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) { ++#if USBD_MULTI_RX_FIFO ++ return(base->ep_fifo_out[num].status & REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY ? true : false); ++#else ++ return(base->dev_status & REG_STAT_OUT_FIFO_EMPTY ? true : false); ++#endif ++ } ++ ++ return(base->ep_fifo_in[num].status & REG_EP_FIFO_STATUS_IN_FIFO_EMPTY ? true : false); ++} ++ ++static inline void iproc_usbd_ep_fifo_flush_dis(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) { ++#if USBD_MULTI_RX_FIFO ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE); ++#else ++ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, REG_CTRL_OUT_FIFO_FLUSH_ENABLE); ++#endif ++ } ++ else { ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); ++ } ++} ++ ++static inline void iproc_usbd_ep_fifo_flush_en(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) { ++#if USBD_MULTI_RX_FIFO ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE); ++#else ++ IPROC_USBD_BITS_SET(base->dev_ctrl, REG_CTRL_OUT_FIFO_FLUSH_ENABLE); ++#endif ++ } else { ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); ++ } ++} ++ ++/***************************************************************************** ++* @brief Endpoint Frame Number routines ++* @param num - Endpoint number ++* @return Frame number of last packet received on the endpoint, and in the following format. ++* bits[13:3] milli-second frame number ++* bits[2:0] micro-frame number ++* @note Really only applicable to OUT endpoints. IN will always return 0. ++*****************************************************************************/ ++static inline uint iproc_usbd_ep_frame_num(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ return((IPROC_USBD_READ(base->ep_fifo_out[num].size1) & REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_MASK) >> ++ REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_SHIFT); ++ ++ return(0); ++} ++ ++/***************************************************************************** ++* @brief Endpoint IRQ / status routines ++* @param num - Endpoint number ++* @note ++* Cannot set specific status for Endpoint interrupts. Can only do operations ++* in a global sense. Once an interrupt occurs for an endpoint, the endpoint ++* status has to be checked for the particular type of interrupt that occurred. ++* ++* The iproc_usbd_ep_irq_en() and iproc_usbd_ep_irq_dis() are used for ++* operations on a specific endpoint. These routines may or may not be used in ++* the context of interrupt processing. ++* ++* Use the usbDevHw_EndptIrqListXxx() routines for operations using a bit-wise ++* list of endpoints (bit 0 for endpoint 0, etc.). Typical use would be for ++* interrupt processing. ++* ++* Use the USBD_EP_STAT_xxx definitions with the status routines. These ++* definitions are bit-wise, and allow operations on multiple conditions ++* by OR'ing the definitions together. ++*****************************************************************************/ ++static inline void iproc_usbd_ep_irq_clear(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_WRITE(base->ep_irq_status, (1 << num) << REG_EP_INTR_OUT_SHIFT); ++ else ++ IPROC_USBD_WRITE(base->ep_irq_status, (1 << num) << REG_EP_INTR_IN_SHIFT); ++} ++ ++static inline void iproc_usbd_ep_irq_dis(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_SET(base->ep_irq_mask, ((1 << num) << REG_EP_INTR_OUT_SHIFT)); ++ else ++ IPROC_USBD_BITS_SET(base->ep_irq_mask, ((1 << num) << REG_EP_INTR_IN_SHIFT)); ++} ++ ++static inline void iproc_usbd_ep_irq_en(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_CLEAR(base->ep_irq_mask, ((1 << num) << REG_EP_INTR_OUT_SHIFT)); ++ else ++ IPROC_USBD_BITS_CLEAR(base->ep_irq_mask, ((1 << num) << REG_EP_INTR_IN_SHIFT)); ++} ++ ++static inline uint iproc_usbd_ep_irq_list_active(struct iproc_usbd_regs *base, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ return((IPROC_USBD_READ(base->ep_irq_status) & REG_EP_INTR_OUT_MASK) >> REG_EP_INTR_OUT_SHIFT); ++ ++ return((IPROC_USBD_READ(base->ep_irq_status) & REG_EP_INTR_IN_MASK) >> REG_EP_INTR_IN_SHIFT); ++} ++ ++static inline void iproc_usbd_ep_irq_list_clear(struct iproc_usbd_regs *base, uint dirn, uint mask) ++{ ++ if (dirn == USB_DIR_OUT) /*strat from bit 16 */ ++ IPROC_USBD_WRITE(base->ep_irq_status, (mask << REG_EP_INTR_OUT_SHIFT)); ++ else /* start from bit 0 */ ++ IPROC_USBD_WRITE(base->ep_irq_status, (mask << REG_EP_INTR_IN_SHIFT)); ++} ++ ++static inline uint iproc_usbd_ep_stat_active(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) /* End Point Status register */ ++ return(IPROC_USBD_READ(base->ep_fifo_out[num].status)); ++ ++ return(IPROC_USBD_READ(base->ep_fifo_in[num].status)); ++} ++ ++static inline void iproc_usbd_ep_stat_clear(struct iproc_usbd_regs *base, uint num, uint dirn, uint mask) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_WRITE(base->ep_fifo_out[num].status, mask); ++ else ++ IPROC_USBD_WRITE(base->ep_fifo_in[num].status, mask); ++} ++ ++/***************************************************************************** ++* @brief Endpoint NAK routines ++* @param num - Endpoint number ++* @note A NAK response can be enabled by the application by the EndptNakEnable(). ++* The EndptNakInProgress() is used to determine if the controller is ++* currently actively sending NAKs. This may have been a result of the ++* EndptNakEnable() or automatically by the controller under certain ++* conditions. The EndptNakClear() must be used to terminate the NAKs. ++*****************************************************************************/ ++static inline void iproc_usbd_ep_nak_clear(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_NAK_CLEAR); ++ else ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_NAK_CLEAR); ++} ++ ++static inline void iproc_usbd_ep_nak_en(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_NAK_SET); ++ else ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_NAK_SET); ++} ++ ++static inline void iproc_usbd_ep_nak_dis(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_NAK_SET); ++ else ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_NAK_SET); ++} ++ ++static inline bool iproc_usbd_ep_nak_progress(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ return (IPROC_USBD_READ(base->ep_fifo_out[num].ctrl) & REG_EP_FIFO_CTRL_NAK_IN_PROGRESS) ? true : false; ++ ++ return (IPROC_USBD_READ(base->ep_fifo_in[num].ctrl) & REG_EP_FIFO_CTRL_NAK_IN_PROGRESS) ? true : false; ++} ++ ++/***************************************************************************** ++* @brief Endpoint Stall routines ++* Disable / Enable STALL responses (halt feature) on a given endpoint. ++* @param num - Endpoint number ++*****************************************************************************/ ++static inline void iproc_usbd_ep_stall_dis(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_STALL_ENABLE); ++ else ++ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_STALL_ENABLE); ++} ++ ++static inline void iproc_usbd_ep_stall_en(struct iproc_usbd_regs *base, uint num, uint dirn) ++{ ++#if USBD_MULTI_RX_FIFO ++ if (!(IPROC_USBD_READ(base->ep_fifo_out[num].status) & REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY)) ++#else ++ if (!(IPROC_USBD_READ(base->dev_status) & REG_STAT_OUT_FIFO_EMPTY)) ++#endif ++ return; ++ ++ if (dirn == USB_DIR_OUT) ++ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, REG_EP_FIFO_CTRL_STALL_ENABLE); ++ else ++ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, REG_EP_FIFO_CTRL_STALL_ENABLE); ++} ++ ++ ++/***************************************************************************** ++* @brief Initialize device controller operations ++*****************************************************************************/ ++static inline void iproc_usbd_ops_init(struct iproc_usbd_regs *base) ++{ ++ int idx; ++ ++ iproc_usbd_dma_dis(base); ++ iproc_usbd_irq_dis(base, USBD_IRQ_ALL); ++ iproc_usbd_irq_clear(base, USBD_IRQ_ALL); ++ ++ /* @todo Create and use usbDevHw_EndptIrqListDisable?? */ ++ for (idx = 0; idx < USBD_EP_CFG_CNT; idx++) { ++ iproc_usbd_ep_irq_dis(base, idx, USB_DIR_IN); ++ iproc_usbd_ep_irq_clear(base, idx, USB_DIR_IN); ++ iproc_usbd_ep_stat_clear(base, idx, USB_DIR_IN, ++ iproc_usbd_ep_stat_active(base, idx, USB_DIR_IN)); ++ ++ iproc_usbd_ep_irq_dis(base, idx, USB_DIR_OUT); ++ iproc_usbd_ep_irq_clear(base, idx, USB_DIR_OUT); ++ iproc_usbd_ep_stat_clear(base, idx, USB_DIR_OUT, ++ iproc_usbd_ep_stat_active(base, idx, USB_DIR_OUT)); ++ } ++ ++ IPROC_USBD_WRITE(base->dev_cfg, (REG_CFG_SET_DESCRIPTOR_ENABLE | ++ REG_CFG_UTMI_8BIT_ENABLE | ++ REG_CFG_CSR_PROGRAM_ENABLE | ++ REG_CFG_SPD_HS)); ++ ++ IPROC_USBD_WRITE(base->dev_ctrl, (REG_CTRL_LE_ENABLE | ++ REG_CTRL_DISCONNECT_ENABLE | ++ REG_CTRL_DMA_MODE_ENABLE | ++ REG_CTRL_DMA_IN_ENABLE | ++ REG_CTRL_DMA_OUT_ENABLE | ++ REG_CTRL_DMA_DESC_UPDATE_ENABLE | ++ REG_CTRL_OUT_NAK_ALL_ENABLE | ++ REG_CTRL_DMA_OUT_THRESHOLD_LEN_MASK | ++ REG_CTRL_DMA_BURST_LEN_MASK | ++#if !USBD_MULTI_RX_FIFO ++ REG_CTRL_OUT_FIFO_FLUSH_ENABLE | ++#endif ++ REG_CTRL_DMA_BURST_ENABLE)); ++ ++ IPROC_USBD_WRITE(base->dev_irq_mask, (REG_INTR_BUS_IDLE | REG_INTR_SOF_RX)); ++ IPROC_USBD_WRITE(base->ep_irq_mask,0); ++} ++ ++/***************************************************************************** ++* @brief Disable / Enable USB device ++*****************************************************************************/ ++static inline void iproc_usbd_dis(struct iproc_usbd_idm_regs *idm_base) ++{ ++ /* reset usb device */ ++ IPROC_USBD_BITS_SET(idm_base->reset_ctrl, IPROC_USB2D_IDM_REG_RESET_CTRL_RESET); ++ ++ /* disable usb device clock */ ++ IPROC_USBD_BITS_CLEAR(idm_base->io_ctrl, IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE); ++ mdelay(10); ++} ++ ++static inline void iproc_usbd_en(struct iproc_usbd_idm_regs *idm_base) ++{ ++ /* enable usb device clock */ ++ IPROC_USBD_BITS_SET(idm_base->io_ctrl, IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE); ++ mdelay(10); ++ ++ /* get usb device out of reset */ ++ IPROC_USBD_BITS_CLEAR(idm_base->reset_ctrl, IPROC_USB2D_IDM_REG_RESET_CTRL_RESET); ++ mdelay(100); ++} ++ ++#endif /* _USBD_REGS_H_ */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +--- a/drivers/usb/host/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/host/Kconfig 2018-05-10 11:31:33.793404173 +0800 +@@ -214,6 +214,13 @@ config USB_EHCI_HCD_STI + Enable support for the on-chip EHCI controller found on + STMicroelectronics consumer electronics SoC's. + ++config USB_EHCI_XGS_IPROC ++ bool "BRCM XGS iProc EHCI patch" ++ depends on (ARCH_XGS_IPROC && USB_EHCI_HCD_PLATFORM) ++ default n ++ ---help--- ++ This option is for BRCM XGS iProc EHCI patch ++ + config USB_EHCI_HCD_AT91 + tristate "Support for Atmel on-chip EHCI USB controller" + depends on USB_EHCI_HCD && ARCH_AT91 +@@ -591,6 +598,13 @@ config USB_OHCI_HCD_PLATFORM + + If unsure, say N. + ++config USB_OHCI_XGS_IPROC ++ bool "BRCM XGS iProc OHCI patch" ++ depends on (ARCH_XGS_IPROC && USB_OHCI_HCD_PLATFORM) ++ default n ++ ---help--- ++ This option is for BRCM XGS iProc OHCI patch ++ + config USB_OCTEON_OHCI + bool "Octeon on-chip OHCI support (DEPRECATED)" + depends on CAVIUM_OCTEON_SOC +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +--- a/drivers/usb/host/ehci-platform.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/host/ehci-platform.c 2018-05-10 11:31:33.793404173 +0800 +@@ -43,6 +43,12 @@ + #define EHCI_MAX_RSTS 4 + #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) + ++#if IS_ENABLED(CONFIG_USB_EHCI_XGS_IPROC) ++#include ++#include ++#define BCM_USB_FIFO_THRESHOLD 0x00800040 ++#endif ++ + struct ehci_platform_priv { + struct clk *clks[EHCI_MAX_CLKS]; + struct reset_control *rsts[EHCI_MAX_RSTS]; +@@ -152,10 +158,24 @@ static int ehci_platform_probe(struct pl + struct ehci_platform_priv *priv; + struct ehci_hcd *ehci; + int err, irq, phy_num, clk = 0, rst; ++ struct usb_phy __maybe_unused *phy; + + if (usb_disabled()) + return -ENODEV; + ++ if (IS_ENABLED(CONFIG_USB_EHCI_XGS_IPROC)) { ++ phy = devm_usb_get_phy_by_phandle(&dev->dev, "usb-phy", 0); ++ if (IS_ERR(phy)) { ++ dev_err(&dev->dev, "unable to find transceiver\n"); ++ return PTR_ERR(phy); ++ } ++ ++ if (phy->flags != IPROC_USB_MODE_HOST) ++ return -ENODEV; ++ ++ usb_phy_init(phy); ++ } ++ + /* + * Use reasonable defaults so platforms don't have to provide these + * with DT probing on ARM. +@@ -296,12 +316,20 @@ static int ehci_platform_probe(struct pl + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + ++ if (IS_ENABLED(CONFIG_USB_EHCI_XGS_IPROC)) ++ hcd->usb_phy = phy; ++ + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) + goto err_power; + + device_wakeup_enable(hcd->self.controller); + device_enable_async_suspend(hcd->self.controller); ++ ++ if (IS_ENABLED(CONFIG_USB_EHCI_XGS_IPROC)) ++ ehci_writel(ehci, BCM_USB_FIFO_THRESHOLD, ++ &ehci->regs->reserved4[6]); ++ + platform_set_drvdata(dev, hcd); + + return err; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +--- a/drivers/usb/host/ohci-platform.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/host/ohci-platform.c 2018-05-10 11:31:33.805404187 +0800 +@@ -37,6 +37,13 @@ + #define OHCI_MAX_RESETS 2 + #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv) + ++#if IS_ENABLED(CONFIG_USB_OHCI_XGS_IPROC) ++#include ++#include ++#define UHCRHDA_REG_OFFSET 0x48 ++#define UHCRHDA_OCPM BIT(11) ++#endif ++ + struct ohci_platform_priv { + struct clk *clks[OHCI_MAX_CLKS]; + struct reset_control *resets[OHCI_MAX_RESETS]; +@@ -120,10 +127,24 @@ static int ohci_platform_probe(struct pl + struct ohci_platform_priv *priv; + struct ohci_hcd *ohci; + int err, irq, phy_num, clk = 0, rst = 0; ++ struct usb_phy __maybe_unused *phy; + + if (usb_disabled()) + return -ENODEV; + ++ if (IS_ENABLED(CONFIG_USB_OHCI_XGS_IPROC)) { ++ phy = devm_usb_get_phy_by_phandle(&dev->dev, "usb-phy", 0); ++ if (IS_ERR(phy)) { ++ dev_err(&dev->dev, "unable to find transceiver\n"); ++ return PTR_ERR(phy); ++ } ++ ++ if (phy->flags != IPROC_USB_MODE_HOST) ++ return -ENODEV; ++ ++ usb_phy_init(phy); ++ } ++ + /* + * Use reasonable defaults so platforms don't have to provide these + * with DT probing on ARM. +@@ -264,6 +285,13 @@ static int ohci_platform_probe(struct pl + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + ++ if (IS_ENABLED(CONFIG_USB_OHCI_XGS_IPROC)) { ++ if (of_find_property(dev->dev.of_node, "iproc-ocpm-fix", NULL)) ++ writel(readl(hcd->regs + UHCRHDA_REG_OFFSET) | ++ UHCRHDA_OCPM, hcd->regs + UHCRHDA_REG_OFFSET); ++ hcd->usb_phy = phy; ++ } ++ + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) + goto err_power; +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig +--- a/drivers/usb/phy/Kconfig 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/phy/Kconfig 2018-05-10 11:31:33.833404217 +0800 +@@ -202,4 +202,18 @@ config USB_ULPI_VIEWPORT + Provides read/write operations to the ULPI phy register set for + controllers with a viewport register (e.g. Chipidea/ARC controllers). + ++config USBPHY_XGS_IPROC ++ tristate "BRCM iProc USB controller support" ++ depends on ARCH_XGS_IPROC ++ select USB_PHY ++ help ++ BRCM iProc USB controller support ++ ++config USB_XGS_IPROC_DRD ++ tristate "BRCM iProc USB DRD controller support" ++ depends on ARCH_XGS_IPROC ++ select USB_PHY ++ help ++ BRCM iProc USB DRD controller support ++ + endmenu +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile +--- a/drivers/usb/phy/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/usb/phy/Makefile 2018-05-10 11:31:33.833404217 +0800 +@@ -26,3 +26,5 @@ obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-us + obj-$(CONFIG_USB_ULPI) += phy-ulpi.o + obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o + obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o ++obj-$(CONFIG_USBPHY_XGS_IPROC) += phy-xgs-iproc.o ++obj-$(CONFIG_USB_XGS_IPROC_DRD) += phy-xgs-iproc-drd.o +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/phy-xgs-iproc-drd.c b/drivers/usb/phy/phy-xgs-iproc-drd.c +--- a/drivers/usb/phy/phy-xgs-iproc-drd.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/phy/phy-xgs-iproc-drd.c 2018-05-10 11:31:33.837404222 +0800 +@@ -0,0 +1,270 @@ ++/* ++ * $Copyright Open Broadcom Corporation$ ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define ICFG_USB_CTRL_ADDR(base) (base + 0x00) ++#define ICFG_USB_CTRL__DRD_FORCE_HOST_MODE 6 ++#define ICFG_USB_CTRL__DRD_FORCE_DEVICE_MODE 5 ++#define ICFG_USB_CTRL__XHC_CSR_RESET 4 ++#define ICFG_USB_CTRL__BDC_CSR_RESET 3 ++#define ICFG_USB_CTRL__DRD_SOFT_RESET 2 ++#define ICFG_USB_CTRL__XHC_SOFT_RESET 1 ++#define ICFG_USB_CTRL__BDC_SOFT_RESET 0 ++ ++#define IPROC_WRAP_USBPHY_CTRL_0_ADDR(base) (base + 0x00) ++#define IPROC_WRAP_USBPHY_CTRL_0__PHY_ISO 18 ++#define IPROC_WRAP_USBPHY_CTRL_0__PLL_CTRL_45 17 ++#define IPROC_WRAP_USBPHY_CTRL_0__PLL_SUSPEND_EN 16 ++#define IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB 15 ++#define IPROC_WRAP_USBPHY_CTRL_0__RESETB 14 ++#define IPROC_WRAP_USBPHY_CTRL_2_ADDR(base) (base + 0x08) ++#define IPROC_WRAP_USBPHY_CTRL_2__AFE_LDO_PWRDWNB 2 ++#define IPROC_WRAP_USBPHY_CTRL_2__AFE_PLL_PWRDWNB 1 ++#define IPROC_WRAP_USBPHY_CTRL_2__AFE_BG_PWRDWNB 0 ++#define IPROC_WRAP_MISC_STATUS_0_ADDR(base) (base + 0x1c) ++#define IPROC_WRAP_MISC_STATUS_0__USBPHY_PLL_LOCK 0 ++#define IPROC_WRAP_MISC_STATUS_1_ADDR(base) (base + 0x20) ++ ++struct iproc_usb_priv { ++ struct usb_phy phy; ++ struct device *dev; ++ struct device_node *dn; ++ void __iomem *wrap_base; ++ void __iomem *icfg_usb_base; ++}; ++ ++extern void __iomem *get_iproc_wrap_ctrl_base(void); ++ ++/*************************************************************************** ++**************************************************************************** ++***************************************************************************/ ++static int iproc_usb_phy_init(struct usb_phy *phy) ++{ ++ struct iproc_usb_priv *iproc_usb_data = container_of(phy, struct iproc_usb_priv, phy); ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ struct device *dev = iproc_usb_data->dev; ++ uint val; ++ ulong mask, count = 0; ++ ++ if (!wrap_base) { ++ return -EINVAL; ++ } ++ ++ /* FIXME. PHY initial sequence, need to get the sequence from DE */ ++ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__PHY_ISO); ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__PLL_SUSPEND_EN); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB); ++ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__RESETB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_2__AFE_BG_PWRDWNB); ++ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_2__AFE_LDO_PWRDWNB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ udelay(10); ++ ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_2__AFE_BG_PWRDWNB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ udelay(150); ++ ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_2__AFE_LDO_PWRDWNB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ udelay(160); ++ ++ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__PHY_ISO); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ udelay(20); ++ ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ mdelay(20); ++ ++ ++ /* check pll_lock */ ++ mask = (1 << IPROC_WRAP_MISC_STATUS_0__USBPHY_PLL_LOCK); ++ do { ++ val = readl_relaxed(IPROC_WRAP_MISC_STATUS_0_ADDR(wrap_base)); ++ if ((val & mask) == mask) { ++ break; ++ } else { ++ udelay(10); ++ count ++; ++ } ++ } while(count <= 10); ++ if (count > 10) { ++ dev_err(dev, "%s : PLL not lock! IPROC_WRAP_MISC_STATUS_0 = 0x%.8x\n", ++ __FUNCTION__, val); ++ } ++ ++ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__RESETB); ++ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ udelay(2); ++ ++ return 0; ++} ++ ++static int iproc_usb_reset(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *icfg_usb_base = iproc_usb_data->icfg_usb_base; ++ uint val; ++ ++ if (!icfg_usb_base) { ++ return -EINVAL; ++ } ++ ++ /* Put DRD into reset state */ ++ val = readl_relaxed(ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ val |= (1 << ICFG_USB_CTRL__DRD_SOFT_RESET); ++ writel_relaxed(val, ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ ++ /* Put BDC and XHC into reset state */ ++ val = readl_relaxed(ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ val |= (1 << ICFG_USB_CTRL__BDC_SOFT_RESET); ++ val |= (1 << ICFG_USB_CTRL__XHC_SOFT_RESET); ++ writel_relaxed(val, ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ ++ mdelay(10); ++ ++ /* Get the BDC and XHC out of reset */ ++ val = readl_relaxed(ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ val &= ~(1 << ICFG_USB_CTRL__BDC_SOFT_RESET); ++ val &= ~(1 << ICFG_USB_CTRL__XHC_SOFT_RESET); ++ writel_relaxed(val, ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ ++ /* Get the DRD out of reset */ ++ val = readl_relaxed(ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ val &= ~(1 << ICFG_USB_CTRL__DRD_SOFT_RESET); ++ writel_relaxed(val, ICFG_USB_CTRL_ADDR(icfg_usb_base)); ++ ++ return 0; ++} ++ ++static int xgs_iproc_drd_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *dn = pdev->dev.of_node; ++ struct iproc_usb_priv *iproc_usb_data; ++ int ret; ++ ++ if (!of_device_is_available(dn)) { ++ return -ENODEV; ++ } ++ ++ iproc_usb_data = devm_kzalloc(dev, sizeof(*iproc_usb_data), GFP_KERNEL); ++ if (!iproc_usb_data) { ++ dev_err(dev, "devm_kzalloc() failed\n" ); ++ return -ENOMEM; ++ } ++ memset(iproc_usb_data, 0, sizeof(*iproc_usb_data)); ++ platform_set_drvdata(pdev, iproc_usb_data); ++ ++ iproc_usb_data->dev = dev; ++ ++ iproc_usb_data->wrap_base = get_iproc_wrap_ctrl_base(); ++ if (!iproc_usb_data->wrap_base) { ++ dev_err(&pdev->dev, "can't iomap usb phy base address\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ iproc_usb_data->icfg_usb_base = (void *)of_iomap(dn, 1); ++ if (!iproc_usb_data->icfg_usb_base) { ++ dev_err(&pdev->dev, "can't iomap icfg usb base address\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ iproc_usb_data->phy.dev = dev; ++ iproc_usb_data->phy.type = USB_PHY_TYPE_USB2; ++ iproc_usb_data->phy.init = iproc_usb_phy_init; ++ ++ iproc_usb_reset(iproc_usb_data); ++ iproc_usb_phy_init(&iproc_usb_data->phy); ++ ++ ret = usb_add_phy_dev(&iproc_usb_data->phy); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to add the phy device\n"); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ if (iproc_usb_data->icfg_usb_base) { ++ iounmap(iproc_usb_data->icfg_usb_base); ++ } ++ if (iproc_usb_data) { ++ iounmap(iproc_usb_data); ++ } ++ ++ return ret; ++} ++ ++static int xgs_iproc_drd_remove(struct platform_device *pdev) ++{ ++ struct iproc_usb_priv *iproc_usb_data = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(&iproc_usb_data->phy); ++ ++ platform_set_drvdata(pdev, NULL); ++ if (iproc_usb_data->icfg_usb_base) { ++ iounmap(iproc_usb_data->icfg_usb_base); ++ } ++ ++ if (iproc_usb_data) { ++ iounmap(iproc_usb_data); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id xgs_iproc_drd_dt_ids[] = { ++ { .compatible = "brcm,usb-phy,hx5", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, xgs_iproc_drd_dt_ids); ++ ++static struct platform_driver xgs_iproc_drd_driver = ++{ ++ .driver = { ++ .name = "usb-phy", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(xgs_iproc_drd_dt_ids), ++ }, ++ .probe = xgs_iproc_drd_probe, ++ .remove = xgs_iproc_drd_remove, ++}; ++ ++module_platform_driver(xgs_iproc_drd_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB DRD controller driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/phy-xgs-iproc.c b/drivers/usb/phy/phy-xgs-iproc.c +--- a/drivers/usb/phy/phy-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/usb/phy/phy-xgs-iproc.c 2018-05-10 11:31:33.837404222 +0800 +@@ -0,0 +1,701 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define USB2_IDM_IO_CONTROL_DIRECT_ADDR(base) (base + 0x408) ++#define USB2_IDM_RESET_CONTROL_ADDR(base) (base + 0x800) ++#define IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK BIT(1) ++#define USB2_IDM_RESET_CONTROL__RESET BIT(0) ++#define USB2_IDM_IO_CONTROL_DIRECT__clk_enable BIT(0) ++ ++/* HX4 */ ++#define HX4_WRAP_XGPLL_CTRL_0_ADDR(base) (base + 0x1c) ++#define HX4_WRAP_XGPLL_CTRL_4_ADDR(base) (base + 0x2c) ++#define HX4_WRAP_USBPHY_CTRL_ADDR(base) (base + 0x34) ++#define HX4_WRAP_MISC_STATUS_ADDR(base) (base + 0x38) ++#define IPROC_CLK_NDIV_40 0x80 ++#define IPROC_CLK_NDIV_20 0x8C ++#define USB_CLK_NDIV_MASK 0xFE7FFE00 ++#define USB_CLK_PLL_RESET_MASK 0xFF7FFE00 ++#define USB_CLK_PHY_RESET_MASK 0xFFFFFE00 ++#define USB_CLK_NDIV_40 0x30 ++#define USB_CLK_NDIV_20 0x60 ++#define HX4_XGPLL_CTRL_4__NDIV_INT_R 0 ++#define HX4_XGPLL_CTRL_4__NDIV_INT_WIDTH 8 ++#define HX4_XGPLL_CTRL_0__CH3_MDIV_R 8 ++#define HX4_XGPLL_CTRL_0__CH3_MDIV_WIDTH 8 ++ ++/* KT2 */ ++#define KT2_PLL_CTRL_REG_3_ADDR(base) (base + 0x0c) ++#define KT2_PLL_CTRL_REG_5_ADDR(base) (base + 0x14) ++#define KT2_WRAP_USBPHY_CTRL_ADDR(base) (base + 0x20) ++#define KT2_WRAP_MISC_STATUS_ADDR(base) (base + 0x28) ++#define KT2_PLL_CTRL_REG_3__NDIV_INT_R 0 ++#define KT2_PLL_CTRL_REG_3__NDIV_INT_WIDTH 10 ++#define KT2_PLL_CTRL_REG_5__CH1_MDIV_R 0 ++#define KT2_PLL_CTRL_REG_5__CH1_MDIV_WIDTH 8 ++ ++/* SB2/GH/GH2/HR3 */ ++#define IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ BIT(26) ++#define IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB BIT(25) ++#define IPROC_WRAP_USBPHY_CTRL_0__RESETB BIT(24) ++#define IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO BIT(17) ++#define IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0 BIT(0) ++#define IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11 BIT(11) ++ ++/* SB2 */ ++#define SB2_WRAP_USBPHY_CTRL_0_ADDR(base) (base + 0x28) ++#define SB2_WRAP_USBPHY_CTRL_2_ADDR(base) (base + 0x30) ++#define SB2_WRAP_MISC_STATUS_ADDR(base) (base + 0x44) ++#define IPROC_WRAP_TOP_STRAP_CTRL_ADDR(base) (base + 0x70) ++#define IPROC_WRAP_TOP_STRAP_CTRL__USB_DEVICE BIT(10) ++ ++/* GH/GH2/HR3 */ ++#define GH_WRAP_USBPHY_CTRL_0_ADDR(base) (base + 0x44) ++#define GH_WRAP_USBPHY_CTRL_2_ADDR(base) (base + 0x4c) ++#define GH_WRAP_MISC_STATUS_ADDR(base) (base + 0x58) ++#define IPROC_WRAP_TOP_STRAP_STATUS_ADDR(base) (base + 0xa4) ++#define IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL BIT(17) ++ ++/* GH2 */ ++#define USBH_Utmi_p0Ctl(base) (base + 0x10) ++ ++ ++struct iproc_usb_priv { ++ struct usb_phy phy; ++ struct phy_device *mdio_phy; ++ void __iomem *wrap_base; ++ void __iomem *idm_base; ++ void __iomem *utmi_base; ++ int usb_mode; ++ int init_count; ++}; ++ ++extern void __iomem *get_iproc_wrap_ctrl_base(void); ++extern void xgs_phy_wr_reg(struct phy_device *phydev, u32 regnum, u16 data); ++extern u16 xgs_phy_rd_reg(struct phy_device *phydev, u32 regnum); ++extern void xgs_sb2_usb_phy_wr_reg(struct phy_device *phydev, u32 regnum, ++ u16 data); ++ ++/*************************************************************************** ++**************************************************************************** ++***************************************************************************/ ++ ++ ++/* check pll_lock */ ++static bool check_usbphy_pll_lock(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ void __iomem *wrap_addr = NULL; ++ struct device_node *dn = iproc_usb_data->phy.dev->of_node; ++ u32 val=0, mask; ++ u32 count = 0; ++ ++ if (of_device_is_compatible(dn, "brcm,usb-phy-hx4")) ++ wrap_addr = HX4_WRAP_MISC_STATUS_ADDR(wrap_base); ++ else if (of_device_is_compatible(dn, "brcm,usb-phy-kt2")) ++ wrap_addr = KT2_WRAP_MISC_STATUS_ADDR(wrap_base); ++ else if (of_device_is_compatible(dn, "brcm,usb-phy-sb2")) ++ wrap_addr = SB2_WRAP_MISC_STATUS_ADDR(wrap_base); ++ else if (of_device_is_compatible(dn, "brcm,usb-phy-gh") || ++ of_device_is_compatible(dn, "brcm,usb-phy-hr3") || ++ of_device_is_compatible(dn, "brcm,usb-phy-gh2")) ++ wrap_addr = GH_WRAP_MISC_STATUS_ADDR(wrap_base); ++ ++ if (!wrap_addr) { ++ dev_warn(iproc_usb_data->phy.dev, "No wrap addr specified\n"); ++ return 0; ++ } ++ ++ mask = IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK; ++ do { ++ val = readl(wrap_addr); ++ if ((val & mask) == mask) ++ break; ++ ++ udelay(10); ++ count ++; ++ } while(count <= 10); ++ ++ if (count <= 10) ++ return 1; ++ ++ dev_warn(iproc_usb_data->phy.dev, ++ "PLL not locked: IPROC_WRAP_MISC_STATUS = %x\n", val); ++ return 0; ++} ++ ++static int xgs_iproc_usb_phy_mode(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ struct device *dev = iproc_usb_data->phy.dev; ++ struct device_node *dn = dev->of_node; ++ int usb_mode = IPROC_USB_MODE_HOST; ++ u32 __maybe_unused val; ++ int __maybe_unused gpio_pin, ret; ++ ++ if (!wrap_base) ++ dev_warn(dev, "no wrap base addr"); ++ ++ if (of_device_is_compatible(dn, "brcm,usb-phy-hx4") || ++ of_device_is_compatible(dn, "brcm,usb-phy-kt2")) { ++ /* gpio pin 4 to control host/device mode */ ++ gpio_pin = of_get_named_gpio(dev->of_node, "usbdev-gpio", 0); ++ ++ if (gpio_pin < 0) { ++ /* default to 4 */ ++ dev_warn(dev, "No gpio pin set for USB device detection\n"); ++ gpio_pin = 4; ++ } ++ ++ ret = devm_gpio_request(dev, gpio_pin, "usbdev-gpio"); ++ if (ret) { ++ dev_warn(dev, "request gpio #%d fail\n", gpio_pin); ++ /* Use default host mode */ ++ return usb_mode; ++ } ++ ++ gpio_direction_input(gpio_pin); ++ val = gpio_get_value(gpio_pin); ++ if (val) ++ usb_mode = IPROC_USB_MODE_DEVICE; ++ ++ devm_gpio_free(dev, gpio_pin); ++ } else if (of_device_is_compatible(dn, "brcm,usb-phy-sb2")) { ++ /* u-boot enable this bit to indicate usb in host mode */ ++ val = readl(IPROC_WRAP_TOP_STRAP_CTRL_ADDR(wrap_base)); ++ if (!(val & IPROC_WRAP_TOP_STRAP_CTRL__USB_DEVICE)) ++ usb_mode = IPROC_USB_MODE_DEVICE; ++ } else if (of_device_is_compatible(dn, "brcm,usb-phy-gh") || ++ of_device_is_compatible(dn, "brcm,usb-phy-hr3") || ++ of_device_is_compatible(dn, "brcm,usb-phy-gh2")) { ++ /* u-boot enable this bit to indicate usb in host mode */ ++ val = readl(IPROC_WRAP_TOP_STRAP_STATUS_ADDR(wrap_base)); ++ if (!(val & IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL)) ++ usb_mode = IPROC_USB_MODE_DEVICE; ++ } ++ ++ dev_info(dev, "usb mode: %s\n", ++ usb_mode == IPROC_USB_MODE_DEVICE ? "DEVICE" : "HOST"); ++ ++ return usb_mode; ++} ++ ++/* Returns USB PHY PLL ref clock in MHz for HX4/KT2 */ ++static u32 _get_usb_clk(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ struct device_node *dn = iproc_usb_data->phy.dev->of_node; ++ u32 ndiv, mdiv, refclk; ++ u32 val; ++ ++ if (of_device_is_compatible(dn, "brcm,usb-phy-hx4")) { ++ val = readl(HX4_WRAP_XGPLL_CTRL_4_ADDR(wrap_base)); ++ ndiv = ((val >> HX4_XGPLL_CTRL_4__NDIV_INT_R) & ++ ~(0xFFFFFFFF << HX4_XGPLL_CTRL_4__NDIV_INT_WIDTH)); ++ ++ val = readl(HX4_WRAP_XGPLL_CTRL_0_ADDR(wrap_base)); ++ mdiv = ((val >> HX4_XGPLL_CTRL_0__CH3_MDIV_R) & ++ ~(0xFFFFFFFF << HX4_XGPLL_CTRL_0__CH3_MDIV_WIDTH)); ++ } else /*if (of_device_is_compatible(dn, "brcm,usb-phy-kt2"))*/ { ++ val = readl(KT2_PLL_CTRL_REG_3_ADDR(wrap_base)); ++ ndiv = ((val >> KT2_PLL_CTRL_REG_3__NDIV_INT_R) & ++ ~(0xFFFFFFFF << KT2_PLL_CTRL_REG_3__NDIV_INT_WIDTH)); ++ ++ /* read channel 1 mdiv */ ++ val = readl(KT2_PLL_CTRL_REG_5_ADDR(wrap_base)); ++ mdiv = ((val >> KT2_PLL_CTRL_REG_5__CH1_MDIV_R) & ++ ~(0xFFFFFFFF << KT2_PLL_CTRL_REG_5__CH1_MDIV_WIDTH)); ++ } ++ ++ refclk = (25 * ndiv) / mdiv; ++ ++ return refclk; ++} ++ ++static void hx4_clk_setup(void __iomem *wrap_base) ++{ ++ u32 val, ndiv; ++ void __iomem *wrap_addr = HX4_WRAP_USBPHY_CTRL_ADDR(wrap_base); ++ ++ val = readl(HX4_WRAP_XGPLL_CTRL_4_ADDR(wrap_base)); ++ ndiv = ((val >> HX4_XGPLL_CTRL_4__NDIV_INT_R) & ++ ~(0xFFFFFFFF << HX4_XGPLL_CTRL_4__NDIV_INT_WIDTH)); ++ ++ if (ndiv == IPROC_CLK_NDIV_40) { ++ val = readl(wrap_addr); ++ val = (val & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_40; ++ writel(val, wrap_addr); ++ udelay(10); ++ val = (val & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_40; ++ writel(val, wrap_addr); ++ udelay(10); ++ val = (val & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_40; ++ writel(val, wrap_addr); ++ udelay(10); ++ } else if (ndiv == IPROC_CLK_NDIV_20) { ++ val = readl(wrap_addr); ++ val = (val & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_20; ++ writel(val, wrap_addr); ++ udelay(10); ++ val = (val & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_20; ++ writel(val, wrap_addr); ++ udelay(10); ++ val = (val & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_20; ++ writel(val, wrap_addr); ++ udelay(10); ++ } ++} ++ ++static int iproc_usb_phy_hx4_config(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ void __iomem *wrap_addr = NULL; ++ struct device_node *dn = iproc_usb_data->phy.dev->of_node; ++ u32 ndiv, pdiv, miidata; ++ u32 val; ++ ++ if (!wrap_base) ++ return -EINVAL; ++ ++ if (iproc_usb_data->usb_mode == IPROC_USB_MODE_DEVICE) { ++ ndiv = 1920 / _get_usb_clk(iproc_usb_data); ++ pdiv = 1 << 12; ++ miidata = pdiv + ndiv; ++ ++ /* Program NDIV and PDIV into 0x1C register */ ++ xgs_phy_wr_reg(iproc_usb_data->mdio_phy, 0x800c, miidata); ++ mdelay(10); ++ ++ /* Program other PLL parameters into 0x1D register, disable suspend and ++ put PHY into reset */ ++ miidata = 1 << 13 | 3 << 8 | 3 << 4 | 0xa; ++ xgs_phy_wr_reg(iproc_usb_data->mdio_phy, 0x800d, miidata); ++ mdelay(10); ++ ++ /* Program register 0x15, USB device mode set and get PHY out ++ of reset */ ++ miidata = 1 << 2 | 1 << 1; ++ xgs_phy_wr_reg(iproc_usb_data->mdio_phy, 0x8005, miidata); ++ mdelay(10); ++ ++ /* Program register 0x19, set mdio mode */ ++ miidata = 1 << 7; ++ xgs_phy_wr_reg(iproc_usb_data->mdio_phy, 0x8009, miidata); ++ mdelay(10); ++ ++ /* get the PLL out of reset */ ++ miidata = xgs_phy_rd_reg(iproc_usb_data->mdio_phy, 0x800d); ++ miidata |= (1 << 12); ++ xgs_phy_wr_reg(iproc_usb_data->mdio_phy, 0x800d, miidata); ++ mdelay(10); ++ } else { ++ if (of_device_is_compatible(dn, "brcm,usb-phy-hx4")) ++ wrap_addr = HX4_WRAP_USBPHY_CTRL_ADDR(wrap_base); ++ else if (of_device_is_compatible(dn, "brcm,usb-phy-kt2")) ++ wrap_addr = KT2_WRAP_USBPHY_CTRL_ADDR(wrap_base); ++ ++ val = readl(wrap_addr); ++ /* PLL_RESETB = 1 */ ++ val |= BIT(24); ++ writel(val, wrap_addr); ++ ++ mdelay(10); ++ ++ /* check pll_lock */ ++ check_usbphy_pll_lock(iproc_usb_data); ++ ++ val = readl(wrap_addr); ++ /* RESETB = 0 */ ++ val &= ~BIT(23); ++ writel(val, wrap_addr); ++ mdelay(100); ++ ++ if (of_device_is_compatible(dn, "brcm,usb-phy-hx4")) ++ hx4_clk_setup(wrap_base); ++ ++ val = readl(wrap_addr); ++ /* RESETB = 1 */ ++ val |= BIT(23); ++ writel(val, wrap_addr); ++ mdelay(1); ++ } ++ ++ return 0; ++} ++ ++static int iproc_usb_phy_sb2_config(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ u32 val; ++ ++ if (!wrap_base) ++ return -EINVAL; ++ ++ val = readl(SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= 0x0c000000; /* 27:PHY_ISO & 26:PLL_SUSPEND_EN = 1 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~0x03000000; /* 25:PLL_RESETB & 24:RESETB = 0 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val = readl(SB2_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val &= ~0x03000000; /* 25:AFE_BG_PWRDWNB & 24:AFE_LDO_PWRDWNB = 0 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ udelay(10); ++ val |= 0x02000000; /* 25:AFE_BG_PWRDWNB = 1 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ udelay(150); ++ val |= 0x01000000; /* 24:AFE_LDO_PWRDWNB = 1 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ udelay(160); ++ ++ val = readl(SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~0x08000000; /* 27:PHY_ISO = 0 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ udelay(20); ++ val |= 0x02000000; /* 25:PLL_RESETB = 1 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ mdelay(20); ++ ++ /* check pll_lock */ ++ check_usbphy_pll_lock(iproc_usb_data); ++ ++ val = readl(SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= 0x01000000; /* 24:RESETB = 1 */ ++ writel(val, SB2_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ udelay(2); ++ ++ /* adjust tx amplitude */ ++ xgs_sb2_usb_phy_wr_reg(iproc_usb_data->mdio_phy, 0x80aa, 0xeea0); ++ ++ return 0; ++} ++ ++static int iproc_usb_phy_gh_config(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ u32 val; ++ ++ if (!wrap_base) ++ return -EINVAL; ++ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ /* set phy_resetb to 0, pll_resetb to 0 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_0__RESETB; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ /* set p1ctl[11] to 0 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ /* set phy_iso to 0 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ /* set phy_iddq to 0 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ mdelay(1); ++ ++ /* set pll_resetb to 1, phy_resetb to 1 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ val = readl(GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_0__RESETB; ++ writel(val, GH_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); ++ ++ mdelay(20); ++ ++ /* check pll_lock */ ++ check_usbphy_pll_lock(iproc_usb_data); ++ ++ /* set non_drving to 0 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val &= ~IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ /* set p1ctl[11] to 1 */ ++ val = readl(GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ val |= IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11; ++ writel(val, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ ++ return 0; ++} ++ ++static int iproc_usb_phy_gh2_config(struct iproc_usb_priv *iproc_usb_data) ++{ ++ void __iomem *wrap_base = iproc_usb_data->wrap_base; ++ void __iomem *utmi_base = NULL; ++ u32 val; ++ ++ if (!wrap_base) ++ return -EINVAL; ++ ++ /* This value is from DE team to set Internal Power Sequence Mode */ ++ val = readl(IPROC_WRAP_TOP_STRAP_STATUS_ADDR(wrap_base)); ++ if (val & IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL) { ++ /* host mode */ ++ utmi_base = iproc_usb_data->utmi_base; ++ if (!utmi_base) ++ return -EINVAL; ++ writel(0x0802, USBH_Utmi_p0Ctl(utmi_base)); ++ } else { ++ /* device mode */ ++ writel(0x0806, GH_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); ++ } ++ ++ mdelay(20); ++ ++ /* check pll_lock */ ++ check_usbphy_pll_lock(iproc_usb_data); ++ ++ return 0; ++} ++ ++static int iproc_usb_phy_init(struct usb_phy *phy) ++{ ++ struct iproc_usb_priv *iproc_usb_data = ++ container_of(phy, struct iproc_usb_priv, phy); ++ struct device *dev = phy->dev; ++ void __iomem *idm_base = iproc_usb_data->idm_base; ++ int ret = 0; ++ u32 val; ++ ++ if (iproc_usb_data->init_count) ++ return 0; ++ else ++ iproc_usb_data->init_count++; ++ ++ if (!iproc_usb_data->wrap_base || !iproc_usb_data->idm_base) ++ return -EINVAL; ++ ++ /* Put USB controller into reset state and disable clock */ ++ val = readl(USB2_IDM_RESET_CONTROL_ADDR(idm_base)); ++ val |= USB2_IDM_RESET_CONTROL__RESET; ++ writel(val, USB2_IDM_RESET_CONTROL_ADDR(idm_base)); ++ ++ val = readl(USB2_IDM_IO_CONTROL_DIRECT_ADDR(idm_base)); ++ val &= ~USB2_IDM_IO_CONTROL_DIRECT__clk_enable; ++ writel(val, USB2_IDM_IO_CONTROL_DIRECT_ADDR(idm_base)); ++ ++ if (of_device_is_compatible(dev->of_node, "brcm,usb-phy-hx4") || ++ of_device_is_compatible(dev->of_node, "brcm,usb-phy-kt2")) ++ ret = iproc_usb_phy_hx4_config(iproc_usb_data); ++ else if (of_device_is_compatible(dev->of_node, "brcm,usb-phy-sb2")) ++ ret = iproc_usb_phy_sb2_config(iproc_usb_data); ++ else if (of_device_is_compatible(dev->of_node, "brcm,usb-phy-gh") || ++ of_device_is_compatible(dev->of_node, "brcm,usb-phy-hr3")) ++ ret = iproc_usb_phy_gh_config(iproc_usb_data); ++ ++ /* Enable clock to USB and get the USB out of reset */ ++ val = readl(USB2_IDM_IO_CONTROL_DIRECT_ADDR(idm_base)); ++ val |= USB2_IDM_IO_CONTROL_DIRECT__clk_enable; ++ writel(val, USB2_IDM_IO_CONTROL_DIRECT_ADDR(idm_base)); ++ ++ mdelay(10); ++ val = readl(USB2_IDM_RESET_CONTROL_ADDR(idm_base)); ++ val &= ~USB2_IDM_RESET_CONTROL__RESET; ++ writel(val, USB2_IDM_RESET_CONTROL_ADDR(idm_base)); ++ mdelay(100); ++ ++ /* For GH2, PHY should be inited after RESET */ ++ if (of_device_is_compatible(dev->of_node, "brcm,usb-phy-gh2")) ++ ret = iproc_usb_phy_gh2_config(iproc_usb_data); ++ ++ return ret; ++} ++ ++static int xgs_iproc_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *dn = pdev->dev.of_node; ++ struct device_node *mdio_phy_np = NULL; ++ struct iproc_usb_priv *iproc_usb_data; ++ struct resource *res; ++ int gpio_pin; ++ enum of_gpio_flags flags; ++ u32 gpio_active_low; ++ int ret, usb_mode; ++ ++ if (!of_device_is_available(dn)) ++ return -ENODEV; ++ ++ iproc_usb_data = devm_kzalloc(dev, sizeof(*iproc_usb_data), GFP_KERNEL); ++ if (!iproc_usb_data) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, iproc_usb_data); ++ ++ iproc_usb_data->wrap_base = get_iproc_wrap_ctrl_base(); ++ if (!iproc_usb_data->wrap_base) { ++ dev_err(dev, "No wrap_base addr in DT"); ++ return -ENXIO; ++ } ++ ++ gpio_pin = of_get_named_gpio_flags(dn, "vbus-gpio", 0, &flags); ++ if (gpio_pin < 0) { ++ dev_err(dev, "No gpio pin set for USB power\n"); ++ return gpio_pin; ++ } ++ ++ gpio_active_low = flags & OF_GPIO_ACTIVE_LOW; ++ ++ ret = devm_gpio_request(dev, gpio_pin, "usbphy-vbus"); ++ if (ret != 0) { ++ dev_err(dev, "Failed to request gpio #%d\n", gpio_pin); ++ return ret; ++ } ++ ++ iproc_usb_data->phy.dev = dev; ++ usb_mode = xgs_iproc_usb_phy_mode(iproc_usb_data); ++ ++ iproc_usb_data->usb_mode = usb_mode; ++ /* Save host/device mode in phy.flags for use by ECHI/OHCI drivers */ ++ iproc_usb_data->phy.flags = usb_mode; ++ iproc_usb_data->phy.init = iproc_usb_phy_init; ++ iproc_usb_data->phy.type = USB_PHY_TYPE_USB2; ++ ++ if (usb_mode == IPROC_USB_MODE_HOST) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ iproc_usb_data->idm_base = ++ devm_ioremap_resource(dev, res); ++ if (IS_ERR(iproc_usb_data->idm_base)) { ++ dev_err(dev, "can't iomap usb2h idm base\n"); ++ return PTR_ERR(iproc_usb_data->idm_base); ++ } ++ ++ /* required for GH2 */ ++ if (of_device_is_compatible(dev->of_node, "brcm,usb-phy-gh2")) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ iproc_usb_data->utmi_base = ++ devm_ioremap_resource(dev, res); ++ } ++ ++ gpio_direction_output(gpio_pin, 1); ++ /* turn off the power: if active low, then set 1 to turn off */ ++ if (gpio_active_low) ++ gpio_set_value(gpio_pin, 1); ++ else ++ gpio_set_value(gpio_pin, 0); ++ } else { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ iproc_usb_data->idm_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(iproc_usb_data->idm_base)) { ++ dev_err(dev, "can't iomap usb2d idm base\n"); ++ return PTR_ERR(iproc_usb_data->idm_base); ++ } ++ } ++ ++ ++ /* PHY controlled through MDIO */ ++ mdio_phy_np = of_parse_phandle(dn, "mdio-phy-handle", 0); ++ if (mdio_phy_np) ++ iproc_usb_data->mdio_phy = of_phy_find_device(mdio_phy_np); ++ ++ ret = usb_add_phy_dev(&iproc_usb_data->phy); ++ if (ret) ++ return ret; ++ ++ /* supply power for USB device connected to the host */ ++ if (usb_mode == IPROC_USB_MODE_HOST) { ++ if (gpio_active_low) ++ gpio_set_value(gpio_pin, 0); ++ else ++ gpio_set_value(gpio_pin, 1); ++ } ++ ++ devm_gpio_free(dev, gpio_pin); ++ ++ return 0; ++} ++ ++static int xgs_iproc_usb_phy_remove(struct platform_device *pdev) ++{ ++ struct iproc_usb_priv *iproc_usb_data = platform_get_drvdata(pdev); ++ ++ if (iproc_usb_data) ++ usb_remove_phy(&iproc_usb_data->phy); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id xgs_iproc_usb_phy_dt_ids[] = { ++ { .compatible = "brcm,usb-phy-hx4", }, ++ { .compatible = "brcm,usb-phy-kt2", }, ++ { .compatible = "brcm,usb-phy-gh", }, ++ { .compatible = "brcm,usb-phy-sb2", }, ++ { .compatible = "brcm,usb-phy-hr3", }, ++ { .compatible = "brcm,usb-phy-gh2", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, xgs_iproc_usb_phy_dt_ids); ++ ++static struct platform_driver xgs_iproc_usb_phy_driver = ++{ ++ .driver = { ++ .name = "xgs-usb-phy", ++ .owner = THIS_MODULE, ++ .of_match_table = xgs_iproc_usb_phy_dt_ids, ++ }, ++ .probe = xgs_iproc_usb_phy_probe, ++ .remove = xgs_iproc_usb_phy_remove, ++}; ++ ++module_platform_driver(xgs_iproc_usb_phy_driver); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB phy driver"); ++MODULE_LICENSE("GPL"); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c +--- a/drivers/watchdog/sp805_wdt.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/drivers/watchdog/sp805_wdt.c 2018-05-10 11:31:34.017404421 +0800 +@@ -27,6 +27,8 @@ + #include + #include + #include ++#include ++ + + /* default timeout in seconds */ + #define DEFAULT_TIMEOUT 60 +@@ -74,6 +76,24 @@ module_param(nowayout, bool, 0); + MODULE_PARM_DESC(nowayout, + "Set to 1 to keep watchdog running after device release"); + ++/* This routine get boot status to indicate if the last boot is from WDT */ ++static unsigned int wdt_get_clear_bootstatus( ++ void __iomem *wdt_bootstatus, ++ unsigned int wdt_bootstatus_bit) ++{ ++ unsigned int reg; ++ unsigned int bootstatus = 0; ++ ++ reg = readl_relaxed(wdt_bootstatus); ++ bootstatus = reg & (1 << wdt_bootstatus_bit); ++ ++ if (bootstatus) ++ /* write 1 to clear boot status bit */ ++ writel_relaxed(reg, wdt_bootstatus); ++ ++ return bootstatus; ++} ++ + /* This routine finds load value that will reset system in required timout */ + static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) + { +@@ -204,6 +224,8 @@ sp805_wdt_probe(struct amba_device *adev + { + struct sp805_wdt *wdt; + int ret = 0; ++ void __iomem *wdt_bootstatus = NULL; ++ unsigned int bootstatus_bit = 0; + + wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) { +@@ -215,6 +237,13 @@ sp805_wdt_probe(struct amba_device *adev + if (IS_ERR(wdt->base)) + return PTR_ERR(wdt->base); + ++ wdt_bootstatus = of_iomap(adev->dev.of_node, 1); ++ if (!wdt_bootstatus) { ++ ret = -ENOMEM; ++ dev_warn(&adev->dev, "of_iomap failed\n"); ++ goto err; ++ } ++ + wdt->clk = devm_clk_get(&adev->dev, NULL); + if (IS_ERR(wdt->clk)) { + dev_warn(&adev->dev, "Clock not found\n"); +@@ -240,6 +269,9 @@ sp805_wdt_probe(struct amba_device *adev + } + amba_set_drvdata(adev, wdt); + ++ wdt->wdd.bootstatus = wdt_get_clear_bootstatus( ++ wdt_bootstatus, bootstatus_bit); ++ + dev_info(&adev->dev, "registration successful\n"); + return 0; + +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/include/linux/phy/xgs_iproc_serdes.h b/include/linux/phy/xgs_iproc_serdes.h +--- a/include/linux/phy/xgs_iproc_serdes.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/include/linux/phy/xgs_iproc_serdes.h 2018-05-10 11:31:34.757405249 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2017 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _XGS_IPROC_SERDES_H_ ++#define _XGS_IPROC_SERDES_H_ ++ ++/* Specify the used lane number of SERDES */ ++typedef struct xgs_serdes_info_s { ++ u32 lane; ++} xgs_serdes_info_t; ++ ++extern bool xgs_serdes_hx4_amac(struct phy_device *); ++extern bool xgs_serdes_kt2_amac(struct phy_device *); ++extern void xgs_serdes_set_lane(struct phy_device *phy_dev, u32 lane); ++ ++#endif /* _XGS_IPROC_SERDES_H_ */ ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/include/linux/soc/bcm/iproc-cmic.h b/include/linux/soc/bcm/iproc-cmic.h +--- a/include/linux/soc/bcm/iproc-cmic.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/include/linux/soc/bcm/iproc-cmic.h 2018-05-10 11:31:34.797405294 +0800 +@@ -0,0 +1,34 @@ ++#ifndef _IPROC_CMIC_H ++#define _IPROC_CMIC_H ++ ++struct iproc_cmic { ++ void __iomem *base; ++ struct device *dev; ++ ++ const struct sbus_ops *sbus_ops; ++}; ++ ++struct sbus_ops { ++ int (*init)(struct iproc_cmic *cmic); ++ int (*reg32_write)(struct iproc_cmic *cmic, u32 block, u32 addr, u32 val); ++ u32 (*reg32_read)(struct iproc_cmic *cmic, u32 block, u32 addr); ++ int (*reg64_write)(struct iproc_cmic *cmic, u32 block, u32 addr, u64 val); ++ u64 (*reg64_read)(struct iproc_cmic *cmic, u32 block, u32 addr); ++ int (*ucmem_write)(struct iproc_cmic *cmic, u32 block, u32 *mem); ++ int (*ucmem_read)(struct iproc_cmic *cmic, u32 block, u32 *mem); ++}; ++ ++enum cmic_block_type { ++ CMIC_BLOCK_TYPE_TOP = 0, ++ CMIC_BLOCK_TYPE_APM = 1, ++}; ++ ++extern int iproc_cmic_schan_reg32_write(u32 blk_type, u32 addr, u32 val); ++extern u32 iproc_cmic_schan_reg32_read(u32 blk_type, u32 addr); ++extern int iproc_cmic_schan_reg64_write(u32 blk_type, u32 addr, u64 val); ++extern u64 iproc_cmic_schan_reg64_read(u32 blk_type, u32 addr); ++extern int iproc_cmic_schan_ucmem_write(u32 blk_type, u32 *mem); ++extern int iproc_cmic_schan_ucmem_read(u32 blk_type, u32 *mem); ++extern void inline __iomem *iproc_cmic_base_get(void); ++ ++#endif /* _IPROC_CMIC_H */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/include/linux/soc/bcm/xgs-iproc-idm.h b/include/linux/soc/bcm/xgs-iproc-idm.h +--- a/include/linux/soc/bcm/xgs-iproc-idm.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/include/linux/soc/bcm/xgs-iproc-idm.h 2018-05-10 11:31:34.797405294 +0800 +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef XGS_IPROC_IDM_H ++#define XGS_IPROC_IDM_H ++ ++extern void inline __iomem *get_iproc_idm_base(int idx); ++extern int xgs_iproc_idm_dmac_reset(void); ++extern int xgs_iproc_idm_init(void); ++ ++#endif /* XGS_IPROC_IDM_H */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/include/linux/soc/bcm/xgs-iproc-misc-setup.h b/include/linux/soc/bcm/xgs-iproc-misc-setup.h +--- a/include/linux/soc/bcm/xgs-iproc-misc-setup.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/include/linux/soc/bcm/xgs-iproc-misc-setup.h 2018-05-10 11:31:34.797405294 +0800 +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 2016 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef XGS_IPROC_MISC_SETUP_H ++#define XGS_IPROC_MISC_SETUP_H ++ ++extern int xgs_iproc_misc_setup(void); ++extern void __iomem *get_iproc_wrap_ctrl_base(void); ++extern void __iomem *get_iproc_dmu_pcu_base(void); ++extern int is_wh2_amac_sgmii(void); ++ ++#endif /* XGS_IPROC_MISC_SETUP_H */ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/include/linux/usb/iproc_usb.h b/include/linux/usb/iproc_usb.h +--- a/include/linux/usb/iproc_usb.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/include/linux/usb/iproc_usb.h 2018-05-10 11:31:34.817405317 +0800 +@@ -0,0 +1,23 @@ ++/* ++ * Copyright 2017 Broadcom Limited ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT 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 __LINUX_USB_IPROC_USB_H ++#define __LINUX_USB_IPROC_USB_H ++ ++/* USB Flags */ ++ ++#define IPROC_USB_MODE_HOST (0) ++#define IPROC_USB_MODE_DEVICE (1) ++ ++#endif /* __LINUX_USB_IPROC_USB_H */ ++ +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidbg/Makefile b/tools/power/acpi/tools/acpidbg/Makefile +--- a/tools/power/acpi/tools/acpidbg/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidbg/Makefile 1970-01-01 08:00:00.000000000 +0800 +@@ -1,25 +0,0 @@ +-# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile +-# +-# Copyright (c) 2015, Intel Corporation +-# Author: Lv Zheng +-# +-# This program is free software; you can redistribute it and/or +-# modify it under the terms of the GNU General Public License +-# as published by the Free Software Foundation; version 2 +-# of the License. +- +-include ../../Makefile.config +- +-TOOL = acpidbg +-vpath %.c \ +- ../../../../../drivers/acpi/acpica\ +- ../../common\ +- ../../os_specific/service_layers\ +- . +-CFLAGS += -DACPI_APPLICATION -DACPI_SINGLE_THREAD -DACPI_DEBUGGER\ +- -I. +-LDFLAGS += -lpthread +-TOOL_OBJS = \ +- acpidbg.o +- +-include ../../Makefile.rules +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c +--- a/tools/power/acpi/tools/acpidbg/acpidbg.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidbg/acpidbg.c 1970-01-01 08:00:00.000000000 +0800 +@@ -1,444 +0,0 @@ +-/* +- * ACPI AML interfacing userspace utility +- * +- * Copyright (C) 2015, Intel Corporation +- * Authors: Lv Zheng +- * +- * 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. +- */ +- +-#include +- +-/* Headers not included by include/acpi/platform/aclinux.h */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "../../../../../include/linux/circ_buf.h" +- +-#define ACPI_AML_FILE "/sys/kernel/debug/acpi/acpidbg" +-#define ACPI_AML_SEC_TICK 1 +-#define ACPI_AML_USEC_PEEK 200 +-#define ACPI_AML_BUF_SIZE 4096 +- +-#define ACPI_AML_BATCH_WRITE_CMD 0x00 /* Write command to kernel */ +-#define ACPI_AML_BATCH_READ_LOG 0x01 /* Read log from kernel */ +-#define ACPI_AML_BATCH_WRITE_LOG 0x02 /* Write log to console */ +- +-#define ACPI_AML_LOG_START 0x00 +-#define ACPI_AML_PROMPT_START 0x01 +-#define ACPI_AML_PROMPT_STOP 0x02 +-#define ACPI_AML_LOG_STOP 0x03 +-#define ACPI_AML_PROMPT_ROLL 0x04 +- +-#define ACPI_AML_INTERACTIVE 0x00 +-#define ACPI_AML_BATCH 0x01 +- +-#define circ_count(circ) \ +- (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE)) +-#define circ_count_to_end(circ) \ +- (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE)) +-#define circ_space(circ) \ +- (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE)) +-#define circ_space_to_end(circ) \ +- (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE)) +- +-#define acpi_aml_cmd_count() circ_count(&acpi_aml_cmd_crc) +-#define acpi_aml_log_count() circ_count(&acpi_aml_log_crc) +-#define acpi_aml_cmd_space() circ_space(&acpi_aml_cmd_crc) +-#define acpi_aml_log_space() circ_space(&acpi_aml_log_crc) +- +-#define ACPI_AML_DO(_fd, _op, _buf, _ret) \ +- do { \ +- _ret = acpi_aml_##_op(_fd, &acpi_aml_##_buf##_crc); \ +- if (_ret == 0) { \ +- fprintf(stderr, \ +- "%s %s pipe closed.\n", #_buf, #_op); \ +- return; \ +- } \ +- } while (0) +-#define ACPI_AML_BATCH_DO(_fd, _op, _buf, _ret) \ +- do { \ +- _ret = acpi_aml_##_op##_batch_##_buf(_fd, \ +- &acpi_aml_##_buf##_crc); \ +- if (_ret == 0) \ +- return; \ +- } while (0) +- +- +-static char acpi_aml_cmd_buf[ACPI_AML_BUF_SIZE]; +-static char acpi_aml_log_buf[ACPI_AML_BUF_SIZE]; +-static struct circ_buf acpi_aml_cmd_crc = { +- .buf = acpi_aml_cmd_buf, +- .head = 0, +- .tail = 0, +-}; +-static struct circ_buf acpi_aml_log_crc = { +- .buf = acpi_aml_log_buf, +- .head = 0, +- .tail = 0, +-}; +-static const char *acpi_aml_file_path = ACPI_AML_FILE; +-static unsigned long acpi_aml_mode = ACPI_AML_INTERACTIVE; +-static bool acpi_aml_exit; +- +-static bool acpi_aml_batch_drain; +-static unsigned long acpi_aml_batch_state; +-static char acpi_aml_batch_prompt; +-static char acpi_aml_batch_roll; +-static unsigned long acpi_aml_log_state; +-static char *acpi_aml_batch_cmd = NULL; +-static char *acpi_aml_batch_pos = NULL; +- +-static int acpi_aml_set_fl(int fd, int flags) +-{ +- int ret; +- +- ret = fcntl(fd, F_GETFL, 0); +- if (ret < 0) { +- perror("fcntl(F_GETFL)"); +- return ret; +- } +- flags |= ret; +- ret = fcntl(fd, F_SETFL, flags); +- if (ret < 0) { +- perror("fcntl(F_SETFL)"); +- return ret; +- } +- return ret; +-} +- +-static int acpi_aml_set_fd(int fd, int maxfd, fd_set *set) +-{ +- if (fd > maxfd) +- maxfd = fd; +- FD_SET(fd, set); +- return maxfd; +-} +- +-static int acpi_aml_read(int fd, struct circ_buf *crc) +-{ +- char *p; +- int len; +- +- p = &crc->buf[crc->head]; +- len = circ_space_to_end(crc); +- len = read(fd, p, len); +- if (len < 0) +- perror("read"); +- else if (len > 0) +- crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1); +- return len; +-} +- +-static int acpi_aml_read_batch_cmd(int unused, struct circ_buf *crc) +-{ +- char *p; +- int len; +- int remained = strlen(acpi_aml_batch_pos); +- +- p = &crc->buf[crc->head]; +- len = circ_space_to_end(crc); +- if (len > remained) { +- memcpy(p, acpi_aml_batch_pos, remained); +- acpi_aml_batch_pos += remained; +- len = remained; +- } else { +- memcpy(p, acpi_aml_batch_pos, len); +- acpi_aml_batch_pos += len; +- } +- if (len > 0) +- crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1); +- return len; +-} +- +-static int acpi_aml_read_batch_log(int fd, struct circ_buf *crc) +-{ +- char *p; +- int len; +- int ret = 0; +- +- p = &crc->buf[crc->head]; +- len = circ_space_to_end(crc); +- while (ret < len && acpi_aml_log_state != ACPI_AML_LOG_STOP) { +- if (acpi_aml_log_state == ACPI_AML_PROMPT_ROLL) { +- *p = acpi_aml_batch_roll; +- len = 1; +- crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1); +- ret += 1; +- acpi_aml_log_state = ACPI_AML_LOG_START; +- } else { +- len = read(fd, p, 1); +- if (len <= 0) { +- if (len < 0) +- perror("read"); +- ret = len; +- break; +- } +- } +- switch (acpi_aml_log_state) { +- case ACPI_AML_LOG_START: +- if (*p == '\n') +- acpi_aml_log_state = ACPI_AML_PROMPT_START; +- crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1); +- ret += 1; +- break; +- case ACPI_AML_PROMPT_START: +- if (*p == ACPI_DEBUGGER_COMMAND_PROMPT || +- *p == ACPI_DEBUGGER_EXECUTE_PROMPT) { +- acpi_aml_batch_prompt = *p; +- acpi_aml_log_state = ACPI_AML_PROMPT_STOP; +- } else { +- if (*p != '\n') +- acpi_aml_log_state = ACPI_AML_LOG_START; +- crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1); +- ret += 1; +- } +- break; +- case ACPI_AML_PROMPT_STOP: +- if (*p == ' ') { +- acpi_aml_log_state = ACPI_AML_LOG_STOP; +- acpi_aml_exit = true; +- } else { +- /* Roll back */ +- acpi_aml_log_state = ACPI_AML_PROMPT_ROLL; +- acpi_aml_batch_roll = *p; +- *p = acpi_aml_batch_prompt; +- crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1); +- ret += 1; +- } +- break; +- default: +- assert(0); +- break; +- } +- } +- return ret; +-} +- +-static int acpi_aml_write(int fd, struct circ_buf *crc) +-{ +- char *p; +- int len; +- +- p = &crc->buf[crc->tail]; +- len = circ_count_to_end(crc); +- len = write(fd, p, len); +- if (len < 0) +- perror("write"); +- else if (len > 0) +- crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1); +- return len; +-} +- +-static int acpi_aml_write_batch_log(int fd, struct circ_buf *crc) +-{ +- char *p; +- int len; +- +- p = &crc->buf[crc->tail]; +- len = circ_count_to_end(crc); +- if (!acpi_aml_batch_drain) { +- len = write(fd, p, len); +- if (len < 0) +- perror("write"); +- } +- if (len > 0) +- crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1); +- return len; +-} +- +-static int acpi_aml_write_batch_cmd(int fd, struct circ_buf *crc) +-{ +- int len; +- +- len = acpi_aml_write(fd, crc); +- if (circ_count_to_end(crc) == 0) +- acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG; +- return len; +-} +- +-static void acpi_aml_loop(int fd) +-{ +- fd_set rfds; +- fd_set wfds; +- struct timeval tv; +- int ret; +- int maxfd = 0; +- +- if (acpi_aml_mode == ACPI_AML_BATCH) { +- acpi_aml_log_state = ACPI_AML_LOG_START; +- acpi_aml_batch_pos = acpi_aml_batch_cmd; +- if (acpi_aml_batch_drain) +- acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG; +- else +- acpi_aml_batch_state = ACPI_AML_BATCH_WRITE_CMD; +- } +- acpi_aml_exit = false; +- while (!acpi_aml_exit) { +- tv.tv_sec = ACPI_AML_SEC_TICK; +- tv.tv_usec = 0; +- FD_ZERO(&rfds); +- FD_ZERO(&wfds); +- +- if (acpi_aml_cmd_space()) { +- if (acpi_aml_mode == ACPI_AML_INTERACTIVE) +- maxfd = acpi_aml_set_fd(STDIN_FILENO, maxfd, &rfds); +- else if (strlen(acpi_aml_batch_pos) && +- acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD) +- ACPI_AML_BATCH_DO(STDIN_FILENO, read, cmd, ret); +- } +- if (acpi_aml_cmd_count() && +- (acpi_aml_mode == ACPI_AML_INTERACTIVE || +- acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD)) +- maxfd = acpi_aml_set_fd(fd, maxfd, &wfds); +- if (acpi_aml_log_space() && +- (acpi_aml_mode == ACPI_AML_INTERACTIVE || +- acpi_aml_batch_state == ACPI_AML_BATCH_READ_LOG)) +- maxfd = acpi_aml_set_fd(fd, maxfd, &rfds); +- if (acpi_aml_log_count()) +- maxfd = acpi_aml_set_fd(STDOUT_FILENO, maxfd, &wfds); +- +- ret = select(maxfd+1, &rfds, &wfds, NULL, &tv); +- if (ret < 0) { +- perror("select"); +- break; +- } +- if (ret > 0) { +- if (FD_ISSET(STDIN_FILENO, &rfds)) +- ACPI_AML_DO(STDIN_FILENO, read, cmd, ret); +- if (FD_ISSET(fd, &wfds)) { +- if (acpi_aml_mode == ACPI_AML_BATCH) +- ACPI_AML_BATCH_DO(fd, write, cmd, ret); +- else +- ACPI_AML_DO(fd, write, cmd, ret); +- } +- if (FD_ISSET(fd, &rfds)) { +- if (acpi_aml_mode == ACPI_AML_BATCH) +- ACPI_AML_BATCH_DO(fd, read, log, ret); +- else +- ACPI_AML_DO(fd, read, log, ret); +- } +- if (FD_ISSET(STDOUT_FILENO, &wfds)) { +- if (acpi_aml_mode == ACPI_AML_BATCH) +- ACPI_AML_BATCH_DO(STDOUT_FILENO, write, log, ret); +- else +- ACPI_AML_DO(STDOUT_FILENO, write, log, ret); +- } +- } +- } +-} +- +-static bool acpi_aml_readable(int fd) +-{ +- fd_set rfds; +- struct timeval tv; +- int ret; +- int maxfd = 0; +- +- tv.tv_sec = 0; +- tv.tv_usec = ACPI_AML_USEC_PEEK; +- FD_ZERO(&rfds); +- maxfd = acpi_aml_set_fd(fd, maxfd, &rfds); +- ret = select(maxfd+1, &rfds, NULL, NULL, &tv); +- if (ret < 0) +- perror("select"); +- if (ret > 0 && FD_ISSET(fd, &rfds)) +- return true; +- return false; +-} +- +-/* +- * This is a userspace IO flush implementation, replying on the prompt +- * characters and can be turned into a flush() call after kernel implements +- * .flush() filesystem operation. +- */ +-static void acpi_aml_flush(int fd) +-{ +- while (acpi_aml_readable(fd)) { +- acpi_aml_batch_drain = true; +- acpi_aml_loop(fd); +- acpi_aml_batch_drain = false; +- } +-} +- +-void usage(FILE *file, char *progname) +-{ +- fprintf(file, "usage: %s [-b cmd] [-f file] [-h]\n", progname); +- fprintf(file, "\nOptions:\n"); +- fprintf(file, " -b Specify command to be executed in batch mode\n"); +- fprintf(file, " -f Specify interface file other than"); +- fprintf(file, " /sys/kernel/debug/acpi/acpidbg\n"); +- fprintf(file, " -h Print this help message\n"); +-} +- +-int main(int argc, char **argv) +-{ +- int fd = -1; +- int ch; +- int len; +- int ret = EXIT_SUCCESS; +- +- while ((ch = getopt(argc, argv, "b:f:h")) != -1) { +- switch (ch) { +- case 'b': +- if (acpi_aml_batch_cmd) { +- fprintf(stderr, "Already specify %s\n", +- acpi_aml_batch_cmd); +- ret = EXIT_FAILURE; +- goto exit; +- } +- len = strlen(optarg); +- acpi_aml_batch_cmd = calloc(len + 2, 1); +- if (!acpi_aml_batch_cmd) { +- perror("calloc"); +- ret = EXIT_FAILURE; +- goto exit; +- } +- memcpy(acpi_aml_batch_cmd, optarg, len); +- acpi_aml_batch_cmd[len] = '\n'; +- acpi_aml_mode = ACPI_AML_BATCH; +- break; +- case 'f': +- acpi_aml_file_path = optarg; +- break; +- case 'h': +- usage(stdout, argv[0]); +- goto exit; +- break; +- case '?': +- default: +- usage(stderr, argv[0]); +- ret = EXIT_FAILURE; +- goto exit; +- break; +- } +- } +- +- fd = open(acpi_aml_file_path, O_RDWR | O_NONBLOCK); +- if (fd < 0) { +- perror("open"); +- ret = EXIT_FAILURE; +- goto exit; +- } +- acpi_aml_set_fl(STDIN_FILENO, O_NONBLOCK); +- acpi_aml_set_fl(STDOUT_FILENO, O_NONBLOCK); +- +- if (acpi_aml_mode == ACPI_AML_BATCH) +- acpi_aml_flush(fd); +- acpi_aml_loop(fd); +- +-exit: +- if (fd >= 0) +- close(fd); +- if (acpi_aml_batch_cmd) +- free(acpi_aml_batch_cmd); +- return ret; +-} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile +--- a/tools/power/acpi/tools/acpidump/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidump/Makefile 1970-01-01 08:00:00.000000000 +0800 +@@ -1,55 +0,0 @@ +-# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile +-# +-# Copyright (c) 2015, Intel Corporation +-# Author: Lv Zheng +-# +-# This program is free software; you can redistribute it and/or +-# modify it under the terms of the GNU General Public License +-# as published by the Free Software Foundation; version 2 +-# of the License. +- +-include ../../Makefile.config +- +-TOOL = acpidump +-EXTRA_INSTALL = install-man +-EXTRA_UNINSTALL = uninstall-man +- +-vpath %.c \ +- ../../../../../drivers/acpi/acpica\ +- ./\ +- ../../common\ +- ../../os_specific/service_layers +-CFLAGS += -DACPI_DUMP_APP -I. +-TOOL_OBJS = \ +- apdump.o\ +- apfiles.o\ +- apmain.o\ +- osunixdir.o\ +- osunixmap.o\ +- osunixxf.o\ +- tbprint.o\ +- tbxfroot.o\ +- utascii.o\ +- utbuffer.o\ +- utdebug.o\ +- utexcep.o\ +- utglobal.o\ +- uthex.o\ +- utmath.o\ +- utnonansi.o\ +- utprint.o\ +- utstring.o\ +- utstrtoul64.o\ +- utxferror.o\ +- oslinuxtbl.o\ +- cmfsize.o\ +- getopt.o +- +-include ../../Makefile.rules +- +-install-man: $(srctree)/man/acpidump.8 +- $(ECHO) " INST " acpidump.8 +- $(QUIET) $(INSTALL_DATA) -D $< $(DESTDIR)$(mandir)/man8/acpidump.8 +-uninstall-man: +- $(ECHO) " UNINST " acpidump.8 +- $(QUIET) rm -f $(DESTDIR)$(mandir)/man8/acpidump.8 +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h +--- a/tools/power/acpi/tools/acpidump/acpidump.h 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidump/acpidump.h 1970-01-01 08:00:00.000000000 +0800 +@@ -1,119 +0,0 @@ +-/****************************************************************************** +- * +- * Module Name: acpidump.h - Include file for acpi_dump utility +- * +- *****************************************************************************/ +- +-/* +- * Copyright (C) 2000 - 2017, Intel Corp. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce at minimum a disclaimer +- * substantially similar to the "NO WARRANTY" disclaimer below +- * ("Disclaimer") and any redistribution must be conditioned upon +- * including a substantially similar Disclaimer requirement for further +- * binary redistribution. +- * 3. Neither the names of the above-listed copyright holders nor the names +- * of any contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * Alternatively, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2 as published by the Free +- * Software Foundation. +- * +- * NO WARRANTY +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGES. +- */ +- +-/* +- * Global variables. Defined in main.c only, externed in all other files +- */ +-#ifdef _DECLARE_GLOBALS +-#define EXTERN +-#define INIT_GLOBAL(a,b) a=b +-#else +-#define EXTERN extern +-#define INIT_GLOBAL(a,b) a +-#endif +- +-#include +-#include "accommon.h" +-#include "actables.h" +-#include "acapps.h" +- +-/* Globals */ +- +-EXTERN u8 INIT_GLOBAL(gbl_summary_mode, FALSE); +-EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE); +-EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE); +-EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, TRUE); +-EXTERN u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, FALSE); +-EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL); +-EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); +-EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); +- +-/* Action table used to defer requested options */ +- +-struct ap_dump_action { +- char *argument; +- u32 to_be_done; +-}; +- +-#define AP_MAX_ACTIONS 32 +- +-#define AP_DUMP_ALL_TABLES 0 +-#define AP_DUMP_TABLE_BY_ADDRESS 1 +-#define AP_DUMP_TABLE_BY_NAME 2 +-#define AP_DUMP_TABLE_BY_FILE 3 +- +-#define AP_MAX_ACPI_FILES 256 /* Prevent infinite loops */ +- +-/* Minimum FADT sizes for various table addresses */ +- +-#define MIN_FADT_FOR_DSDT (ACPI_FADT_OFFSET (dsdt) + sizeof (u32)) +-#define MIN_FADT_FOR_FACS (ACPI_FADT_OFFSET (facs) + sizeof (u32)) +-#define MIN_FADT_FOR_XDSDT (ACPI_FADT_OFFSET (Xdsdt) + sizeof (u64)) +-#define MIN_FADT_FOR_XFACS (ACPI_FADT_OFFSET (Xfacs) + sizeof (u64)) +- +-/* +- * apdump - Table get/dump routines +- */ +-int ap_dump_table_from_file(char *pathname); +- +-int ap_dump_table_by_name(char *signature); +- +-int ap_dump_table_by_address(char *ascii_address); +- +-int ap_dump_all_tables(void); +- +-u8 ap_is_valid_header(struct acpi_table_header *table); +- +-u8 ap_is_valid_checksum(struct acpi_table_header *table); +- +-u32 ap_get_table_length(struct acpi_table_header *table); +- +-/* +- * apfiles - File I/O utilities +- */ +-int ap_open_output_file(char *pathname); +- +-int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance); +- +-struct acpi_table_header *ap_get_table_from_file(char *pathname, +- u32 *file_size); +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c +--- a/tools/power/acpi/tools/acpidump/apdump.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidump/apdump.c 1970-01-01 08:00:00.000000000 +0800 +@@ -1,437 +0,0 @@ +-/****************************************************************************** +- * +- * Module Name: apdump - Dump routines for ACPI tables (acpidump) +- * +- *****************************************************************************/ +- +-/* +- * Copyright (C) 2000 - 2017, Intel Corp. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce at minimum a disclaimer +- * substantially similar to the "NO WARRANTY" disclaimer below +- * ("Disclaimer") and any redistribution must be conditioned upon +- * including a substantially similar Disclaimer requirement for further +- * binary redistribution. +- * 3. Neither the names of the above-listed copyright holders nor the names +- * of any contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * Alternatively, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2 as published by the Free +- * Software Foundation. +- * +- * NO WARRANTY +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGES. +- */ +- +-#include "acpidump.h" +- +-/* Local prototypes */ +- +-static int +-ap_dump_table_buffer(struct acpi_table_header *table, +- u32 instance, acpi_physical_address address); +- +-/****************************************************************************** +- * +- * FUNCTION: ap_is_valid_header +- * +- * PARAMETERS: table - Pointer to table to be validated +- * +- * RETURN: TRUE if the header appears to be valid. FALSE otherwise +- * +- * DESCRIPTION: Check for a valid ACPI table header +- * +- ******************************************************************************/ +- +-u8 ap_is_valid_header(struct acpi_table_header *table) +-{ +- +- if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) { +- +- /* Make sure signature is all ASCII and a valid ACPI name */ +- +- if (!acpi_ut_valid_nameseg(table->signature)) { +- fprintf(stderr, +- "Table signature (0x%8.8X) is invalid\n", +- *(u32 *)table->signature); +- return (FALSE); +- } +- +- /* Check for minimum table length */ +- +- if (table->length < sizeof(struct acpi_table_header)) { +- fprintf(stderr, "Table length (0x%8.8X) is invalid\n", +- table->length); +- return (FALSE); +- } +- } +- +- return (TRUE); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_is_valid_checksum +- * +- * PARAMETERS: table - Pointer to table to be validated +- * +- * RETURN: TRUE if the checksum appears to be valid. FALSE otherwise. +- * +- * DESCRIPTION: Check for a valid ACPI table checksum. +- * +- ******************************************************************************/ +- +-u8 ap_is_valid_checksum(struct acpi_table_header *table) +-{ +- acpi_status status; +- struct acpi_table_rsdp *rsdp; +- +- if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { +- /* +- * Checksum for RSDP. +- * Note: Other checksums are computed during the table dump. +- */ +- rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); +- status = acpi_tb_validate_rsdp(rsdp); +- } else { +- status = acpi_tb_verify_checksum(table, table->length); +- } +- +- if (ACPI_FAILURE(status)) { +- fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", +- table->signature); +- } +- +- return (AE_OK); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_get_table_length +- * +- * PARAMETERS: table - Pointer to the table +- * +- * RETURN: Table length +- * +- * DESCRIPTION: Obtain table length according to table signature. +- * +- ******************************************************************************/ +- +-u32 ap_get_table_length(struct acpi_table_header *table) +-{ +- struct acpi_table_rsdp *rsdp; +- +- /* Check if table is valid */ +- +- if (!ap_is_valid_header(table)) { +- return (0); +- } +- +- if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { +- rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); +- return (acpi_tb_get_rsdp_length(rsdp)); +- } +- +- /* Normal ACPI table */ +- +- return (table->length); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_dump_table_buffer +- * +- * PARAMETERS: table - ACPI table to be dumped +- * instance - ACPI table instance no. to be dumped +- * address - Physical address of the table +- * +- * RETURN: None +- * +- * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a +- * header that is compatible with the acpi_xtract utility. +- * +- ******************************************************************************/ +- +-static int +-ap_dump_table_buffer(struct acpi_table_header *table, +- u32 instance, acpi_physical_address address) +-{ +- u32 table_length; +- +- table_length = ap_get_table_length(table); +- +- /* Print only the header if requested */ +- +- if (gbl_summary_mode) { +- acpi_tb_print_table_header(address, table); +- return (0); +- } +- +- /* Dump to binary file if requested */ +- +- if (gbl_binary_mode) { +- return (ap_write_to_binary_file(table, instance)); +- } +- +- /* +- * Dump the table with header for use with acpixtract utility. +- * Note: simplest to just always emit a 64-bit address. acpi_xtract +- * utility can handle this. +- */ +- fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n", +- table->signature, ACPI_FORMAT_UINT64(address)); +- +- acpi_ut_dump_buffer_to_file(gbl_output_file, +- ACPI_CAST_PTR(u8, table), table_length, +- DB_BYTE_DISPLAY, 0); +- fprintf(gbl_output_file, "\n"); +- return (0); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_dump_all_tables +- * +- * PARAMETERS: None +- * +- * RETURN: Status +- * +- * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the +- * tables that we can possibly get). +- * +- ******************************************************************************/ +- +-int ap_dump_all_tables(void) +-{ +- struct acpi_table_header *table; +- u32 instance = 0; +- acpi_physical_address address; +- acpi_status status; +- int table_status; +- u32 i; +- +- /* Get and dump all available ACPI tables */ +- +- for (i = 0; i < AP_MAX_ACPI_FILES; i++) { +- status = +- acpi_os_get_table_by_index(i, &table, &instance, &address); +- if (ACPI_FAILURE(status)) { +- +- /* AE_LIMIT means that no more tables are available */ +- +- if (status == AE_LIMIT) { +- return (0); +- } else if (i == 0) { +- fprintf(stderr, +- "Could not get ACPI tables, %s\n", +- acpi_format_exception(status)); +- return (-1); +- } else { +- fprintf(stderr, +- "Could not get ACPI table at index %u, %s\n", +- i, acpi_format_exception(status)); +- continue; +- } +- } +- +- table_status = ap_dump_table_buffer(table, instance, address); +- ACPI_FREE(table); +- +- if (table_status) { +- break; +- } +- } +- +- /* Something seriously bad happened if the loop terminates here */ +- +- return (-1); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_dump_table_by_address +- * +- * PARAMETERS: ascii_address - Address for requested ACPI table +- * +- * RETURN: Status +- * +- * DESCRIPTION: Get an ACPI table via a physical address and dump it. +- * +- ******************************************************************************/ +- +-int ap_dump_table_by_address(char *ascii_address) +-{ +- acpi_physical_address address; +- struct acpi_table_header *table; +- acpi_status status; +- int table_status; +- u64 long_address; +- +- /* Convert argument to an integer physical address */ +- +- status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT, +- &long_address); +- if (ACPI_FAILURE(status)) { +- fprintf(stderr, "%s: Could not convert to a physical address\n", +- ascii_address); +- return (-1); +- } +- +- address = (acpi_physical_address)long_address; +- status = acpi_os_get_table_by_address(address, &table); +- if (ACPI_FAILURE(status)) { +- fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n", +- ACPI_FORMAT_UINT64(address), +- acpi_format_exception(status)); +- return (-1); +- } +- +- table_status = ap_dump_table_buffer(table, 0, address); +- ACPI_FREE(table); +- return (table_status); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_dump_table_by_name +- * +- * PARAMETERS: signature - Requested ACPI table signature +- * +- * RETURN: Status +- * +- * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles +- * multiple tables with the same signature (SSDTs). +- * +- ******************************************************************************/ +- +-int ap_dump_table_by_name(char *signature) +-{ +- char local_signature[ACPI_NAME_SIZE + 1]; +- u32 instance; +- struct acpi_table_header *table; +- acpi_physical_address address; +- acpi_status status; +- int table_status; +- +- if (strlen(signature) != ACPI_NAME_SIZE) { +- fprintf(stderr, +- "Invalid table signature [%s]: must be exactly 4 characters\n", +- signature); +- return (-1); +- } +- +- /* Table signatures are expected to be uppercase */ +- +- strcpy(local_signature, signature); +- acpi_ut_strupr(local_signature); +- +- /* To be friendly, handle tables whose signatures do not match the name */ +- +- if (ACPI_COMPARE_NAME(local_signature, "FADT")) { +- strcpy(local_signature, ACPI_SIG_FADT); +- } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) { +- strcpy(local_signature, ACPI_SIG_MADT); +- } +- +- /* Dump all instances of this signature (to handle multiple SSDTs) */ +- +- for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) { +- status = acpi_os_get_table_by_name(local_signature, instance, +- &table, &address); +- if (ACPI_FAILURE(status)) { +- +- /* AE_LIMIT means that no more tables are available */ +- +- if (status == AE_LIMIT) { +- return (0); +- } +- +- fprintf(stderr, +- "Could not get ACPI table with signature [%s], %s\n", +- local_signature, acpi_format_exception(status)); +- return (-1); +- } +- +- table_status = ap_dump_table_buffer(table, instance, address); +- ACPI_FREE(table); +- +- if (table_status) { +- break; +- } +- } +- +- /* Something seriously bad happened if the loop terminates here */ +- +- return (-1); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_dump_table_from_file +- * +- * PARAMETERS: pathname - File containing the binary ACPI table +- * +- * RETURN: Status +- * +- * DESCRIPTION: Dump an ACPI table from a binary file +- * +- ******************************************************************************/ +- +-int ap_dump_table_from_file(char *pathname) +-{ +- struct acpi_table_header *table; +- u32 file_size = 0; +- int table_status = -1; +- +- /* Get the entire ACPI table from the file */ +- +- table = ap_get_table_from_file(pathname, &file_size); +- if (!table) { +- return (-1); +- } +- +- if (!acpi_ut_valid_nameseg(table->signature)) { +- fprintf(stderr, +- "No valid ACPI signature was found in input file %s\n", +- pathname); +- } +- +- /* File must be at least as long as the table length */ +- +- if (table->length > file_size) { +- fprintf(stderr, +- "Table length (0x%X) is too large for input file (0x%X) %s\n", +- table->length, file_size, pathname); +- goto exit; +- } +- +- if (gbl_verbose_mode) { +- fprintf(stderr, +- "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", +- pathname, table->signature, file_size, file_size); +- } +- +- table_status = ap_dump_table_buffer(table, 0, 0); +- +-exit: +- ACPI_FREE(table); +- return (table_status); +-} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c +--- a/tools/power/acpi/tools/acpidump/apfiles.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidump/apfiles.c 1970-01-01 08:00:00.000000000 +0800 +@@ -1,257 +0,0 @@ +-/****************************************************************************** +- * +- * Module Name: apfiles - File-related functions for acpidump utility +- * +- *****************************************************************************/ +- +-/* +- * Copyright (C) 2000 - 2017, Intel Corp. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce at minimum a disclaimer +- * substantially similar to the "NO WARRANTY" disclaimer below +- * ("Disclaimer") and any redistribution must be conditioned upon +- * including a substantially similar Disclaimer requirement for further +- * binary redistribution. +- * 3. Neither the names of the above-listed copyright holders nor the names +- * of any contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * Alternatively, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2 as published by the Free +- * Software Foundation. +- * +- * NO WARRANTY +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGES. +- */ +- +-#include "acpidump.h" +- +-/* Local prototypes */ +- +-static int ap_is_existing_file(char *pathname); +- +-/****************************************************************************** +- * +- * FUNCTION: ap_is_existing_file +- * +- * PARAMETERS: pathname - Output filename +- * +- * RETURN: 0 on success +- * +- * DESCRIPTION: Query for file overwrite if it already exists. +- * +- ******************************************************************************/ +- +-static int ap_is_existing_file(char *pathname) +-{ +-#if !defined(_GNU_EFI) && !defined(_EDK2_EFI) +- struct stat stat_info; +- +- if (!stat(pathname, &stat_info)) { +- fprintf(stderr, +- "Target path already exists, overwrite? [y|n] "); +- +- if (getchar() != 'y') { +- return (-1); +- } +- } +-#endif +- +- return 0; +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_open_output_file +- * +- * PARAMETERS: pathname - Output filename +- * +- * RETURN: Open file handle +- * +- * DESCRIPTION: Open a text output file for acpidump. Checks if file already +- * exists. +- * +- ******************************************************************************/ +- +-int ap_open_output_file(char *pathname) +-{ +- ACPI_FILE file; +- +- /* If file exists, prompt for overwrite */ +- +- if (ap_is_existing_file(pathname) != 0) { +- return (-1); +- } +- +- /* Point stdout to the file */ +- +- file = fopen(pathname, "w"); +- if (!file) { +- fprintf(stderr, "Could not open output file: %s\n", pathname); +- return (-1); +- } +- +- /* Save the file and path */ +- +- gbl_output_file = file; +- gbl_output_filename = pathname; +- return (0); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_write_to_binary_file +- * +- * PARAMETERS: table - ACPI table to be written +- * instance - ACPI table instance no. to be written +- * +- * RETURN: Status +- * +- * DESCRIPTION: Write an ACPI table to a binary file. Builds the output +- * filename from the table signature. +- * +- ******************************************************************************/ +- +-int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) +-{ +- char filename[ACPI_NAME_SIZE + 16]; +- char instance_str[16]; +- ACPI_FILE file; +- acpi_size actual; +- u32 table_length; +- +- /* Obtain table length */ +- +- table_length = ap_get_table_length(table); +- +- /* Construct lower-case filename from the table local signature */ +- +- if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { +- ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME); +- } else { +- ACPI_MOVE_NAME(filename, table->signature); +- } +- +- filename[0] = (char)tolower((int)filename[0]); +- filename[1] = (char)tolower((int)filename[1]); +- filename[2] = (char)tolower((int)filename[2]); +- filename[3] = (char)tolower((int)filename[3]); +- filename[ACPI_NAME_SIZE] = 0; +- +- /* Handle multiple SSDts - create different filenames for each */ +- +- if (instance > 0) { +- snprintf(instance_str, sizeof(instance_str), "%u", instance); +- strcat(filename, instance_str); +- } +- +- strcat(filename, FILE_SUFFIX_BINARY_TABLE); +- +- if (gbl_verbose_mode) { +- fprintf(stderr, +- "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", +- table->signature, filename, table->length, +- table->length); +- } +- +- /* Open the file and dump the entire table in binary mode */ +- +- file = fopen(filename, "wb"); +- if (!file) { +- fprintf(stderr, "Could not open output file: %s\n", filename); +- return (-1); +- } +- +- actual = fwrite(table, 1, table_length, file); +- if (actual != table_length) { +- fprintf(stderr, "Error writing binary output file: %s\n", +- filename); +- fclose(file); +- return (-1); +- } +- +- fclose(file); +- return (0); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_get_table_from_file +- * +- * PARAMETERS: pathname - File containing the binary ACPI table +- * out_file_size - Where the file size is returned +- * +- * RETURN: Buffer containing the ACPI table. NULL on error. +- * +- * DESCRIPTION: Open a file and read it entirely into a new buffer +- * +- ******************************************************************************/ +- +-struct acpi_table_header *ap_get_table_from_file(char *pathname, +- u32 *out_file_size) +-{ +- struct acpi_table_header *buffer = NULL; +- ACPI_FILE file; +- u32 file_size; +- acpi_size actual; +- +- /* Must use binary mode */ +- +- file = fopen(pathname, "rb"); +- if (!file) { +- fprintf(stderr, "Could not open input file: %s\n", pathname); +- return (NULL); +- } +- +- /* Need file size to allocate a buffer */ +- +- file_size = cm_get_file_size(file); +- if (file_size == ACPI_UINT32_MAX) { +- fprintf(stderr, +- "Could not get input file size: %s\n", pathname); +- goto cleanup; +- } +- +- /* Allocate a buffer for the entire file */ +- +- buffer = ACPI_ALLOCATE_ZEROED(file_size); +- if (!buffer) { +- fprintf(stderr, +- "Could not allocate file buffer of size: %u\n", +- file_size); +- goto cleanup; +- } +- +- /* Read the entire file */ +- +- actual = fread(buffer, 1, file_size, file); +- if (actual != file_size) { +- fprintf(stderr, "Could not read input file: %s\n", pathname); +- ACPI_FREE(buffer); +- buffer = NULL; +- goto cleanup; +- } +- +- *out_file_size = file_size; +- +-cleanup: +- fclose(file); +- return (buffer); +-} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c +--- a/tools/power/acpi/tools/acpidump/apmain.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/acpidump/apmain.c 1970-01-01 08:00:00.000000000 +0800 +@@ -1,382 +0,0 @@ +-/****************************************************************************** +- * +- * Module Name: apmain - Main module for the acpidump utility +- * +- *****************************************************************************/ +- +-/* +- * Copyright (C) 2000 - 2017, Intel Corp. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce at minimum a disclaimer +- * substantially similar to the "NO WARRANTY" disclaimer below +- * ("Disclaimer") and any redistribution must be conditioned upon +- * including a substantially similar Disclaimer requirement for further +- * binary redistribution. +- * 3. Neither the names of the above-listed copyright holders nor the names +- * of any contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * Alternatively, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2 as published by the Free +- * Software Foundation. +- * +- * NO WARRANTY +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGES. +- */ +- +-#define _DECLARE_GLOBALS +-#include "acpidump.h" +- +-/* +- * acpidump - A portable utility for obtaining system ACPI tables and dumping +- * them in an ASCII hex format suitable for binary extraction via acpixtract. +- * +- * Obtaining the system ACPI tables is an OS-specific operation. +- * +- * This utility can be ported to any host operating system by providing a +- * module containing system-specific versions of these interfaces: +- * +- * acpi_os_get_table_by_address +- * acpi_os_get_table_by_index +- * acpi_os_get_table_by_name +- * +- * See the ACPICA Reference Guide for the exact definitions of these +- * interfaces. Also, see these ACPICA source code modules for example +- * implementations: +- * +- * source/os_specific/service_layers/oswintbl.c +- * source/os_specific/service_layers/oslinuxtbl.c +- */ +- +-/* Local prototypes */ +- +-static void ap_display_usage(void); +- +-static int ap_do_options(int argc, char **argv); +- +-static int ap_insert_action(char *argument, u32 to_be_done); +- +-/* Table for deferred actions from command line options */ +- +-struct ap_dump_action action_table[AP_MAX_ACTIONS]; +-u32 current_action = 0; +- +-#define AP_UTILITY_NAME "ACPI Binary Table Dump Utility" +-#define AP_SUPPORTED_OPTIONS "?a:bc:f:hn:o:r:svxz" +- +-/****************************************************************************** +- * +- * FUNCTION: ap_display_usage +- * +- * DESCRIPTION: Usage message for the acpi_dump utility +- * +- ******************************************************************************/ +- +-static void ap_display_usage(void) +-{ +- +- ACPI_USAGE_HEADER("acpidump [options]"); +- +- ACPI_OPTION("-b", "Dump tables to binary files"); +- ACPI_OPTION("-h -?", "This help message"); +- ACPI_OPTION("-o ", "Redirect output to file"); +- ACPI_OPTION("-r
", "Dump tables from specified RSDP"); +- ACPI_OPTION("-s", "Print table summaries only"); +- ACPI_OPTION("-v", "Display version information"); +- ACPI_OPTION("-z", "Verbose mode"); +- +- ACPI_USAGE_TEXT("\nTable Options:\n"); +- +- ACPI_OPTION("-a
", "Get table via a physical address"); +- ACPI_OPTION("-c ", "Turning on/off customized table dumping"); +- ACPI_OPTION("-f ", "Get table via a binary file"); +- ACPI_OPTION("-n ", "Get table via a name/signature"); +- ACPI_OPTION("-x", "Do not use but dump XSDT"); +- ACPI_OPTION("-x -x", "Do not use or dump XSDT"); +- +- ACPI_USAGE_TEXT("\n" +- "Invocation without parameters dumps all available tables\n" +- "Multiple mixed instances of -a, -f, and -n are supported\n\n"); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_insert_action +- * +- * PARAMETERS: argument - Pointer to the argument for this action +- * to_be_done - What to do to process this action +- * +- * RETURN: Status +- * +- * DESCRIPTION: Add an action item to the action table +- * +- ******************************************************************************/ +- +-static int ap_insert_action(char *argument, u32 to_be_done) +-{ +- +- /* Insert action and check for table overflow */ +- +- action_table[current_action].argument = argument; +- action_table[current_action].to_be_done = to_be_done; +- +- current_action++; +- if (current_action > AP_MAX_ACTIONS) { +- fprintf(stderr, "Too many table options (max %u)\n", +- AP_MAX_ACTIONS); +- return (-1); +- } +- +- return (0); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: ap_do_options +- * +- * PARAMETERS: argc/argv - Standard argc/argv +- * +- * RETURN: Status +- * +- * DESCRIPTION: Command line option processing. The main actions for getting +- * and dumping tables are deferred via the action table. +- * +- *****************************************************************************/ +- +-static int ap_do_options(int argc, char **argv) +-{ +- int j; +- acpi_status status; +- +- /* Command line options */ +- +- while ((j = +- acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != ACPI_OPT_END) +- switch (j) { +- /* +- * Global options +- */ +- case 'b': /* Dump all input tables to binary files */ +- +- gbl_binary_mode = TRUE; +- continue; +- +- case 'c': /* Dump customized tables */ +- +- if (!strcmp(acpi_gbl_optarg, "on")) { +- gbl_dump_customized_tables = TRUE; +- } else if (!strcmp(acpi_gbl_optarg, "off")) { +- gbl_dump_customized_tables = FALSE; +- } else { +- fprintf(stderr, +- "%s: Cannot handle this switch, please use on|off\n", +- acpi_gbl_optarg); +- return (-1); +- } +- continue; +- +- case 'h': +- case '?': +- +- ap_display_usage(); +- return (1); +- +- case 'o': /* Redirect output to a single file */ +- +- if (ap_open_output_file(acpi_gbl_optarg)) { +- return (-1); +- } +- continue; +- +- case 'r': /* Dump tables from specified RSDP */ +- +- status = +- acpi_ut_strtoul64(acpi_gbl_optarg, +- ACPI_STRTOUL_64BIT, +- &gbl_rsdp_base); +- if (ACPI_FAILURE(status)) { +- fprintf(stderr, +- "%s: Could not convert to a physical address\n", +- acpi_gbl_optarg); +- return (-1); +- } +- continue; +- +- case 's': /* Print table summaries only */ +- +- gbl_summary_mode = TRUE; +- continue; +- +- case 'x': /* Do not use XSDT */ +- +- if (!acpi_gbl_do_not_use_xsdt) { +- acpi_gbl_do_not_use_xsdt = TRUE; +- } else { +- gbl_do_not_dump_xsdt = TRUE; +- } +- continue; +- +- case 'v': /* Revision/version */ +- +- acpi_os_printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); +- return (1); +- +- case 'z': /* Verbose mode */ +- +- gbl_verbose_mode = TRUE; +- fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); +- continue; +- +- /* +- * Table options +- */ +- case 'a': /* Get table by physical address */ +- +- if (ap_insert_action +- (acpi_gbl_optarg, AP_DUMP_TABLE_BY_ADDRESS)) { +- return (-1); +- } +- break; +- +- case 'f': /* Get table from a file */ +- +- if (ap_insert_action +- (acpi_gbl_optarg, AP_DUMP_TABLE_BY_FILE)) { +- return (-1); +- } +- break; +- +- case 'n': /* Get table by input name (signature) */ +- +- if (ap_insert_action +- (acpi_gbl_optarg, AP_DUMP_TABLE_BY_NAME)) { +- return (-1); +- } +- break; +- +- default: +- +- ap_display_usage(); +- return (-1); +- } +- +- /* If there are no actions, this means "get/dump all tables" */ +- +- if (current_action == 0) { +- if (ap_insert_action(NULL, AP_DUMP_ALL_TABLES)) { +- return (-1); +- } +- } +- +- return (0); +-} +- +-/****************************************************************************** +- * +- * FUNCTION: main +- * +- * PARAMETERS: argc/argv - Standard argc/argv +- * +- * RETURN: Status +- * +- * DESCRIPTION: C main function for acpidump utility +- * +- ******************************************************************************/ +- +-#if !defined(_GNU_EFI) && !defined(_EDK2_EFI) +-int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) +-#else +-int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) +-#endif +-{ +- int status = 0; +- struct ap_dump_action *action; +- u32 file_size; +- u32 i; +- +- ACPI_DEBUG_INITIALIZE(); /* For debug version only */ +- acpi_os_initialize(); +- gbl_output_file = ACPI_FILE_OUT; +- acpi_gbl_integer_byte_width = 8; +- +- /* Process command line options */ +- +- status = ap_do_options(argc, argv); +- if (status > 0) { +- return (0); +- } +- if (status < 0) { +- return (status); +- } +- +- /* Get/dump ACPI table(s) as requested */ +- +- for (i = 0; i < current_action; i++) { +- action = &action_table[i]; +- switch (action->to_be_done) { +- case AP_DUMP_ALL_TABLES: +- +- status = ap_dump_all_tables(); +- break; +- +- case AP_DUMP_TABLE_BY_ADDRESS: +- +- status = ap_dump_table_by_address(action->argument); +- break; +- +- case AP_DUMP_TABLE_BY_NAME: +- +- status = ap_dump_table_by_name(action->argument); +- break; +- +- case AP_DUMP_TABLE_BY_FILE: +- +- status = ap_dump_table_from_file(action->argument); +- break; +- +- default: +- +- fprintf(stderr, +- "Internal error, invalid action: 0x%X\n", +- action->to_be_done); +- return (-1); +- } +- +- if (status) { +- return (status); +- } +- } +- +- if (gbl_output_filename) { +- if (gbl_verbose_mode) { +- +- /* Summary for the output file */ +- +- file_size = cm_get_file_size(gbl_output_file); +- fprintf(stderr, +- "Output file %s contains 0x%X (%u) bytes\n\n", +- gbl_output_filename, file_size, file_size); +- } +- +- fclose(gbl_output_file); +- } +- +- return (status); +-} +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/ec/Makefile b/tools/power/acpi/tools/ec/Makefile +--- a/tools/power/acpi/tools/ec/Makefile 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/ec/Makefile 1970-01-01 08:00:00.000000000 +0800 +@@ -1,17 +0,0 @@ +-# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile +-# +-# Copyright (c) 2015, Intel Corporation +-# Author: Lv Zheng +-# +-# This program is free software; you can redistribute it and/or +-# modify it under the terms of the GNU General Public License +-# as published by the Free Software Foundation; version 2 +-# of the License. +- +-include ../../Makefile.config +- +-TOOL = ec +-TOOL_OBJS = \ +- ec_access.o +- +-include ../../Makefile.rules +diff -uprN -EbwB --no-dereference -X /home/kevin/BRCM_DISK/disk1/xldksw/INTERNAL/release/tools/dontdiff a/tools/power/acpi/tools/ec/ec_access.c b/tools/power/acpi/tools/ec/ec_access.c +--- a/tools/power/acpi/tools/ec/ec_access.c 2017-11-13 02:46:13.000000000 +0800 ++++ b/tools/power/acpi/tools/ec/ec_access.c 1970-01-01 08:00:00.000000000 +0800 +@@ -1,238 +0,0 @@ +-/* +- * ec_access.c +- * +- * Copyright (C) 2010 SUSE Linux Products GmbH +- * Author: +- * Thomas Renninger +- * +- * This work is licensed under the terms of the GNU GPL, version 2. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-#define EC_SPACE_SIZE 256 +-#define SYSFS_PATH "/sys/kernel/debug/ec/ec0/io" +- +-/* TBD/Enhancements: +- - Provide param for accessing different ECs (not supported by kernel yet) +-*/ +- +-static int read_mode = -1; +-static int sleep_time; +-static int write_byte_offset = -1; +-static int read_byte_offset = -1; +-static uint8_t write_value = -1; +- +-void usage(char progname[], int exit_status) +-{ +- printf("Usage:\n"); +- printf("1) %s -r [-s sleep]\n", basename(progname)); +- printf("2) %s -b byte_offset\n", basename(progname)); +- printf("3) %s -w byte_offset -v value\n\n", basename(progname)); +- +- puts("\t-r [-s sleep] : Dump EC registers"); +- puts("\t If sleep is given, sleep x seconds,"); +- puts("\t re-read EC registers and show changes"); +- puts("\t-b offset : Read value at byte_offset (in hex)"); +- puts("\t-w offset -v value : Write value at byte_offset"); +- puts("\t-h : Print this help\n\n"); +- puts("Offsets and values are in hexadecimal number system."); +- puts("The offset and value must be between 0 and 0xff."); +- exit(exit_status); +-} +- +-void parse_opts(int argc, char *argv[]) +-{ +- int c; +- +- while ((c = getopt(argc, argv, "rs:b:w:v:h")) != -1) { +- +- switch (c) { +- case 'r': +- if (read_mode != -1) +- usage(argv[0], EXIT_FAILURE); +- read_mode = 1; +- break; +- case 's': +- if (read_mode != -1 && read_mode != 1) +- usage(argv[0], EXIT_FAILURE); +- +- sleep_time = atoi(optarg); +- if (sleep_time <= 0) { +- sleep_time = 0; +- usage(argv[0], EXIT_FAILURE); +- printf("Bad sleep time: %s\n", optarg); +- } +- break; +- case 'b': +- if (read_mode != -1) +- usage(argv[0], EXIT_FAILURE); +- read_mode = 1; +- read_byte_offset = strtoul(optarg, NULL, 16); +- break; +- case 'w': +- if (read_mode != -1) +- usage(argv[0], EXIT_FAILURE); +- read_mode = 0; +- write_byte_offset = strtoul(optarg, NULL, 16); +- break; +- case 'v': +- write_value = strtoul(optarg, NULL, 16); +- break; +- case 'h': +- usage(argv[0], EXIT_SUCCESS); +- default: +- fprintf(stderr, "Unknown option!\n"); +- usage(argv[0], EXIT_FAILURE); +- } +- } +- if (read_mode == 0) { +- if (write_byte_offset < 0 || +- write_byte_offset >= EC_SPACE_SIZE) { +- fprintf(stderr, "Wrong byte offset 0x%.2x, valid: " +- "[0-0x%.2x]\n", +- write_byte_offset, EC_SPACE_SIZE - 1); +- usage(argv[0], EXIT_FAILURE); +- } +- if (write_value < 0 || +- write_value >= 255) { +- fprintf(stderr, "Wrong byte offset 0x%.2x, valid:" +- "[0-0xff]\n", write_byte_offset); +- usage(argv[0], EXIT_FAILURE); +- } +- } +- if (read_mode == 1 && read_byte_offset != -1) { +- if (read_byte_offset < -1 || +- read_byte_offset >= EC_SPACE_SIZE) { +- fprintf(stderr, "Wrong byte offset 0x%.2x, valid: " +- "[0-0x%.2x]\n", +- read_byte_offset, EC_SPACE_SIZE - 1); +- usage(argv[0], EXIT_FAILURE); +- } +- } +- /* Add additional parameter checks here */ +-} +- +-void dump_ec(int fd) +-{ +- char buf[EC_SPACE_SIZE]; +- char buf2[EC_SPACE_SIZE]; +- int byte_off, bytes_read; +- +- bytes_read = read(fd, buf, EC_SPACE_SIZE); +- +- if (bytes_read == -1) +- err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH); +- +- if (bytes_read != EC_SPACE_SIZE) +- fprintf(stderr, "Could only read %d bytes\n", bytes_read); +- +- printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); +- for (byte_off = 0; byte_off < bytes_read; byte_off++) { +- if ((byte_off % 16) == 0) +- printf("\n%.2X: ", byte_off); +- printf(" %.2x ", (uint8_t)buf[byte_off]); +- } +- printf("\n"); +- +- if (!sleep_time) +- return; +- +- printf("\n"); +- lseek(fd, 0, SEEK_SET); +- sleep(sleep_time); +- +- bytes_read = read(fd, buf2, EC_SPACE_SIZE); +- +- if (bytes_read == -1) +- err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH); +- +- if (bytes_read != EC_SPACE_SIZE) +- fprintf(stderr, "Could only read %d bytes\n", bytes_read); +- +- printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); +- for (byte_off = 0; byte_off < bytes_read; byte_off++) { +- if ((byte_off % 16) == 0) +- printf("\n%.2X: ", byte_off); +- +- if (buf[byte_off] == buf2[byte_off]) +- printf(" %.2x ", (uint8_t)buf2[byte_off]); +- else +- printf("*%.2x ", (uint8_t)buf2[byte_off]); +- } +- printf("\n"); +-} +- +-void read_ec_val(int fd, int byte_offset) +-{ +- uint8_t buf; +- int error; +- +- error = lseek(fd, byte_offset, SEEK_SET); +- if (error != byte_offset) +- err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset); +- +- error = read(fd, &buf, 1); +- if (error != 1) +- err(EXIT_FAILURE, "Could not read byte 0x%.2x from %s\n", +- byte_offset, SYSFS_PATH); +- printf("0x%.2x\n", buf); +- return; +-} +- +-void write_ec_val(int fd, int byte_offset, uint8_t value) +-{ +- int error; +- +- error = lseek(fd, byte_offset, SEEK_SET); +- if (error != byte_offset) +- err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset); +- +- error = write(fd, &value, 1); +- if (error != 1) +- err(EXIT_FAILURE, "Cannot write value 0x%.2x to offset 0x%.2x", +- value, byte_offset); +-} +- +-int main(int argc, char *argv[]) +-{ +- int file_mode = O_RDONLY; +- int fd; +- +- parse_opts(argc, argv); +- +- if (read_mode == 0) +- file_mode = O_WRONLY; +- else if (read_mode == 1) +- file_mode = O_RDONLY; +- else +- usage(argv[0], EXIT_FAILURE); +- +- fd = open(SYSFS_PATH, file_mode); +- if (fd == -1) +- err(EXIT_FAILURE, "%s", SYSFS_PATH); +- +- if (read_mode) +- if (read_byte_offset == -1) +- dump_ec(fd); +- else if (read_byte_offset < 0 || +- read_byte_offset >= EC_SPACE_SIZE) +- usage(argv[0], EXIT_FAILURE); +- else +- read_ec_val(fd, read_byte_offset); +- else +- write_ec_val(fd, write_byte_offset, write_value); +- close(fd); +- +- exit(EXIT_SUCCESS); +-} diff --git a/packages/base/any/kernels/4.14-lts/patches/drivers-i2c-busses-xgs_iproc_smbus-clk-freq.patch b/packages/base/any/kernels/4.14-lts/patches/drivers-i2c-busses-xgs_iproc_smbus-clk-freq.patch new file mode 100644 index 00000000..3042bbd9 --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/patches/drivers-i2c-busses-xgs_iproc_smbus-clk-freq.patch @@ -0,0 +1,86 @@ +diff -urpN a/drivers/i2c/busses/xgs_iproc_smbus.c b/drivers/i2c/busses/xgs_iproc_smbus.c +--- a/drivers/i2c/busses/xgs_iproc_smbus.c 2018-12-17 15:00:29.412457650 +0000 ++++ b/drivers/i2c/busses/xgs_iproc_smbus.c 2018-12-17 15:01:26.255275662 +0000 +@@ -52,6 +52,8 @@ + (regval & ~(mask)) | \ + ((fldval) << (startbit)) + ++//#define IPROC_SMB_DBG 1 ++ + typedef enum iproc_smb_clk_freq { + I2C_SPEED_100KHz = 0, + I2C_SPEED_400KHz = 1, +@@ -178,7 +180,7 @@ static int iproc_smb_set_clk_freq(void _ + SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, + CCB_SMB_TIMGCFG_MODE400_SHIFT); + writel(regval, base_addr + CCB_SMB_TIMGCFG_REG); +- ++ + return 0; + } + +@@ -208,9 +210,20 @@ static int iproc_smbus_block_init(struct + udelay(100); + + /* Set default clock frequency */ +- if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq)) +- /*no property available, use default: 100KHz*/ +- i2c_clk_freq = I2C_SPEED_100KHz; ++ if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq)) { ++ /*no property available, use default: 100KHz*/ ++ i2c_clk_freq = 100000; ++ } ++ ++/* Edgecore patch */ ++ if (i2c_clk_freq == 400000) { ++ dev_info(dev->dev, "bus set to %u Hz\n", i2c_clk_freq); ++ i2c_clk_freq = I2C_SPEED_400KHz; ++ } else { ++ dev_info(dev->dev, "bus set to %u Hz\n", 100000); ++ i2c_clk_freq = I2C_SPEED_100KHz; ++ } ++ + iproc_smb_set_clk_freq(base_addr, i2c_clk_freq); + + /* Disable intrs */ +@@ -577,7 +590,9 @@ static int iproc_smb_data_send(struct i2 + + if (regval != MSTR_STS_XACT_SUCCESS) { + /* We can flush Tx FIFO here */ ++#ifdef IPROC_SMB_DBG + dev_err(dev->dev, "Send: Error in transaction\n"); ++#endif + return -EREMOTEIO; + } + } +@@ -662,7 +677,9 @@ static int iproc_smb_data_recv(struct i2 + + if (regval != MSTR_STS_XACT_SUCCESS) { + /* We can flush Tx FIFO here */ ++#ifdef IPROC_SMB_DBG + dev_info(dev->dev, "Error in transaction\n"); ++#endif + return -EREMOTEIO; + } + } +@@ -840,8 +857,10 @@ static int iproc_smb_xfer(struct i2c_ada + } + + if (rc < 0) { ++#ifdef IPROC_SMB_DBG + dev_info(dev->dev, "%s error accessing\n", + (read_write == I2C_SMBUS_READ) ? "Read" : "Write"); ++#endif + up(&dev->xfer_lock); + return -EREMOTEIO; + } +@@ -856,7 +875,8 @@ static int iproc_smb_xfer(struct i2c_ada + } + } + +- msleep(1); ++ /* Edge-core comments out the sleep to speed up EEPROM dump */ ++ //msleep(1); + up(&dev->xfer_lock); + + return (rc); diff --git a/packages/base/any/kernels/4.14-lts/patches/drivers-usb-phy-phy-xgs-iproc-usb-phy-mode.patch b/packages/base/any/kernels/4.14-lts/patches/drivers-usb-phy-phy-xgs-iproc-usb-phy-mode.patch new file mode 100644 index 00000000..56cc0e8b --- /dev/null +++ b/packages/base/any/kernels/4.14-lts/patches/drivers-usb-phy-phy-xgs-iproc-usb-phy-mode.patch @@ -0,0 +1,26 @@ +diff -urpN a/drivers/usb/phy/phy-xgs-iproc.c b/drivers/usb/phy/phy-xgs-iproc.c +--- a/drivers/usb/phy/phy-xgs-iproc.c 2018-12-17 14:49:55.121649311 +0000 ++++ b/drivers/usb/phy/phy-xgs-iproc.c 2018-12-17 14:50:06.529412019 +0000 +@@ -161,12 +161,22 @@ static int xgs_iproc_usb_phy_mode(struct + int usb_mode = IPROC_USB_MODE_HOST; + u32 __maybe_unused val; + int __maybe_unused gpio_pin, ret; ++ const char *phy_mode_str; + + if (!wrap_base) + dev_warn(dev, "no wrap base addr"); + + if (of_device_is_compatible(dn, "brcm,usb-phy-hx4") || + of_device_is_compatible(dn, "brcm,usb-phy-kt2")) { ++ ++ /* Edge-core patch: use "usb-phy-mode" in dts to decide host/device mode */ ++ if (!of_property_read_string(dn, "usb-phy-mode", &phy_mode_str)) { ++ if (!strcasecmp(phy_mode_str, "host")) ++ return IPROC_USB_MODE_HOST; ++ if (!strcasecmp(phy_mode_str, "device")) ++ return IPROC_USB_MODE_DEVICE; ++ } ++ + /* gpio pin 4 to control host/device mode */ + gpio_pin = of_get_named_gpio(dev->of_node, "usbdev-gpio", 0); + diff --git a/packages/base/any/kernels/4.14-lts/patches/series b/packages/base/any/kernels/4.14-lts/patches/series index 3659add7..365505b3 100644 --- a/packages/base/any/kernels/4.14-lts/patches/series +++ b/packages/base/any/kernels/4.14-lts/patches/series @@ -1,3 +1,5 @@ +brcm-iproc-4.14.patch +drivers-usb-phy-phy-xgs-iproc-usb-phy-mode.patch +drivers-i2c-busses-xgs_iproc_smbus-clk-freq.patch 0001-drivers-i2c-muxes-pca954x-deselect-on-exit.patch 0002-driver-support-intel-igb-bcm5461S-phy.patch - diff --git a/packages/base/any/kernels/4.4-lts/patches/kernel-4.4-brcm-iproc.patch b/packages/base/any/kernels/4.4-lts/patches/kernel-4.4-brcm-iproc.patch deleted file mode 100644 index 4da5c804..00000000 --- a/packages/base/any/kernels/4.4-lts/patches/kernel-4.4-brcm-iproc.patch +++ /dev/null @@ -1,75281 +0,0 @@ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/Documentation/devicetree/bindings/gpio/xgs-gpio-iproc.txt b/Documentation/devicetree/bindings/gpio/xgs-gpio-iproc.txt ---- a/Documentation/devicetree/bindings/gpio/xgs-gpio-iproc.txt 1970-01-01 08:00:00.000000000 +0800 -+++ b/Documentation/devicetree/bindings/gpio/xgs-gpio-iproc.txt 2017-11-09 17:52:48.421892000 +0800 -@@ -0,0 +1,46 @@ -+Broadcom XGS iProc GPIO Controller -+ -+Required properties: -+- compatible : Should be "brcm,iproc-gpio,cca" or "brcm,iproc-gpio,ccg". -+ "brcm,iproc-gpio,cca" is used for CCA type gpio controllers on Helix4/Katana2/HR2. -+ "brcm,iproc-gpio,ccg" is used for CCG type gpio controllers on Grehound/Saber2/HR3/Greyhound2. -+- reg : Physical base address and length of the controller's registers. -+- #gpio-cells : should be 2 -+- ngpios : The number of GPIO's the controller provides. -+- interrupts : The interrupt id for the controller. -+- pin-base : The first chip GPIO pin provided by CCA or CCG. For Helix4, set to 4. -+- pin-offset : The offset of available CCA or CCG GPIO pins. For Helix4, set to 0. -+- gpio-controller : Marks the device node as a GPIO controller. -+ -+Optional properties: -+- interrupt-controller : Marks the device node as an interrupt controller. -+ -+ -+Examples for cca gpio: -+ -+ gpio_cca: gpio@18000060 { -+ compatible = "brcm,iproc-gpio,cca"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x18000060 0x50>, -+ intr: <0x18000000 0x50>; -+ ngpios = <8>; -+ pin-offset = <0>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <12>; -+ pin-offset = <4>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ }; -+ -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/Documentation/devicetree/bindings/net/xgs-iproc-mdio.txt b/Documentation/devicetree/bindings/net/xgs-iproc-mdio.txt ---- a/Documentation/devicetree/bindings/net/xgs-iproc-mdio.txt 1970-01-01 08:00:00.000000000 +0800 -+++ b/Documentation/devicetree/bindings/net/xgs-iproc-mdio.txt 2017-11-09 17:52:49.481900000 +0800 -@@ -0,0 +1,30 @@ -+* Broadcom XGS iProc MDIO bus controller -+ -+Required properties: -+- compatible: should be "brcm,iproc-ccb-mdio" or "brcm,iproc-ccg-mdio" or "brcm,iproc-cmicd-mdio" -+- reg: address and length of the register set for the MDIO interface -+- #size-cells: must be 0 -+- #address-cells: must be 1 -+- #bus-id: Physical bus ID -+- #logical-bus-id: Logical bus ID, required for cmicd -+- bus-type: "internal" or "external" -+- clocks: clock source -+ -+Example: -+ -+ mdio_int: mdio_int@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ }; -+ -+ mdio_ext: mdio_ext@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #bus-id = <2>; -+ #logical-bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ }; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/Documentation/devicetree/bindings/pci/xgs-iproc-pcie.txt b/Documentation/devicetree/bindings/pci/xgs-iproc-pcie.txt ---- a/Documentation/devicetree/bindings/pci/xgs-iproc-pcie.txt 1970-01-01 08:00:00.000000000 +0800 -+++ b/Documentation/devicetree/bindings/pci/xgs-iproc-pcie.txt 2017-11-09 17:52:49.540901000 +0800 -@@ -0,0 +1,35 @@ -+* Broadcom XGS iProc PCIe controller -+ -+Required properties: -+- compatible: set to "brcm,iproc-pcie" -+- reg: base address and length of the PCIe controller -+- linux,pci-domain: PCI domain ID. Should be unique for each host controller -+- interrupts: interrupt ID -+- #address-cells: set to <3> -+- #size-cells: set to <2> -+- device_type: set to "pci" -+- ranges: ranges for the PCI memory and I/O regions -+ -+Optional properties: -+- phy-addr: PCIe PHY addr for MDIO access -+- bus-range: PCI bus numbers covered -+ -+Example: -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ }; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/Documentation/devicetree/bindings/spi/xgs-iproc-qspi.txt b/Documentation/devicetree/bindings/spi/xgs-iproc-qspi.txt ---- a/Documentation/devicetree/bindings/spi/xgs-iproc-qspi.txt 1970-01-01 08:00:00.000000000 +0800 -+++ b/Documentation/devicetree/bindings/spi/xgs-iproc-qspi.txt 2017-11-09 17:52:50.501910000 +0800 -@@ -0,0 +1,34 @@ -+BROADCOM XGS iProc QSPI controller -+ -+Required properties: -+- compatible: "brcm,iproc-qspi"; -+- reg: Offset and length of the register set including -+ mspi_hw: Master SPI -+ bspi_hw: Boot SPI -+ bspi_hw_raf: Boot SPI read ahead fifo -+ qspi_intr: QSPI interrupt related -+ idm_qspi:QSPI IDM related -+ cru_hw: QSPI CRU related -+- interrupts: interrupt id of the QSPI controller -+- clocks: clock source -+ -+Optional properties: -+- #chip-select: Specify the used chip select for controller with multi chip selects -+ -+Example: -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0x1811f408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ }; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/Kconfig b/arch/arm/Kconfig ---- a/arch/arm/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/arch/arm/Kconfig 2017-11-09 17:52:54.375925000 +0800 -@@ -850,6 +850,8 @@ source "arch/arm/mach-iop33x/Kconfig" - - source "arch/arm/mach-iop13xx/Kconfig" - -+source "arch/arm/mach-iproc/Kconfig" -+ - source "arch/arm/mach-ixp4xx/Kconfig" - - source "arch/arm/mach-keystone/Kconfig" -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/Makefile b/arch/arm/Makefile ---- a/arch/arm/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/arch/arm/Makefile 2017-11-09 17:52:54.385925000 +0800 -@@ -176,6 +176,7 @@ machine-$(CONFIG_ARCH_INTEGRATOR) += int - machine-$(CONFIG_ARCH_IOP13XX) += iop13xx - machine-$(CONFIG_ARCH_IOP32X) += iop32x - machine-$(CONFIG_ARCH_IOP33X) += iop33x -+machine-$(CONFIG_ARCH_XGS_IPROC) += iproc - machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx - machine-$(CONFIG_ARCH_KEYSTONE) += keystone - machine-$(CONFIG_ARCH_KS8695) += ks8695 -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile ---- a/arch/arm/boot/dts/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/arch/arm/boot/dts/Makefile 2017-11-09 17:52:54.462930000 +0800 -@@ -777,6 +777,17 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb - dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb -+ -+dtb-$(CONFIG_MACH_HX4) += bcm956340.dtb -+dtb-$(CONFIG_MACH_KT2) += bcm956450.dtb -+dtb-$(CONFIG_MACH_HR2) += bcm956150.dtb -+dtb-$(CONFIG_MACH_GH) += bcm95341x.dtb -+dtb-$(CONFIG_MACH_GH2) += bcm956170.dtb bcm95357x.dtb -+dtb-$(CONFIG_MACH_SB2) += bcm956260.dtb -+dtb-$(CONFIG_MACH_WH2) += bcm953547.dtb -+dtb-$(CONFIG_MACH_HR3) += bcm956160.dtb \ -+ bcm953444.dtb -+ - endif - - dtstree := $(srctree)/$(src) -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-greyhound.dtsi b/arch/arm/boot/dts/bcm-greyhound.dtsi ---- a/arch/arm/boot/dts/bcm-greyhound.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-greyhound.dtsi 2017-11-09 17:52:54.682932000 +0800 -@@ -0,0 +1,362 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom GH iProc"; -+ compatible = "brcm,greyhound"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@0x1800fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk"; -+ clocks = <&osc>; -+ reg = <0x1800fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18020000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18020000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18021000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18021000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18042000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18042000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <12>; -+ pin-offset = <4>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,gh"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18111000 0x1000>; -+ vbus-gpio = <&gpio_ccg 6 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@18048000 { -+ compatible = "generic-ehci"; -+ reg = <0x18048000 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@18048800 { -+ compatible = "generic-ohci"; -+ reg = <0x18048800 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@1804c000 { -+ compatible = "brcm,usbd,gh"; -+ reg = <0x1804c000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18046000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18046000 0x600>, -+ <0xf8105408 0x10>, -+ <0x18046f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0xf8106408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18008000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18008000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_ext: mdio_ext@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #bus-id = <2>; -+ #logical-bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ pnor_flash: pnor_flash@18045000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "brcm,iproc-nor"; -+ reg = nor_regs: <0x18045000 0x1000>, -+ nor_mem: <0xE8000000 0x8000000>, -+ nor_sel: <0x18000c8c 0x4>, -+ nor_strap: <0x18000a5c 0x4>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18032000 { -+ compatible = "brcm,iproc-rng"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18032000 0x1000>; -+ rng-type = "rng200"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18009000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18009000 0x1000>, -+ iproc_reset_reg: <0x1800f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@03200000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x03200000 0x100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p7"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x20000000, -+ * cpu addr 0x20000000, size 0x0 0x20000000 -+ */ -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1800f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1800f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1800fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = idm0: <0x18100000 0x100000>, -+ idm1: <0xf8100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-greyhound2.dtsi b/arch/arm/boot/dts/bcm-greyhound2.dtsi ---- a/arch/arm/boot/dts/bcm-greyhound2.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-greyhound2.dtsi 2017-11-09 17:52:54.683934000 +0800 -@@ -0,0 +1,415 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom GH2 iProc"; -+ compatible = "brcm,greyhound2"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@0x1800fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk"; -+ clocks = <&osc>; -+ reg = <0x1800fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18020000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18020000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18021000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18021000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18042000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18042000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac1: ethernet@1804a000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x1804a000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <12>; -+ pin-offset = <4>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,gh"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18111000 0x1000>, -+ idm_utmih: <0x18049500 0x100>; -+ vbus-gpio = <&gpio_ccg 6 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@18048000 { -+ compatible = "generic-ehci"; -+ reg = <0x18048000 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@18048800 { -+ compatible = "generic-ohci"; -+ reg = <0x18048800 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@1804c000 { -+ compatible = "brcm,usbd,gh"; -+ reg = <0x1804c000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18046000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18046000 0x600>, -+ <0xf8105408 0x10>, -+ <0x18046f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0xf8106408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18008000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18008000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ ccg_mdio_int: ccg_mdio_int@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_int: mdio_int@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <0>; -+ #logical-bus-id = <1>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_ext: mdio_ext@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <2>; -+ #logical-bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ pnor_flash: pnor_flash@18045000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "brcm,iproc-nor"; -+ reg = nor_regs: <0x18045000 0x1000>, -+ nor_mem: <0xE8000000 0x8000000>, -+ nor_sel: <0x18000c8c 0x4>, -+ nor_strap: <0x18000a5c 0x4>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18032000 { -+ compatible = "brcm,iproc-rng"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18032000 0x1000>; -+ rng-type = "rng200"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18009000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18009000 0x1000>, -+ iproc_reset_reg: <0x1800f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ dmac0: dma@18018000 { -+ compatible = "brcm,dma330", "arm,primecell"; -+ reg = dma330_base: <0x18018000 0x1000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ #dma-cells = <1>; -+ #dma-channels = <8>; -+ #dma-requests = <16>; -+ status = "disabled"; -+ }; -+ -+ crypto: crypto@03100000 { -+ compatible = "brcm,iproc-crypto"; -+ reg = axi: <0x03100000 0x100>, /* SPUM AXI registers */ -+ apb: <0x18037000 0x100>, /* SPUM control registers */ -+ idm: <0x1811a000 0x1000>; /* Crypto control registers */ -+ brcm,max-pkt-size = <65536>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@03200000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x03200000 0x100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p7"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x20000000, -+ * cpu addr 0x20000000, size 0x0 0x20000000 -+ */ -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1800f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1800f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1800fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = idm0: <0x18100000 0x100000>, -+ idm1: <0xf8100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-helix4.dtsi b/arch/arm/boot/dts/bcm-helix4.dtsi ---- a/arch/arm/boot/dts/bcm-helix4.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-helix4.dtsi 2017-11-09 17:52:54.684933000 +0800 -@@ -0,0 +1,434 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom HX4 iProc"; -+ compatible = "brcm,helix4"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ enable-method = "brcm,bcm-nsp-smp"; -+ secondary-boot-reg = <0xffff042c>; -+ reg = <0x1>; -+ }; -+ }; -+ -+ mpcore { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ /*arm,parity-enable = <1>; -+ interrupts = ;*/ -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@0x1803fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk", "axi-clk-hx4"; -+ clocks = <&osc>; -+ reg = <0x1803fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18000300 { -+ compatible = "ns16550a"; -+ reg = <0x18000300 0x100>; -+ interrupts = ; -+ clock-frequency = <62500000>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18000400 { -+ compatible = "ns16550a"; -+ reg = <0x18000400 0x100>; -+ interrupts = ; -+ clock-frequency = <62500000>; -+ status = "disabled"; -+ }; -+ -+ uart2: serial@18037000 { -+ compatible = "ns16550a"; -+ reg = <0x18037000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gpio_cca: gpio@18000060 { -+ compatible = "brcm,iproc-gpio,cca"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x18000060 0x50>, -+ intr: <0x18000000 0x50>; -+ ngpios = <8>; -+ pin-offset = <0>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18022000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18022000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac1: ethernet@18023000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18023000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18026000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18026000 0x600>, -+ <0x1811b408 0x10>, -+ <0x18026f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ }; -+ -+ qspi: spi@18027000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18027200 0x188>, -+ bspi_hw:<0x18027000 0x050>, -+ bspi_hw_raf:<0x18027100 0x024>, -+ qspi_intr:<0x180273a0 0x01c>, -+ idm_qspi:<0x1811c408 0x004>, -+ cru_hw:<0x1803e000 0x004>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,hx4"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18116000 0x1000>; -+ vbus-gpio = <&gpio_cca 1 GPIO_ACTIVE_LOW>; -+ usbdev-gpio = <&gpio_cca 0 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@1802a000 { -+ compatible = "generic-ehci"; -+ reg = <0x1802a000 0x1000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@18042000 { -+ compatible = "brcm,usbd,hx4"; -+ reg = <0x18042000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18038000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18038000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@1803b000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x1803b000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ mdio_ext: mdio_ext@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18033000 { -+ compatible = "brcm,iproc-rng"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18033000 0x1000>; -+ rng-type = "rng"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@0x18039000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18039000 0x1000>, -+ iproc_reset_reg: <0x1803f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ dmac0: dma@18020000 { -+ compatible = "arm,pl330", "arm,primecell"; -+ reg = pl330_base: <0x18020000 0x1000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ /*arm,primecell-periphid = <0x00041330>;*/ -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ #dma-cells = <1>; -+ #dma-channels = <8>; -+ #dma-requests = <16>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@48000000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x48000000 0x40000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p2"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x08000000, -+ * cpu addr 0x08000000, size 0x0 0x08000000 -+ */ -+ ranges = <0x82000000 0 0x08000000 0x08000000 0 0x08000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie1: pcie@18013000 { -+ compatible = "brcm,iproc-pcie", "iproc-p2"; -+ reg = <0x18013000 0x1000>; -+ linux,pci-domain = <1>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x40000000, -+ * cpu addr 0x40000000, size 0x0 0x08000000 -+ */ -+ ranges = <0x82000000 0 0x40000000 0x40000000 0 0x08000000>; -+ phy-addr = <1>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1803f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x1803f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1803fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x1803fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-hurricane2.dtsi b/arch/arm/boot/dts/bcm-hurricane2.dtsi ---- a/arch/arm/boot/dts/bcm-hurricane2.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-hurricane2.dtsi 2017-11-09 17:52:54.685935000 +0800 -@@ -0,0 +1,314 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom HR2 iProc"; -+ compatible = "brcm,hurricane2"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@1803fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk", "axi-clk-hr2"; -+ clocks = <&osc>; -+ reg = <0x1803fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18000300 { -+ compatible = "ns16550a"; -+ reg = <0x18000300 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18000400 { -+ compatible = "ns16550a"; -+ reg = <0x18000400 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ gpio_cca: gpio@18000060 { -+ compatible = "brcm,iproc-gpio,cca"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x18000060 0x50>, -+ intr: <0x18000000 0x50>, -+ dmu: <0x18020000 0x200>; -+ ngpios = <12>; -+ pin-offset = <0>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18022000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18022000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18026000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18026000 0x600>, -+ <0x1811b408 0x10>, -+ <0x18026f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18027000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18027200 0x188>, -+ bspi_hw:<0x18027000 0x050>, -+ bspi_hw_raf:<0x18027100 0x024>, -+ qspi_intr:<0x180273a0 0x01c>, -+ idm_qspi:<0x1811c408 0x004>, -+ cru_hw:<0x1803e000 0x004>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ mdio_ext: mdio_ext@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ pnor_flash: pnor_flash@18021000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "brcm,iproc-nor"; -+ reg = nor_regs: <0x18021000 0x1000>, -+ nor_mem: <0x20000000 0x4000000>, -+ nor_sel: <0x1803fc3c 0x4>; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18039000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18039000 0x1000>, -+ iproc_reset_reg: <0x1803f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@48000000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x48000000 0x40000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p2"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x08000000, -+ * cpu addr 0x08000000, size 0x0 0x08000000 -+ */ -+ ranges = <0x82000000 0 0x08000000 0x08000000 0 0x08000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1803f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1803f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1803fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1803fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = <0x18100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-hurricane3.dtsi b/arch/arm/boot/dts/bcm-hurricane3.dtsi ---- a/arch/arm/boot/dts/bcm-hurricane3.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-hurricane3.dtsi 2017-11-09 17:52:54.686936000 +0800 -@@ -0,0 +1,369 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom HR3 iProc"; -+ compatible = "brcm,hurricane3"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@1800fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk"; -+ clocks = <&osc>; -+ reg = <0x1800fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18020000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18020000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18021000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18021000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18042000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18042000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <12>; -+ pin-offset = <4>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,gh"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18111000 0x1000>; -+ vbus-gpio = <&gpio_ccg 3 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@0x18048000 { -+ compatible = "generic-ehci"; -+ reg = <0x18048000 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@0x18048800 { -+ compatible = "generic-ohci"; -+ reg = <0x18048800 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@1804c000 { -+ compatible = "brcm,usbd,hr3"; -+ reg = <0x1804c000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ sdio: sdio@18041000 { -+ compatible = "brcm,iproc-hr3-sdio"; -+ reg = <0x18041000 0x1000>, -+ <0x18116408 0x1000>; -+ reg-names = "sdio", "iproc-idm"; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18046000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18046000 0x600>, -+ <0x1811d408 0x10>, -+ <0x18046f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0x1811f408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18008000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18008000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_ext: mdio_ext@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #bus-id = <2>; -+ #logical-bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ pnor_flash: pnor_flash@18045000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "brcm,iproc-nor"; -+ reg = nor_regs: <0x18045000 0x1000>, -+ nor_mem: <0xE8000000 0x8000000>, -+ nor_sel: <0x18000c8c 0x4>, -+ nor_strap: <0x18000a5c 0x4>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18032000 { -+ compatible = "brcm,iproc-rng"; -+ reg = <0x18032000 0x1000>; -+ rng-type = "rng200"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18009000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18009000 0x1000>, -+ iproc_reset_reg: <0x1800f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@03200000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x03200000 0x100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x20000000, -+ * cpu addr 0x20000000, size 0x0 0x20000000 -+ */ -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1800f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1800f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1800fc00 0x100>; -+ -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = <0x18100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+ -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-katana2.dtsi b/arch/arm/boot/dts/bcm-katana2.dtsi ---- a/arch/arm/boot/dts/bcm-katana2.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-katana2.dtsi 2017-11-09 17:52:54.687932000 +0800 -@@ -0,0 +1,431 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom KT2 iProc"; -+ compatible = "brcm,katana2"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ enable-method = "brcm,bcm-nsp-smp"; -+ secondary-boot-reg = <0xffff042c>; -+ reg = <0x1>; -+ }; -+ }; -+ -+ mpcore { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: axi_clk_fixed_495M { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <495000000>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18000300 { -+ compatible = "ns16550a"; -+ reg = <0x18000300 0x100>; -+ interrupts = ; -+ clock-frequency = <61875000>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18000400 { -+ compatible = "ns16550a"; -+ reg = <0x18000400 0x100>; -+ interrupts = ; -+ clock-frequency = <61875000>; -+ status = "disabled"; -+ }; -+ -+ uart2: serial@18037000 { -+ compatible = "ns16550a"; -+ reg = <0x18037000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gpio_cca: gpio@18000060 { -+ compatible = "brcm,iproc-gpio,cca"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x18000060 0x50>, -+ intr: <0x18000000 0x50>; -+ ngpios = <8>; -+ pin-offset = <0>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18022000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18022000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac1: ethernet@18023000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18023000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18026000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18026000 0x600>, -+ <0x1811b408 0x10>, -+ <0x18026f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ }; -+ -+ qspi: spi@18027000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18027200 0x188>, -+ bspi_hw:<0x18027000 0x050>, -+ bspi_hw_raf:<0x18027100 0x024>, -+ qspi_intr:<0x180273a0 0x01c>, -+ idm_qspi:<0x1811c408 0x004>, -+ cru_hw:<0x1803e000 0x004>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,kt2"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18116000 0x1000>; -+ vbus-gpio = <&gpio_cca 1 GPIO_ACTIVE_LOW>; -+ usbdev-gpio = <&gpio_cca 0 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@1802a000 { -+ compatible = "generic-ehci"; -+ reg = <0x1802a000 0x1000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@18042000 { -+ compatible = "brcm,usbd,kt2"; -+ reg = <0x18042000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@0x18038000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18038000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@1803b000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x1803b000 0x100>; -+ interrupts = ; -+ #bus-id = <1>; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ mdio_ext: mdio_ext@18032000 { -+ compatible = "brcm,iproc-ccb-mdio"; -+ reg = <0x18032000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18033000 { -+ compatible = "brcm,iproc-rng"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18033000 0x1000>; -+ rng-type = "rng"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18039000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18039000 0x1000>, -+ iproc_reset_reg: <0x1803f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ dmac0: dma@18020000 { -+ compatible = "arm,pl330", "arm,primecell"; -+ reg = pl330_base: <0x18020000 0x1000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ /*arm,primecell-periphid = <0x00041330>;*/ -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ #dma-cells = <1>; -+ #dma-channels = <8>; -+ #dma-requests = <16>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@48000000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x48000000 0x40000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p2"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x08000000, -+ * cpu addr 0x08000000, size 0x0 0x08000000 -+ */ -+ ranges = <0x82000000 0 0x08000000 0x08000000 0 0x08000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie1: pcie@18013000 { -+ compatible = "brcm,iproc-pcie", "iproc-p2"; -+ reg = <0x18013000 0x1000>; -+ linux,pci-domain = <1>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x40000000, -+ * cpu addr 0x40000000, size 0x0 0x08000000 -+ */ -+ ranges = <0x82000000 0 0x40000000 0x40000000 0 0x08000000>; -+ phy-addr = <1>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1803f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x1803f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1803fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x1803fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-saber2.dtsi b/arch/arm/boot/dts/bcm-saber2.dtsi ---- a/arch/arm/boot/dts/bcm-saber2.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-saber2.dtsi 2017-11-09 17:52:54.689928000 +0800 -@@ -0,0 +1,356 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+/ { -+ model = "Broadcom SB2 iProc"; -+ compatible = "brcm,saber2"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator_25M { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ osc_1: oscillator_50M { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <50000000>; -+ }; -+ -+ periph_clk: periph_clk@19000000 { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@1800fc50 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk", "axi-clk-sb2"; -+ clocks = <&osc_1>; -+ reg = <0x1800fc50 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18020000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18020000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18021000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18021000 0x1000>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0xf8106408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ -+ gmac0: ethernet@18042000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18042000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,sb2"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18111000 0x1000>; -+ vbus-gpio = <&gpio_ccg 1 GPIO_ACTIVE_LOW>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@18048000 { -+ compatible = "generic-ehci"; -+ reg = <0x18048000 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@18048800 { -+ compatible = "generic-ohci"; -+ reg = <0x18048800 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@1804c000 { -+ compatible = "brcm,usbd,sb2"; -+ reg = usb2d: <0x1804c000 0x2000>, -+ idm_usb: <0x18111000 0x1000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <16>; -+ pin-offset = <0>; -+ pin-base = <0>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ nand: nand@18046000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; -+ reg = <0x18046000 0x600>, -+ <0xf8105408 0x10>, -+ <0x18046f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ brcm,nand-has-wp; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18008000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18008000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ mdio_int: mdio_int@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ mdio_ext: mdio_ext@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #bus-id = <0>; -+ bus-type = "external"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18032000 { -+ compatible = "brcm,iproc-rng"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x18032000 0x1000>; -+ rng-type = "rng200"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18009000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18009000 0x1000>, -+ iproc_reset_reg: <0x1800f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@03200000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x03200000 0x100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie", "iproc-p7"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x20000000, -+ * cpu addr 0x20000000, size 0x0 0x20000000 -+ */ -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1800f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1800f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1800fc00 0x100>; -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = idm0: <0x18100000 0x100000>, -+ idm1: <0xf8100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm-wolfhound2.dtsi b/arch/arm/boot/dts/bcm-wolfhound2.dtsi ---- a/arch/arm/boot/dts/bcm-wolfhound2.dtsi 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm-wolfhound2.dtsi 2017-11-09 17:52:54.690928000 +0800 -@@ -0,0 +1,354 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include "skeleton.dtsi" -+ -+ -+/ { -+ model = "Broadcom HR3 iProc"; -+ compatible = "brcm,hurricane3"; -+ interrupt-parent = <&gic>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+ -+ core { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@00000 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-armpll"; -+ clocks = <&osc>; -+ reg = <0x0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, <0x20100 0x100>; -+ }; -+ -+ twd-timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ arm,filter-ranges = <0x60000000 0x80000000>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iproc_axi_clk: iproc_axi_clk@1800fc00 { -+ #clock-cells = <0>; -+ compatible = "brcm,xgs-iproc-axi-clk"; -+ clocks = <&osc>; -+ reg = <0x1800fc00 0x1c>; -+ }; -+ -+ iproc_apb_clk: iproc_apb_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&iproc_axi_clk>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi { -+ compatible = "simple-bus"; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@18020000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18020000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@18021000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x18021000 0x100>; -+ interrupts = ; -+ clocks = <&iproc_apb_clk>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ gmac0: ethernet@18042000 { -+ compatible = "brcm,iproc-gmac"; -+ reg = <0x18042000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gpio_ccg: gpio@1800a000 { -+ compatible = "brcm,iproc-gpio,ccg"; -+ #gpio-cells = <2>; -+ reg = gpio: <0x1800a000 0x50>; -+ ngpios = <12>; -+ pin-offset = <4>; -+ pin-base = <4>; -+ gpio-controller; -+ interrupt-controller; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ usbphy0: usbphy0 { -+ #phy-cells = <0>; -+ compatible = "brcm,usb-phy,gh"; -+ reg = idm_usb2h: <0x18115000 0x1000>, -+ idm_usb2d: <0x18111000 0x1000>; -+ vbus-gpio = <&gpio_ccg 3 GPIO_ACTIVE_HIGH>; -+ status = "disabled"; -+ }; -+ -+ ehci0: usb@0x18048000 { -+ compatible = "generic-ehci"; -+ reg = <0x18048000 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@0x18048800 { -+ compatible = "generic-ohci"; -+ reg = <0x18048800 0x800>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ usbd: usbd@1804c000 { -+ compatible = "brcm,usbd,hr3"; -+ reg = <0x1804c000 0x2000>; -+ interrupts = ; -+ usb-phy = <&usbphy0>; -+ status = "disabled"; -+ }; -+ -+ qspi: spi@18047000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "brcm,iproc-qspi"; -+ reg = mspi_hw:<0x18047200 0x188>, -+ bspi_hw:<0x18047000 0x050>, -+ bspi_hw_raf:<0x18047100 0x024>, -+ qspi_intr:<0x180473a0 0x01c>, -+ idm_qspi:<0x1811f408 0x004>, -+ cru_hw:<0x1800e000 0x004>; -+ interrupts = ; -+ #chip-select = <0>; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18008000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18008000 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = ; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_int0: mdio_int0@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <0>; -+ #logical-bus-id = <0>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* cmicd cmic_common mdio */ -+ mdio_int1: mdio_int1@03210000 { -+ compatible = "brcm,iproc-cmicd-mdio"; -+ reg = <0x03210000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <1>; -+ #logical-bus-id = <1>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ /* CCG mdio */ -+ mdio_int2: mdio_int2@18002000 { -+ compatible = "brcm,iproc-ccg-mdio"; -+ reg = <0x18002000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #bus-id = <2>; -+ bus-type = "internal"; -+ clocks = <&iproc_apb_clk>; -+ status = "disabled"; -+ }; -+ -+ hwrng: hwrng@18032000 { -+ compatible = "brcm,iproc-rng"; -+ reg = <0x18032000 0x1000>; -+ rng-type = "rng200"; -+ status = "disabled"; -+ }; -+ -+ iproc_wdt: iproc_wdt@18009000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = iproc_wdt_base: <0x18009000 0x1000>, -+ iproc_reset_reg: <0x1800f014 0x4>; -+ wdt_boot_status_bit = <0x0>; -+ clocks = <&iproc_apb_clk>; -+ clock-names = "apb_pclk"; -+ status = "disabled"; -+ }; -+ -+ /* cmicd */ -+ iproc_cmicd: iproc_cmicd@03200000 { -+ compatible = "brcm,iproc-cmicd"; -+ reg = <0x03200000 0x100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ pcie0: pcie@18012000 { -+ compatible = "brcm,iproc-pcie"; -+ reg = <0x18012000 0x1000>; -+ linux,pci-domain = <0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ /*non-prefetchable mem space, pcie addr 0x0 0x20000000, -+ * cpu addr 0x20000000, size 0x0 0x20000000 -+ */ -+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x20000000>; -+ phy-addr = <0>; -+ status = "disabled"; -+ }; -+ -+ dmu_pcu: dmu_pcu@1800f000 { -+ compatible = "brcm,iproc-dmu-pcu"; -+ reg = <0x1800f000 0xc00>; -+ }; -+ -+ iproc_wrap_ctrl: iproc_wrap_ctrl@1800fc00 { -+ compatible = "brcm,iproc-wrap-ctrl"; -+ reg = <0x1800fc00 0x100>; -+ -+ }; -+ -+ iproc_idm: iproc_idm@18100000 { -+ compatible = "brcm,iproc-idm"; -+ reg = <0x18100000 0x100000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ }; -+ -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm95341x.dts b/arch/arm/boot/dts/bcm95341x.dts ---- a/arch/arm/boot/dts/bcm95341x.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm95341x.dts 2017-11-09 17:52:54.730934000 +0800 -@@ -0,0 +1,207 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-greyhound.dtsi" -+ -+/ { -+ model = "Broadcom GH SVK (BCM95341x)"; -+ compatible = "brcm,bcm95341x", "brcm,greyhound"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x30000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&pnor_flash { -+ status = "okay"; -+ -+ partition@0 { -+ label = "pboot"; -+ reg = <0x0 0xc0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "penv"; -+ reg = <0xc0000 0x40000>; -+ }; -+ partition@2 { -+ label = "psystem"; -+ reg = <0x100000 0xf00000>; -+ }; -+ partition@3 { -+ label = "prootfs"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ partition@4 { -+ label = "pcustfs"; -+ reg = <0x2000000 0x2000000>; -+ }; -+}; -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm953444.dts b/arch/arm/boot/dts/bcm953444.dts ---- a/arch/arm/boot/dts/bcm953444.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm953444.dts 2017-11-09 17:52:54.731931000 +0800 -@@ -0,0 +1,128 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-hurricane3.dtsi" -+ -+/ { -+ model = "Broadcom HR3 SVK (BCM953444K)"; -+ compatible = "brcm,bcm953444k", "brcm,hurricane3"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ #bus-id = <1>; /* cmicd mdio needs #logical-bus-id in addition to #bus-id (physical) */ -+ #logical-bus-id = <1>; -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm953547.dts b/arch/arm/boot/dts/bcm953547.dts ---- a/arch/arm/boot/dts/bcm953547.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm953547.dts 2017-11-09 17:52:54.740928000 +0800 -@@ -0,0 +1,154 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-wolfhound2.dtsi" -+ -+/ { -+ model = "Broadcom HR3-WH2 SVK (BCM953547K)"; -+ compatible = "brcm,bcm953547k", "brcm,hurricane3"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&mdio_int0 { -+ status = "okay"; -+ amac_phy0: amac_phy@0 { -+ reg = <24>; -+ }; -+}; -+ -+&mdio_int1 { -+ status = "okay"; -+ amac_serdes: amac_serdes@0 { -+ reg = <20>; -+ }; -+}; -+ -+&mdio_int2 { -+ status = "okay"; -+ pcie_phy0: pcie_phy@0 { -+ reg = <2>; -+ }; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm95357x.dts b/arch/arm/boot/dts/bcm95357x.dts ---- a/arch/arm/boot/dts/bcm95357x.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm95357x.dts 2017-11-09 17:52:54.744928000 +0800 -@@ -0,0 +1,224 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-greyhound2.dtsi" -+ -+/ { -+ model = "Broadcom RG3 SVK (BCM95357x)"; -+ compatible = "brcm,bcm95357x", "brcm,greyhound2"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&gmac1 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x30000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&pnor_flash { -+ status = "okay"; -+ -+ partition@0 { -+ label = "pboot"; -+ reg = <0x0 0xc0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "penv"; -+ reg = <0xc0000 0x40000>; -+ }; -+ partition@2 { -+ label = "psystem"; -+ reg = <0x100000 0xf00000>; -+ }; -+ partition@3 { -+ label = "prootfs"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ partition@4 { -+ label = "pcustfs"; -+ reg = <0x2000000 0x2000000>; -+ }; -+}; -+ -+&ccg_mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&dmac0 { -+ status = "okay"; -+}; -+ -+&crypto { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956150.dts b/arch/arm/boot/dts/bcm956150.dts ---- a/arch/arm/boot/dts/bcm956150.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956150.dts 2017-11-09 17:52:54.744938000 +0800 -@@ -0,0 +1,180 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-hurricane2.dtsi" -+ -+/ { -+ model = "Broadcom HR2 SVK (BCM956150K)"; -+ compatible = "brcm,bcm956150k", "brcm,hurricane2"; -+ -+ aliases { -+ serial0 = &uart1; -+ serial1 = &uart0; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&gpio_cca { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x70000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x01000000>; -+ }; -+ }; -+}; -+ -+&pnor_flash { -+ status = "okay"; -+ -+ partition@0 { -+ label = "pboot"; -+ reg = <0x0 0xc0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "penv"; -+ reg = <0xc0000 0x40000>; -+ }; -+ partition@2 { -+ label = "psystem"; -+ reg = <0x100000 0xf00000>; -+ }; -+ partition@3 { -+ label = "prootfs"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ partition@4 { -+ label = "pcustfs"; -+ reg = <0x2000000 0x2000000>; -+ }; -+}; -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956160.dts b/arch/arm/boot/dts/bcm956160.dts ---- a/arch/arm/boot/dts/bcm956160.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956160.dts 2017-11-09 17:52:54.745938000 +0800 -@@ -0,0 +1,212 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-hurricane3.dtsi" -+ -+/ { -+ model = "Broadcom HR3 SVK (BCM956160K)"; -+ compatible = "brcm,bcm956160k", "brcm,hurricane3"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x30000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&pnor_flash { -+ status = "okay"; -+ -+ partition@0 { -+ label = "pboot"; -+ reg = <0x0 0xc0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "penv"; -+ reg = <0xc0000 0x40000>; -+ }; -+ partition@2 { -+ label = "psystem"; -+ reg = <0x100000 0xf00000>; -+ }; -+ partition@3 { -+ label = "prootfs"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ partition@4 { -+ label = "pcustfs"; -+ reg = <0x2000000 0x2000000>; -+ }; -+}; -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956170.dts b/arch/arm/boot/dts/bcm956170.dts ---- a/arch/arm/boot/dts/bcm956170.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956170.dts 2017-11-09 17:52:54.746936000 +0800 -@@ -0,0 +1,239 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-greyhound2.dtsi" -+ -+/ { -+ model = "Broadcom GH2 SVK (BCM956170)"; -+ compatible = "brcm,bcm956170", "brcm,greyhound2"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&gmac1 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x30000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x03000000>; -+ }; -+ }; -+}; -+ -+&pnor_flash { -+ status = "okay"; -+ -+ partition@0 { -+ label = "pboot"; -+ reg = <0x0 0xc0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "penv"; -+ reg = <0xc0000 0x40000>; -+ }; -+ partition@2 { -+ label = "psystem"; -+ reg = <0x100000 0xf00000>; -+ }; -+ partition@3 { -+ label = "prootfs"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ partition@4 { -+ label = "pcustfs"; -+ reg = <0x2000000 0x2000000>; -+ }; -+}; -+ -+&ccg_mdio_int { -+ status = "okay"; -+ pcie_phy0: pcie_phy@0 { -+ reg = <2>; -+ }; -+}; -+ -+&mdio_int { -+ status = "okay"; -+ amac_serdes0: amac_serdes@0 { -+ reg = <25>; -+ }; -+ amac_serdes1: amac_serdes@1 { -+ reg = <26>; -+ }; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+ amac_phy0: amac_phy@0 { -+ reg = <16>; -+ }; -+ amac_phy1: amac_phy@1 { -+ reg = <17>; -+ }; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&dmac0 { -+ status = "okay"; -+}; -+ -+&crypto { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956260.dts b/arch/arm/boot/dts/bcm956260.dts ---- a/arch/arm/boot/dts/bcm956260.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956260.dts 2017-11-09 17:52:54.747931000 +0800 -@@ -0,0 +1,182 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-saber2.dtsi" -+ -+/ { -+ model = "Broadcom SB2 SVK (BCM956260K)"; -+ compatible = "brcm,bcm956260k", "brcm,saber2"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=1 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_ccg { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c64"; -+ reg = <0x50>; -+ pagesize = <32>; -+ }; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x70000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x01000000>; -+ }; -+ }; -+}; -+ -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956340.dts b/arch/arm/boot/dts/bcm956340.dts ---- a/arch/arm/boot/dts/bcm956340.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956340.dts 2017-11-09 17:52:54.748928000 +0800 -@@ -0,0 +1,196 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-helix4.dtsi" -+ -+/ { -+ model = "Broadcom HX4 SVK (BCM956340K)"; -+ compatible = "brcm,bcm956340k", "brcm,helix4"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&gmac1 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_cca { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&pcie1 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&i2c1 { -+ status = "okay"; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x70000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x01000000>; -+ }; -+ }; -+}; -+ -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&dmac0 { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/bcm956450.dts b/arch/arm/boot/dts/bcm956450.dts ---- a/arch/arm/boot/dts/bcm956450.dts 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm956450.dts 2017-11-09 17:52:54.748939000 +0800 -@@ -0,0 +1,195 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2016 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm-katana2.dtsi" -+ -+/ { -+ model = "Broadcom KT2 SVK (BCM956450K)"; -+ compatible = "brcm,bcm956450k", "brcm,katana2"; -+ -+ aliases { -+ serial0 = &uart0; -+ serial1 = &uart1; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=496M"; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&gmac0 { -+ status = "okay"; -+}; -+ -+&gmac1 { -+ status = "okay"; -+}; -+ -+&usbphy0 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&usbd { -+ status = "okay"; -+}; -+ -+&gpio_cca { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+}; -+ -+&pcie1 { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ eeprom@0x50 { -+ compatible = "atmel,24c01"; -+ reg = <0x50>; -+ pagesize = <8>; -+ }; -+}; -+ -+&i2c1 { -+ status = "okay"; -+}; -+ -+&nand { -+ status = "okay"; -+ nandcs@1 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ nand-on-flash-bbt; -+ /*nand-bus-width = <8>;*/ -+ nand-ecc-strength = <24>; -+ nand-ecc-step-size = <1024>; -+ brcm,nand-oob-sector-size = <27>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "nboot"; -+ reg = <0x0 0x200000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "nenv"; -+ reg = <0x200000 0x400000>; -+ }; -+ partition@2 { -+ label = "nsystem"; -+ reg = <0x600000 0xa00000>; -+ }; -+ partition@3 { -+ label = "nrootfs"; -+ reg = <0x1000000 0xf000000>; -+ }; -+ partition@4 { -+ label = "ncustfs"; -+ reg = <0x10000000 0x70000000>; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "okay"; -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "m25p80"; -+ m25p,fast-read = <1>; -+ spi-max-frequency = <62500000>; -+ reg = <0x0>; -+ partition@0 { -+ label = "boot"; -+ reg = <0x00000000 0x000c0000>; -+ /*read-only;*/ -+ }; -+ partition@1 { -+ label = "env"; -+ reg = <0x000c0000 0x00040000>; -+ }; -+ partition@2 { -+ label = "system"; -+ reg = <0x00100000 0x00f00000>; -+ }; -+ partition@3 { -+ label = "rootfs"; -+ reg = <0x01000000 0x01000000>; -+ }; -+ }; -+}; -+ -+ -+&mdio_int { -+ status = "okay"; -+}; -+ -+&mdio_ext { -+ status = "okay"; -+}; -+ -+&hwrng { -+ status = "okay"; -+}; -+ -+&iproc_wdt { -+ status = "okay"; -+}; -+ -+&dmac0 { -+ status = "okay"; -+}; -+ -+&iproc_cmicd { -+ status = "okay"; -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/greyhound.its b/arch/arm/boot/dts/greyhound.its ---- a/arch/arm/boot/dts/greyhound.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/greyhound.its 2017-11-09 17:52:54.939941000 +0800 -@@ -0,0 +1,62 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm95341x.dtb"; -+ data = /incbin/("./bcm95341x.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+/* -+ fdt@2 { -+ description = "Flattened Device Tree blob - bcm95606x.dtb"; -+ data = /incbin/("./bcm95606x.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "md5"; -+ }; -+ }; -+*/ -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+/* -+ conf@2 { -+ description = "Boot Linux kernel with FDT blob"; -+ kernel = "kernel@1"; -+ fdt = "fdt@2"; -+ }; -+*/ -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/greyhound2.its b/arch/arm/boot/dts/greyhound2.its ---- a/arch/arm/boot/dts/greyhound2.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/greyhound2.its 2017-11-09 17:52:54.945934000 +0800 -@@ -0,0 +1,62 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956170.dtb"; -+ data = /incbin/("./bcm956170.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@2 { -+ description = "Flattened Device Tree blob - bcm95357x.dtb"; -+ data = /incbin/("./bcm95357x.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+/* -+ conf@2 { -+ description = "Boot Linux kernel with FDT blob"; -+ kernel = "kernel@1"; -+ fdt = "fdt@2"; -+ }; -+*/ -+ }; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/helix4.its b/arch/arm/boot/dts/helix4.its ---- a/arch/arm/boot/dts/helix4.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/helix4.its 2017-11-09 17:52:54.946939000 +0800 -@@ -0,0 +1,43 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956340.dtb"; -+ data = /incbin/("./bcm956340.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/hurricane2.its b/arch/arm/boot/dts/hurricane2.its ---- a/arch/arm/boot/dts/hurricane2.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/hurricane2.its 2017-11-09 17:52:54.966932000 +0800 -@@ -0,0 +1,43 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x81008000>; -+ entry = <0x81008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956150.dtb"; -+ data = /incbin/("./bcm956150.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ }; -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/hurricane3.its b/arch/arm/boot/dts/hurricane3.its ---- a/arch/arm/boot/dts/hurricane3.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/hurricane3.its 2017-11-09 17:52:54.966943000 +0800 -@@ -0,0 +1,60 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956160.dtb"; -+ data = /incbin/("./bcm956160.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@2 { -+ description = "Flattened Device Tree blob - bcm953444.dtb"; -+ data = /incbin/("./bcm953444.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob 1"; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ -+ conf@2 { -+ description = "Boot Linux kernel with FDT blob 2"; -+ kernel = "kernel@1"; -+ fdt = "fdt@2"; -+ }; -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/katana2.its b/arch/arm/boot/dts/katana2.its ---- a/arch/arm/boot/dts/katana2.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/katana2.its 2017-11-09 17:52:55.281942000 +0800 -@@ -0,0 +1,43 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956450.dtb"; -+ data = /incbin/("./bcm956450.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/saber2.its b/arch/arm/boot/dts/saber2.its ---- a/arch/arm/boot/dts/saber2.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/saber2.its 2017-11-09 17:52:55.880949000 +0800 -@@ -0,0 +1,43 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm956260.dtb"; -+ data = /incbin/("./bcm956260.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob "; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/boot/dts/wolfhound2.its b/arch/arm/boot/dts/wolfhound2.its ---- a/arch/arm/boot/dts/wolfhound2.its 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/boot/dts/wolfhound2.its 2017-11-09 17:52:56.333945000 +0800 -@@ -0,0 +1,60 @@ -+/dts-v1/; -+ -+/ { -+ description = "Linux kernel and FDT blob"; -+ #address-cells = <1>; -+ -+ images { -+ kernel@1 { -+ description = "Broadcom iProc Linux"; -+ data = /incbin/("../zImage"); -+ type = "kernel"; -+ arch = "arm"; -+ os = "linux"; -+ compression = "none"; -+ load = <0x61008000>; -+ entry = <0x61008000>; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ fdt@1 { -+ description = "Flattened Device Tree blob - bcm953547.dtb"; -+ data = /incbin/("./bcm953547.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; -+ -+ /* fdt@2 { -+ description = "Flattened Device Tree blob - bcm953444.dtb"; -+ data = /incbin/("./bcm953444.dtb"); -+ type = "flat_dt"; -+ arch = "arm"; -+ compression = "none"; -+ hash@1 { -+ algo = "crc32"; -+ }; -+ }; */ -+ }; -+ -+ configurations { -+ default = "conf@1"; -+ conf@1 { -+ description = "Boot Linux kernel with FDT blob 1"; -+ kernel = "kernel@1"; -+ fdt = "fdt@1"; -+ }; -+ -+ /* conf@2 { -+ description = "Boot Linux kernel with FDT blob 2"; -+ kernel = "kernel@1"; -+ fdt = "fdt@2"; -+ }; */ -+ }; -+}; -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig ---- a/arch/arm/mach-iproc/Kconfig 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/Kconfig 2017-11-09 17:52:58.315964000 +0800 -@@ -0,0 +1,84 @@ -+menuconfig ARCH_XGS_IPROC -+ bool "Broadcom XGS iProc Support" if ARCH_MULTI_V7 -+ select HAVE_ARM_TWD if SMP -+ select HAVE_ARM_SCU if SMP -+ select ARM_GLOBAL_TIMER -+ select ARM_GIC -+ select ARCH_REQUIRE_GPIOLIB -+ select CACHE_L2X0 -+ select ARM_AMBA -+ select ARCH_SUPPORTS_BIG_ENDIAN -+ select CPU_ENDIAN_BE8 if CPU_BIG_ENDIAN -+ select ARM_ERRATA_754322 -+ select ARM_ERRATA_764369 if SMP -+ select ARM_ERRATA_775420 -+ help -+ This enables support for Broadcom XGS iProc based SoC chips -+ -+if ARCH_XGS_IPROC -+ -+comment "XGS iProc SoC based Machine types" -+ -+choice -+ prompt "XGS iProc SoC based Machine types" -+ default MACH_HX4 -+ -+config MACH_HX4 -+ bool "Support Broadcom Helix4 bring-up board" -+ help -+ Support for the Broadcom Helix4 bring-up board. -+ -+config MACH_HR2 -+ bool "Support Broadcom Hurricane2 bring-up board" -+ help -+ Support for the Broadcom Hurricane2 bring-up board. -+ -+config MACH_KT2 -+ bool "Support Broadcom Katana2 bring-up board" -+ help -+ Support for the Broadcom Katana2 bring-up board. -+ -+config MACH_GH -+ bool "Support Broadcom Greyhound bring-up board" -+ select MACH_IPROC_P7 -+ help -+ Support for the Broadcom Greyhound bring-up board. -+ -+config MACH_SB2 -+ bool "Support Broadcom Saber2 bring-up board" -+ select MACH_IPROC_P7 -+ help -+ Support for the Broadcom Saber2 bring-up board. -+ -+config MACH_HR3 -+ bool "Support Broadcom Hurricane3 bring-up board" -+ select MACH_IPROC_P7 -+ help -+ Support for the Broadcom Hurricane3 bring-up board. -+ -+config MACH_GH2 -+ bool "Support Broadcom Greyhound2 bring-up board" -+ select MACH_IPROC_P7 -+ help -+ Support for the Broadcom Greyhound2 bring-up board. -+endchoice -+ -+config MACH_IPROC_P7 -+ bool "Support iProc Profile 7 architecture" -+ depends on (MACH_GH || MACH_SB2 || MACH_HR3 || MACH_GH2 || MACH_WH2) -+ help -+ Support for iProc Profile 7 architecture. -+ -+config MACH_WH2 -+ bool "Support Broadcom Wolfhound2 bring-up board" -+ depends on MACH_HR3 -+ default n -+ help -+ Support for the Broadcom Wolfhound2 bring-up board. -+ -+config MACH_IPROC_EMULATION -+ bool "Support iProc emulation" -+ help -+ Support for the iProc emulation. -+ -+endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/Makefile b/arch/arm/mach-iproc/Makefile ---- a/arch/arm/mach-iproc/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/Makefile 2017-11-09 17:52:58.316963000 +0800 -@@ -0,0 +1,3 @@ -+obj-y := board_bu.o -+obj-y += shm.o -+obj-$(CONFIG_SMP) += platsmp.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c ---- a/arch/arm/mach-iproc/board_bu.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/board_bu.c 2017-11-09 17:52:58.317968000 +0800 -@@ -0,0 +1,120 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DMU_CRU_RESET_BASE 0x200 -+ -+#if defined(CONFIG_PL330_DMA) || defined(CONFIG_XGS_IPROC_DMA330_DMA) -+/* SB2/HR3 */ -+#define DMAC_IDM_RESET_OFFSET 0xf800 -+/* HX4/KT2/HR2/GH */ -+#define DMAC_IDM_RESET_OFFSET_1 0x14800 -+#endif /* CONFIG_PL330_DMA || CONFIG_XGS_IPROC_DMA330_DMA */ -+ -+enum xgs_iproc_dev_id { -+ XGS_IPROC_HX4=0, -+ XGS_IPROC_KT2, -+ XGS_IPROC_HR2, -+ XGS_IPROC_GH, -+ XGS_IPROC_SB2, -+ XGS_IPROC_HR3, -+ XGS_IPROC_GH2, -+ XGS_IPROC_GENERIC, -+}; -+ -+const char *const xgs_iproc_dt_compat[] = { -+ "brcm,helix4", -+ "brcm,katana2", -+ "brcm,hurricane2", -+ "brcm,greyhound", -+ "brcm,saber2", -+ "brcm,hurricane3", -+ "brcm,greyhound2", -+ "brcm,xgs-iproc", -+ NULL, -+}; -+ -+#if defined(CONFIG_PL330_DMA) || defined(CONFIG_XGS_IPROC_DMA330_DMA) -+void xgs_iproc_dmac_idm_reset(void) -+{ -+ void __iomem *reset_base = NULL; -+ -+ /* Need to de-assert reset of DMAC before of_platform_populate */ -+ if (of_machine_is_compatible(xgs_iproc_dt_compat[XGS_IPROC_SB2]) || -+ of_machine_is_compatible(xgs_iproc_dt_compat[XGS_IPROC_HR3]) || -+ of_machine_is_compatible(xgs_iproc_dt_compat[XGS_IPROC_GH2])) -+ reset_base = get_iproc_idm_base(0) + DMAC_IDM_RESET_OFFSET; -+ else -+ reset_base = get_iproc_idm_base(0) + DMAC_IDM_RESET_OFFSET_1; -+ -+ if (reset_base != NULL) -+ writel(readl(reset_base) & 0xFFFFFFFE, reset_base); -+} -+#endif /* CONFIG_PL330_DMA || CONFIG_XGS_IPROC_DMA330_DMA */ -+ -+void __init xgs_iproc_init_early(void) -+{ -+ /* -+ * SDK allocates coherent buffers from atomic context. -+ * Increase size of atomic coherent pool to make sure such -+ * the allocations won't fail. -+ */ -+#ifdef CONFIG_DMA_CMA -+ /*can be overrided by "coherent_pool" in bootargs */ -+ init_dma_coherent_pool_size(SZ_1M * 16); -+#endif -+} -+ -+static void __init xgs_iproc_init(void) -+{ -+ int ret; -+ -+ ret = xgs_iproc_wrap_idm_dmu_base_reg_setup(); -+ if (ret < 0) -+ return; -+ -+#if defined(CONFIG_PL330_DMA) || defined(CONFIG_XGS_IPROC_DMA330_DMA) -+ xgs_iproc_dmac_idm_reset(); -+#endif -+ /* Populate platform devices */ -+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -+ -+ /* Setup IDM timeout handler */ -+ xgs_iproc_idm_timeout_handler_setup(); -+} -+ -+ -+static void xgs_iproc_restart(enum reboot_mode mode, const char *cmd) -+{ -+ void * __iomem reg_addr; -+ u32 reg; -+ -+ /* CRU_RESET register */ -+ reg_addr = (void * __iomem)(get_iproc_dmu_pcu_base() + -+ DMU_CRU_RESET_BASE); -+ /* set iproc_reset_n to 0 */ -+ reg = readl(reg_addr); -+ reg &= ~((u32) 1 << 1); -+ -+ writel(reg, reg_addr); -+ -+ /* Wait for reset */ -+ while (1) -+ cpu_do_idle(); -+} -+ -+DT_MACHINE_START(XGS_iProc_DT, "BRCM XGS iProc") -+ .init_early = xgs_iproc_init_early, -+ .init_machine = xgs_iproc_init, -+ .dt_compat = xgs_iproc_dt_compat, -+ .restart = xgs_iproc_restart, -+ .l2c_aux_val = 0, -+ .l2c_aux_mask = ~0, -+MACHINE_END -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/include/plat/shm.h b/arch/arm/mach-iproc/include/plat/shm.h ---- a/arch/arm/mach-iproc/include/plat/shm.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/include/plat/shm.h 2017-11-09 17:52:58.322965000 +0800 -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ */ -+/* -+ * Header for declaring shim layer exports. -+ */ -+ -+#ifndef __SHM_DOT_H_INCLUDED__ -+#define __SHM_DOT_H_INCLUDED__ -+ -+#include -+#include -+#include -+ -+ -+#define iproc_class_create(owner, name) \ -+({ \ -+ static struct lock_class_key __key; \ -+ iproc__class_create(owner, name, &__key); \ -+}) -+ -+extern int iproc_platform_get_irq(struct platform_device *dev, unsigned int num); -+extern struct resource * -+iproc_platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name); -+extern struct resource * -+iproc_platform_get_resource(struct platform_device *dev, unsigned int type, -+ unsigned int num); -+extern int iproc_platform_device_add_resources(struct platform_device *pdev, const struct resource *res, unsigned int num); -+ -+extern int iproc_platform_device_register(struct platform_device * pdev); -+extern void iproc_platform_device_unregister(struct platform_device * pdev); -+extern int iproc_platform_driver_register(struct platform_driver *drv); -+extern void iproc_platform_driver_unregister(struct platform_driver *drv); -+ -+extern struct platform_device *iproc_platform_device_alloc(const char *name, int id); -+ -+extern int iproc_platform_device_add(struct platform_device *pdev); -+extern void iproc_platform_device_put(struct platform_device *pdev); -+ -+extern void iproc_platform_device_put(struct platform_device *pdev); -+extern int iproc_platform_device_add(struct platform_device *pdev); -+extern void iproc_platform_device_del(struct platform_device *pdev); -+extern int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); -+extern void iproc_sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp); -+ -+ -+extern struct class *iproc__class_create(struct module *owner, const char *name, -+ struct lock_class_key *key); -+extern void iproc_class_destroy(struct class *cls); -+extern int iproc_device_create_file(struct device *dev, -+ const struct device_attribute *attr); -+extern struct device *iproc_device_create(struct class *class, -+ struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); -+extern void iproc_device_destroy(struct class *class, dev_t devt); -+extern void iproc_device_remove_file(struct device *dev, -+ const struct device_attribute *attr); -+extern int iproc_platform_get_irq_byname(struct platform_device *, const char *); -+ -+extern int iproc_gpio_to_irq(unsigned gpio); -+#endif /*#ifndef __SHM_DOT_H_INCLUDED__*/ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/platsmp.c b/arch/arm/mach-iproc/platsmp.c ---- a/arch/arm/mach-iproc/platsmp.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/platsmp.c 2017-11-09 17:52:58.323963000 +0800 -@@ -0,0 +1,210 @@ -+/* -+ * Copyright (C) 2014-2015 Broadcom Corporation -+ * Copyright 2014 Linaro Limited -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation version 2. -+ * -+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any -+ * kind, whether express or implied; 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 -+ -+#include -+#include -+#include -+#include -+ -+/* Size of mapped Cortex A9 SCU address space */ -+#define CORTEX_A9_SCU_SIZE 0x58 -+ -+#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */ -+#define BOOT_ADDR_CPUID_MASK 0x3 -+ -+/* Name of device node property defining secondary boot register location */ -+#define OF_SECONDARY_BOOT "secondary-boot-reg" -+#define MPIDR_CPUID_BITMASK 0x3 -+ -+/* I/O address of register used to coordinate secondary core startup */ -+static u32 secondary_boot_addr; -+ -+/* -+ * Enable the Cortex A9 Snoop Control Unit -+ * -+ * By the time this is called we already know there are multiple -+ * cores present. We assume we're running on a Cortex A9 processor, -+ * so any trouble getting the base address register or getting the -+ * SCU base is a problem. -+ * -+ * Return 0 if successful or an error code otherwise. -+ */ -+static int __init scu_a9_enable(void) -+{ -+ unsigned long config_base; -+ void __iomem *scu_base; -+ -+ if (!scu_a9_has_base()) { -+ pr_err("no configuration base address register!\n"); -+ return -ENXIO; -+ } -+ -+ /* Config base address register value is zero for uniprocessor */ -+ config_base = scu_a9_get_base(); -+ if (!config_base) { -+ pr_err("hardware reports only one core\n"); -+ return -ENOENT; -+ } -+ -+ scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); -+ if (!scu_base) { -+ pr_err("failed to remap config base (%lu/%u) for SCU\n", -+ config_base, CORTEX_A9_SCU_SIZE); -+ return -ENOMEM; -+ } -+ -+ scu_enable(scu_base); -+ -+ iounmap(scu_base); /* That's the last we'll need of this */ -+ -+ return 0; -+} -+ -+static int nsp_write_lut(void) -+{ -+ void __iomem *sku_rom_lut; -+ phys_addr_t secondary_startup_phy; -+ -+ if (!secondary_boot_addr) { -+ pr_warn("required secondary boot register not specified\n"); -+ return -EINVAL; -+ } -+ -+ sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, -+ sizeof(secondary_boot_addr)); -+ if (!sku_rom_lut) { -+ pr_warn("unable to ioremap SKU-ROM LUT register\n"); -+ return -ENOMEM; -+ } -+ -+ secondary_startup_phy = virt_to_phys(secondary_startup); -+ BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX); -+ -+ writel_relaxed(secondary_startup_phy, sku_rom_lut); -+ -+ /* Ensure the write is visible to the secondary core */ -+ smp_wmb(); -+ -+ iounmap(sku_rom_lut); -+ -+ return 0; -+} -+ -+static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) -+{ -+ static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; -+ struct device_node *cpus_node = NULL; -+ struct device_node *cpu_node = NULL; -+ int ret; -+ -+ /* -+ * This function is only called via smp_ops->smp_prepare_cpu(). -+ * That only happens if a "/cpus" device tree node exists -+ * and has an "enable-method" property that selects the SMP -+ * operations defined herein. -+ */ -+ cpus_node = of_find_node_by_path("/cpus"); -+ if (!cpus_node) -+ return; -+ -+ for_each_child_of_node(cpus_node, cpu_node) { -+ u32 cpuid; -+ -+ if (of_node_cmp(cpu_node->type, "cpu")) -+ continue; -+ -+ if (of_property_read_u32(cpu_node, "reg", &cpuid)) { -+ pr_debug("%s: missing reg property\n", -+ cpu_node->full_name); -+ ret = -ENOENT; -+ goto out; -+ } -+ -+ /* -+ * "secondary-boot-reg" property should be defined only -+ * for secondary cpu -+ */ -+ if ((cpuid & MPIDR_CPUID_BITMASK) == 1) { -+ /* -+ * Our secondary enable method requires a -+ * "secondary-boot-reg" property to specify a register -+ * address used to request the ROM code boot a secondary -+ * core. If we have any trouble getting this we fall -+ * back to uniprocessor mode. -+ */ -+ if (of_property_read_u32(cpu_node, -+ OF_SECONDARY_BOOT, -+ &secondary_boot_addr)) { -+ pr_warn("%s: no" OF_SECONDARY_BOOT "property\n", -+ cpu_node->name); -+ ret = -ENOENT; -+ goto out; -+ } -+ } -+ } -+ -+ /* -+ * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is -+ * returned, the SoC reported a uniprocessor configuration. -+ * We bail on any other error. -+ */ -+ ret = scu_a9_enable(); -+out: -+ of_node_put(cpu_node); -+ of_node_put(cpus_node); -+ -+ if (ret) { -+ /* Update the CPU present map to reflect uniprocessor mode */ -+ pr_warn("disabling SMP\n"); -+ init_cpu_present(&only_cpu_0); -+ } -+} -+ -+static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ int ret; -+ -+ /* -+ * After wake up, secondary core branches to the startup -+ * address programmed at SKU ROM LUT location. -+ */ -+ ret = nsp_write_lut(); -+ if (ret) { -+ pr_err("unable to write startup addr to SKU ROM LUT\n"); -+ goto out; -+ } -+ -+ /* Send a CPU wakeup interrupt to the secondary core */ -+ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); -+ -+out: -+ return ret; -+} -+ -+/* Leverage NSP SMP code for HX4/KT2 */ -+static const struct smp_operations nsp_smp_ops __initconst = { -+ .smp_prepare_cpus = bcm_smp_prepare_cpus, -+ .smp_boot_secondary = nsp_boot_secondary, -+}; -+CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/arch/arm/mach-iproc/shm.c b/arch/arm/mach-iproc/shm.c ---- a/arch/arm/mach-iproc/shm.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/arch/arm/mach-iproc/shm.c 2017-11-09 17:52:58.324964000 +0800 -@@ -0,0 +1,309 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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/plat/shm.h" -+/** -+ * iproc_platform_get_irq - get an IRQ for a device -+ * wrapper function for platform_get_irq -+ * @dev: platform device -+ * @num: IRQ number index -+ */ -+int iproc_platform_get_irq(struct platform_device *dev, unsigned int num) -+{ -+ return platform_get_irq(dev, num); -+} -+EXPORT_SYMBOL(iproc_platform_get_irq); -+ -+ -+/** -+ * iproc_platform_get_resource_byname - -+ * wrapper function for platform_get_resource_byname -+ * @dev: platform device -+ * @type: resource type -+ * @name: resource name -+ */ -+struct resource * -+iproc_platform_get_resource_byname(struct platform_device *dev, -+ unsigned int type, -+ const char *name) -+{ -+ return platform_get_resource_byname(dev, type, name); -+} -+EXPORT_SYMBOL(iproc_platform_get_resource_byname); -+ -+ -+/** -+ * iproc_platform_get_resource - -+ * wrapper function for platform_get_resource -+ * @dev: platform device -+ * @type: resource type -+ * @num: resource index -+ */ -+struct resource * -+iproc_platform_get_resource(struct platform_device *dev, unsigned int type, -+ unsigned int num) -+{ -+ return platform_get_resource(dev, type, num); -+} -+EXPORT_SYMBOL(iproc_platform_get_resource); -+ -+ -+/** -+ * iproc_platform_driver_register - -+ * wrapper function for platform_driver_register -+ * @drv: platform driver structure -+ */ -+int iproc_platform_driver_register(struct platform_driver *drv) -+{ -+ return platform_driver_register(drv); -+} -+EXPORT_SYMBOL(iproc_platform_driver_register); -+ -+ -+/** -+ * iproc_platform_driver_unregister -+ * wrapper function for platform_driver_unregister -+ * @drv: platform driver structure -+ */ -+void iproc_platform_driver_unregister(struct platform_driver *drv) -+{ -+ return platform_driver_unregister(drv); -+} -+EXPORT_SYMBOL(iproc_platform_driver_unregister); -+ -+ -+/** -+ * iproc_platform_device_register - add a platform-level device -+ * wrapper function for platform_device_register -+ * @pdev: platform device we're adding -+ * -+ */ -+int iproc_platform_device_register(struct platform_device * pdev) -+{ -+ return platform_device_register(pdev); -+} -+EXPORT_SYMBOL(iproc_platform_device_register); -+ -+ -+/** -+ * iproc_platform_device_unregister - -+ * wrapper function for platform_device_unregister -+ * @pdev: platform device we're unregistering -+ */ -+void iproc_platform_device_unregister(struct platform_device * pdev) -+{ -+ return platform_device_unregister(pdev); -+} -+EXPORT_SYMBOL(iproc_platform_device_unregister); -+ -+ -+/** -+ * iproc_platform_device_alloc - -+ * wrapper function for platform_device_alloc -+ * @name: base name of the device we're adding -+ * @id: instance id -+ */ -+struct platform_device *iproc_platform_device_alloc(const char *name, int id) -+{ -+ return platform_device_alloc(name, id); -+} -+EXPORT_SYMBOL(iproc_platform_device_alloc); -+ -+/** -+ * iproc_platform_device_add - -+ * wrapper function for platform_device_add -+ * @pdev: platform device we're adding -+ */ -+int iproc_platform_device_add(struct platform_device *pdev) -+{ -+ return platform_device_add(pdev); -+} -+EXPORT_SYMBOL(iproc_platform_device_add); -+ -+/** -+ * iproc_platform_device_del - -+ * wrapper function for platform_device_del -+ * @pdev: platform device we're removing -+ */ -+void iproc_platform_device_del(struct platform_device *pdev) -+{ -+ platform_device_del(pdev); -+} -+EXPORT_SYMBOL(iproc_platform_device_del); -+ -+ -+/** -+ * iproc_platform_device_put - -+ * wrapper function for platform_device_put -+ * @pdev: platform device to free -+ */ -+void iproc_platform_device_put(struct platform_device *pdev) -+{ -+ platform_device_put(pdev); -+} -+EXPORT_SYMBOL(iproc_platform_device_put); -+ -+ -+/** -+ * iproc_platform_device_add_resources - -+ * wrapper function for platform_device_add_resources -+ * @pdev: platform device allocated by platform_device_alloc to add resources to -+ * @res: set of resources that needs to be allocated for the device -+ * @num: number of resources -+ */ -+int iproc_platform_device_add_resources(struct platform_device *pdev, -+ const struct resource *res, unsigned int num) -+{ -+ return platform_device_add_resources(pdev, res, num); -+} -+EXPORT_SYMBOL(iproc_platform_device_add_resources); -+ -+ -+/** -+ * iproc_platform_device_put - -+ * wrapper function for sysfs_create_group -+ * @kobj: The kobject to create the group on -+ * @grp: The attribute group to create -+ */ -+int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) -+{ -+ return sysfs_create_group(kobj, grp); -+} -+EXPORT_SYMBOL(iproc_sysfs_create_group); -+ -+ -+/** -+ * iproc_sysfs_remove_group - -+ * wrapper function for sysfs_remove_group -+ * @kobj: The kobject which the group is on -+ * @grp: The attribute group to remove -+ */ -+void iproc_sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) -+{ -+ sysfs_remove_group(kobj, grp); -+} -+EXPORT_SYMBOL(iproc_sysfs_remove_group); -+ -+/** -+ * iproc__class_create - -+ * wrapper function for __class_create -+ * @ower: pointer to the module that is to "own" this struct class -+ * @name: pointer to a string for the name of this class. -+ * @key: the lock_class_key for this class; used by mutex lock debugging -+ */ -+struct class *iproc__class_create(struct module *owner, const char *name, -+ struct lock_class_key *key) -+{ -+ return __class_create(owner, name, key); -+} -+EXPORT_SYMBOL(iproc__class_create); -+ -+/** -+ * iproc_class_destroy - -+ * wrapper function for class_destroy -+ * @cls: pointer to the struct class that is to be destroyed -+ */ -+void iproc_class_destroy(struct class *cls) -+{ -+ class_destroy(cls); -+} -+EXPORT_SYMBOL(iproc_class_destroy); -+ -+/** -+ * iproc_device_create_file - -+ * wrapper function for device_create_file -+ * @dev: device. -+ * @attr: device attribute descriptor. -+ */ -+int iproc_device_create_file(struct device *dev, -+ const struct device_attribute *attr) -+{ -+ return device_create_file(dev, attr); -+} -+EXPORT_SYMBOL(iproc_device_create_file); -+ -+/** -+ * iproc_device_create - -+ * wrapper function for device_create -+ * -+ * @class: pointer to the struct class that this device should be -+ * registered to -+ * @parent: pointer to the parent struct device of this new device, if any -+ * @devt: the dev_t for the char device to be added -+ * @drvdata: the data to be added to the device for callbacks -+ * @fmt: string for the device's name -+ */ -+struct device *iproc_device_create(struct class *class, -+ struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) -+{ -+ va_list args; -+ struct device *r; -+ -+ va_start(args, fmt); -+ r = device_create_vargs(class, parent, devt, drvdata, fmt, args); -+ va_end(args); -+ -+ return r; -+} -+EXPORT_SYMBOL(iproc_device_create); -+ -+/** -+ * iproc_device_destroy - -+ * wrapper function for device_destroy -+ * @class: pointer to the struct class that this device was registered with -+ * @devt: the dev_t of the device that was previously registered -+ */ -+void iproc_device_destroy(struct class *class, dev_t devt) -+{ -+ return device_destroy(class, devt); -+} -+EXPORT_SYMBOL(iproc_device_destroy); -+ -+/** -+ * proc_device_remove_file - -+ * wrapper function for device_remove_file -+ * @dev: device. -+ * @attr: device attribute descriptor. -+ */ -+void iproc_device_remove_file(struct device *dev, -+ const struct device_attribute *attr) -+{ -+ return device_remove_file(dev, attr); -+} -+EXPORT_SYMBOL(iproc_device_remove_file); -+ -+/** -+ * iproc_platform_get_irq_byname - -+ * wrapper function for platform_get_irq_byname -+ * @dev: platform device -+ * @name: IRQ name -+ */ -+int iproc_platform_get_irq_byname(struct platform_device *dev, const char *n) -+{ -+ return platform_get_irq_byname(dev,n); -+} -+EXPORT_SYMBOL(iproc_platform_get_irq_byname); -+ -+/** -+ * iproc_gpio_to_irq - -+ * wrapper function for gpio_to_irq -+ * @gpio: gpio whose IRQ will be returned (already requested) -+ */ -+int iproc_gpio_to_irq(unsigned gpio) -+{ -+ return gpio_to_irq(gpio); -+} -+EXPORT_SYMBOL(iproc_gpio_to_irq); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig ---- a/drivers/char/hw_random/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/char/hw_random/Kconfig 2017-11-09 17:53:25.197163000 +0800 -@@ -114,6 +114,18 @@ config HW_RANDOM_IPROC_RNG200 - - If unsure, say Y. - -+config HW_RANDOM_XGS_IPROC_RNG -+ tristate "Broadcom iProc RNG support" -+ depends on (ARCH_XGS_IPROC && HW_RANDOM) -+ ---help--- -+ This driver provides kernel-side support for the RNG -+ hardware found on the Broadcom iProc SoCs. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called iproc-rng -+ -+ If unsure, say Y. -+ - config HW_RANDOM_GEODE - tristate "AMD Geode HW Random Number Generator support" - depends on X86_32 && PCI -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile ---- a/drivers/char/hw_random/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/char/hw_random/Makefile 2017-11-09 17:53:25.198159000 +0800 -@@ -29,6 +29,7 @@ obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos - obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o - obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o - obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o -+obj-$(CONFIG_HW_RANDOM_XGS_IPROC_RNG) += xgs-iproc-rng200.o - obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o - obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o - obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/char/hw_random/xgs-iproc-rng200.c b/drivers/char/hw_random/xgs-iproc-rng200.c ---- a/drivers/char/hw_random/xgs-iproc-rng200.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/char/hw_random/xgs-iproc-rng200.c 2017-11-09 17:53:25.250157000 +0800 -@@ -0,0 +1,442 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+/* -+ * DESCRIPTION: The Broadcom iProc RNG200 Driver -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Registers for RNG */ -+#define RNG_CTRL_OFFSET 0x00000000 -+#define RNG_CTRL_RESERVED_MASK 0xF00000CC -+#define RNG_CTRL_COMBLK2_OSC_DIS_SHIFT 22 -+#define RNG_CTRL_COMBLK2_OSC_DIS_MASK 0x0FC00000 -+#define RNG_CTRL_COMBLK1_OSC_DIS_SHIFT 16 -+#define RNG_CTRL_COMBLK1_OSC_DIS_MASK 0x003F0000 -+#define RNG_CTRL_JCLK_BYP_DIV_CNT_SHIFT 8 -+#define RNG_CTRL_JCLK_BYP_DIV_CNT_MASK 0x0000FF00 -+#define RNG_CTRL_JCLK_BYP_SRC_SHIFT 5 -+#define RNG_CTRL_JCLK_BYP_SRC_MASK 0x00000020 -+#define RNG_CTRL_JCLK_BYP_SEL_SHIFT 4 -+#define RNG_CTRL_JCLK_BYP_SEL_MASK 0x00000010 -+#define RNG_CTRL_RBG2X_SHIFT 1 -+#define RNG_CTRL_RBG2X_MASK 0x00000002 -+#define RNG_CTRL_RBGEN_SHIFT 0 -+#define RNG_CTRL_RBGEN_MASK 0x00000001 -+ -+#define RNG_STATUS_OFFSET 0x00000004 -+#define RNG_STATUS_RESERVED_MASK 0x00F00000 -+#define RNG_STATUS_RND_VAL_SHIFT 24 -+#define RNG_STATUS_RND_VAL_MASK 0xFF000000 -+#define RNG_STATUS_WARM_CNT_SHIFT 0 -+#define RNG_STATUS_WARM_CNT_MASK 0x000FFFFF -+ -+#define RNG_DATA_OFFSET 0x00000008 -+#define RNG_DATA_RESERVED_MASK 0x00000000 -+#define RNG_DATA_RNG_NUM_SHIFT 0 -+#define RNG_DATA_RNG_NUM_MASK 0xFFFFFFFF -+ -+#define RNG_FF_THRES_OFFSET 0x0000000C -+#define RNG_FF_THRES_RESERVED_MASK 0xFFFFFFE0 -+#define RNG_FF_THRES_RNG_FF_THRESH_SHIFT 0 -+#define RNG_FF_THRES_RNG_FF_THRESH_MASK 0x0000001F -+ -+#define RNG_INT_MASK_OFFSET 0x00000010 -+#define RNG_INT_MASK_RESERVED_MASK 0xFFFFFFFE -+#define RNG_INT_MASK_OFF_SHIFT 0 -+#define RNG_INT_MASK_OFF_MASK 0x00000001 -+ -+/* Registers for RNG200*/ -+#define RNG200_CTRL_OFFSET 0x00 -+#define RNG200_CTRL_RBGEN_MASK 0x00001FFF -+#define RNG200_CTRL_RBGEN_ENABLE 0x00000001 -+#define RNG200_CTRL_RBGEN_DISABLE 0x00000000 -+ -+#define RNG200_SOFT_RESET_OFFSET 0x04 -+#define RNG200_SOFT_RESET_MASK 0x00000001 -+#define RNG200_SOFT_RESET_ACTIVE 0x00000001 -+#define RNG200_SOFT_RESET_CLEAR 0x00000000 -+ -+#define RBG_SOFT_RESET_OFFSET 0x08 -+#define RBG_RNG_SOFT_RESET_MASK 0x00000001 -+#define RBG_RNG_SOFT_RESET_ACTIVE 0x00000001 -+#define RBG_RNG_SOFT_RESET_CLEAR 0x00000000 -+ -+#define RNG200_INT_STATUS_OFFSET 0x18 -+#define RNG200_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000 -+#define RNG200_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK 0x00020000 -+#define RNG200_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020 -+#define RNG200_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK 0x00000001 -+ -+#define RNG200_FIFO_DATA_OFFSET 0x20 -+#define RNG200_FIFO_COUNT_OFFSET 0x24 -+#define RNG200_FIFO_COUNT_MASK 0x000000FF -+ -+static int rng_read(struct hwrng *rng, void *buf, size_t max, -+ bool wait) -+{ -+ u32 num_words = 0; -+ u32 num_remaining = max; -+ -+ #define MAX_IDLE_TIME (1 * HZ) -+ unsigned long idle_endtime = jiffies + MAX_IDLE_TIME; -+ -+ /* Retrieve HW RNG registers base address. */ -+ void __iomem *base_addr = (void __iomem *)rng->priv; -+ -+ while ((num_remaining > 0) && time_before(jiffies, idle_endtime)) { -+ /* Are there any random numbers available? */ -+ num_words = (ioread32(base_addr + RNG_STATUS_OFFSET) & -+ RNG_STATUS_RND_VAL_MASK) >> RNG_STATUS_RND_VAL_SHIFT; -+ if (num_words > 0) { -+ if (num_remaining >= sizeof(u32)) { -+ /* Buffer has room to store entire word */ -+ *(u32 *)buf = ioread32(base_addr + -+ RNG_DATA_OFFSET); -+ buf += sizeof(u32); -+ num_remaining -= sizeof(u32); -+ } else { -+ /* Buffer can only store partial word */ -+ u32 rnd_number = ioread32(base_addr + -+ RNG_DATA_OFFSET); -+ memcpy(buf, &rnd_number, num_remaining); -+ buf += num_remaining; -+ num_remaining = 0; -+ } -+ -+ /* Reset the IDLE timeout */ -+ idle_endtime = jiffies + MAX_IDLE_TIME; -+ } else if (!wait) { -+ /* Cannot wait, return immediately */ -+ break; -+ } else { -+ /* Can wait, give others chance to run */ -+ cpu_relax(); -+ } -+ } -+ -+ return max - num_remaining; -+} -+ -+static struct hwrng rng_ops = { -+ .name = "iproc-rng", -+ .read = rng_read, -+}; -+ -+static int rng_probe(struct platform_device *pdev) -+{ -+ int error; -+ u32 val; -+ struct device *dev = &pdev->dev; -+ void __iomem *base_addr; -+ struct device_node *node; -+ -+ pr_info("Broadcom IPROC RNG Driver\n"); -+ /* We only accept one device, and it must have an id of -1 */ -+ if (pdev->id != -1) -+ return -ENODEV; -+ -+ node = pdev->dev.of_node; -+ base_addr = of_iomap(node, 0); -+ if (!base_addr) { -+ dev_err(&pdev->dev, "can't iomap base_addr for rng\n"); -+ return -EIO; -+ } -+ rng_ops.priv = (unsigned long)base_addr; -+ -+ /* Start RNG block */ -+ val = ioread32(base_addr + RNG_CTRL_OFFSET); -+ val |= RNG_CTRL_RBGEN_MASK; -+ iowrite32(val, base_addr + RNG_CTRL_OFFSET); -+ -+ /* Enable RNG RBG2X */ -+ val = ioread32(base_addr + RNG_CTRL_OFFSET); -+ val |= RNG_CTRL_RBG2X_MASK; -+ iowrite32(val, base_addr + RNG_CTRL_OFFSET); -+ -+ /* Disable RNG INTERRUPT */ -+ val = ioread32(base_addr + RNG_INT_MASK_OFFSET); -+ val |= RNG_INT_MASK_OFF_MASK; -+ iowrite32(val, base_addr + RNG_INT_MASK_OFFSET); -+ -+ /* set warmup cycle 0xfff */ -+ iowrite32(RNG_STATUS_WARM_CNT_MASK - -+ (0xfff & RNG_STATUS_WARM_CNT_MASK), -+ base_addr + RNG_STATUS_OFFSET); -+ while ((ioread32(base_addr + RNG_STATUS_OFFSET) & -+ RNG_STATUS_WARM_CNT_MASK) != RNG_STATUS_WARM_CNT_MASK) -+ cpu_relax(); -+ -+ /* register to the Linux RNG framework */ -+ error = hwrng_register(&rng_ops); -+ if (error) { -+ dev_err(dev, "hwrng registration failed\n"); -+ iounmap(base_addr); -+ return error; -+ } -+ dev_dbg(dev, "hwrng registered\n"); -+ -+ return 0; -+} -+ -+static int rng_remove(struct platform_device *pdev) -+{ -+ u32 val; -+ void __iomem *base_addr = (void __iomem *)rng_ops.priv; -+ /* Unregister driver */ -+ hwrng_unregister(&rng_ops); -+ -+ if (base_addr) { -+ /* Disable RNG hardware */ -+ val = ioread32(base_addr + RNG_CTRL_OFFSET); -+ val &= ~RNG_CTRL_RBGEN_MASK; -+ iowrite32(val, base_addr + RNG_CTRL_OFFSET); -+ -+ val = ioread32(base_addr + RNG_CTRL_OFFSET); -+ val &= ~RNG_CTRL_RBG2X_MASK; -+ iowrite32(val, base_addr + RNG_CTRL_OFFSET); -+ -+ iounmap(base_addr); -+ } -+ -+ return 0; -+} -+ -+static void iproc_rng200_restart(void __iomem *rng_base) -+{ -+ u32 val; -+ -+ /* Disable RBG */ -+ val = ioread32(rng_base + RNG200_CTRL_OFFSET); -+ val &= ~RNG200_CTRL_RBGEN_MASK; -+ val |= RNG200_CTRL_RBGEN_DISABLE; -+ iowrite32(val, rng_base + RNG200_CTRL_OFFSET); -+ -+ /* Clear all interrupt status */ -+ iowrite32(0xFFFFFFFFUL, rng_base + RNG200_INT_STATUS_OFFSET); -+ -+ /* Reset RNG and RBG */ -+ val = ioread32(rng_base + RBG_SOFT_RESET_OFFSET); -+ val &= ~RBG_RNG_SOFT_RESET_MASK; -+ val |= RBG_RNG_SOFT_RESET_ACTIVE; -+ iowrite32(val, rng_base + RBG_SOFT_RESET_OFFSET); -+ -+ val = ioread32(rng_base + RNG200_SOFT_RESET_OFFSET); -+ val &= ~RNG200_SOFT_RESET_MASK; -+ val |= RNG200_SOFT_RESET_ACTIVE; -+ iowrite32(val, rng_base + RNG200_SOFT_RESET_OFFSET); -+ -+ val = ioread32(rng_base + RNG200_SOFT_RESET_OFFSET); -+ val &= ~RNG200_SOFT_RESET_MASK; -+ val |= RNG200_SOFT_RESET_CLEAR; -+ iowrite32(val, rng_base + RNG200_SOFT_RESET_OFFSET); -+ -+ val = ioread32(rng_base + RBG_SOFT_RESET_OFFSET); -+ val &= ~RBG_RNG_SOFT_RESET_MASK; -+ val |= RBG_RNG_SOFT_RESET_CLEAR; -+ iowrite32(val, rng_base + RBG_SOFT_RESET_OFFSET); -+ -+ /* Enable RBG */ -+ val = ioread32(rng_base + RNG200_CTRL_OFFSET); -+ val &= ~RNG200_CTRL_RBGEN_MASK; -+ val |= RNG200_CTRL_RBGEN_ENABLE; -+ iowrite32(val, rng_base + RNG200_CTRL_OFFSET); -+} -+ -+static int iproc_rng200_read(struct hwrng *rng, void *buf, size_t max, -+ bool wait) -+{ -+ u32 status; -+ u32 rng_fifo; -+ u32 num_remaining = max; -+ -+ #define MAX_RESETS_PER_READ 1 -+ u32 num_resets = 0; -+ -+ #define MAX_IDLE_TIME (1 * HZ) -+ unsigned long idle_endtime = jiffies + MAX_IDLE_TIME; -+ -+ /* Retrieve HW RNG registers base address. */ -+ void __iomem *rng_base = (void __iomem *)rng->priv; -+ -+ while ((num_remaining > 0) && time_before(jiffies, idle_endtime)) { -+ -+ /* Is RNG sane? If not, reset it. */ -+ status = ioread32(rng_base + RNG200_INT_STATUS_OFFSET); -+ if ((status & (RNG200_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK | -+ RNG200_INT_STATUS_NIST_FAIL_IRQ_MASK)) != 0) { -+ -+ if (num_resets >= MAX_RESETS_PER_READ) -+ return max - num_remaining; -+ -+ iproc_rng200_restart(rng_base); -+ num_resets++; -+ } -+ -+ /* Are there any random numbers available? */ -+ rng_fifo = ioread32(rng_base + RNG200_FIFO_COUNT_OFFSET); -+ if ((rng_fifo & RNG200_FIFO_COUNT_MASK) > 0) { -+ -+ if (num_remaining >= sizeof(u32)) { -+ /* Buffer has room to store entire word */ -+ *(u32 *)buf = ioread32(rng_base + -+ RNG200_FIFO_DATA_OFFSET); -+ buf += sizeof(u32); -+ num_remaining -= sizeof(u32); -+ } else { -+ /* Buffer can only store partial word */ -+ u32 rnd_number = ioread32(rng_base + -+ RNG200_FIFO_DATA_OFFSET); -+ memcpy(buf, &rnd_number, num_remaining); -+ buf += num_remaining; -+ num_remaining = 0; -+ } -+ -+ /* Reset the IDLE timeout */ -+ idle_endtime = jiffies + MAX_IDLE_TIME; -+ } else { -+ if (!wait) -+ /* Cannot wait, return immediately */ -+ break; -+ -+ /* Can wait, give others chance to run */ -+ cpu_relax(); -+ } -+ } -+ -+ return max - num_remaining; -+} -+ -+static struct hwrng iproc_rng200_ops = { -+ .name = "iproc-rng200", -+ .read = iproc_rng200_read, -+}; -+ -+static int iproc_rng200_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ void __iomem *rng_base; -+ struct resource *res; -+ u32 val; -+ int err; -+ -+ pr_info("Broadcom IPROC RNG200 Driver\n"); -+ /* Map peripheral */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(dev, "failed to get rng resources"); -+ return -ENODEV; -+ } -+ -+ rng_base = devm_ioremap_resource(dev, res); -+ //rng_base = ioremap(res->start, res->end - res->start); -+ if (!rng_base) { -+ dev_err(dev, "failed to remap rng regs"); -+ return -ENODEV; -+ } -+ -+ iproc_rng200_ops.priv = (unsigned long)rng_base; -+ -+ /* Setup RNG. */ -+ val = ioread32(rng_base + RNG200_CTRL_OFFSET); -+ val &= ~RNG200_CTRL_RBGEN_MASK; -+ val |= RNG200_CTRL_RBGEN_ENABLE; -+ iowrite32(val, rng_base + RNG200_CTRL_OFFSET); -+ -+ /* Register driver */ -+ err = hwrng_register(&iproc_rng200_ops); -+ if (err) { -+ dev_err(dev, "hwrng registration failed\n"); -+ return err; -+ } -+ dev_dbg(dev, "hwrng registered\n"); -+ -+ return 0; -+} -+ -+static int iproc_rng200_remove(struct platform_device *pdev) -+{ -+ u32 val; -+ void __iomem *rng_base = (void __iomem *)iproc_rng200_ops.priv; -+ -+ /* Unregister driver */ -+ hwrng_unregister(&iproc_rng200_ops); -+ if (rng_base) { -+ /* Disable RNG hardware */ -+ val = ioread32(rng_base + RNG200_CTRL_OFFSET); -+ val &= ~RNG200_CTRL_RBGEN_MASK; -+ val |= RNG200_CTRL_RBGEN_DISABLE; -+ iowrite32(val, rng_base + RNG200_CTRL_OFFSET); -+ } -+ return 0; -+} -+static int rng_probe_gen(struct platform_device *pdev) -+{ -+ int ret = -ENODEV; -+ struct device_node *node; -+ const char *rng_name; -+ node = pdev->dev.of_node; -+ rng_name = node->name; -+ -+ if (!of_device_is_available(node)) -+ return -ENODEV; -+ -+ of_property_read_string(node, "rng-type", &rng_name); -+ if (strcmp(rng_name, "rng200") == 0) -+ ret = iproc_rng200_probe(pdev); -+ else if (strcmp(rng_name, "rng") == 0) -+ ret = rng_probe(pdev); -+ -+ return ret; -+} -+ -+static int rng_remove_gen(struct platform_device *pdev) -+{ -+ int ret = -ENODEV; -+ struct device_node *node; -+ const char *rng_name; -+ node = pdev->dev.of_node; -+ rng_name = node->name; -+ -+ if (!of_device_is_available(node)) -+ return -ENODEV; -+ -+ of_property_read_string(node, "rng-type", &rng_name); -+ if (strcmp(rng_name, "rng200") == 0) -+ ret = iproc_rng200_remove(pdev); -+ else if (strcmp(rng_name, "rng") == 0) -+ ret = rng_remove(pdev); -+ -+ return ret; -+} -+ -+static const struct of_device_id bcm_iproc_dt_ids[] = { -+ { .compatible = "brcm,iproc-rng"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_dt_ids); -+ -+static struct platform_driver iproc_rng_driver = { -+ .driver = { -+ .name = "iproc-rng", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(bcm_iproc_dt_ids), -+ }, -+ .probe = rng_probe_gen, -+ .remove = rng_remove_gen, -+}; -+module_platform_driver(iproc_rng_driver); -+ -+MODULE_AUTHOR("Broadcom"); -+MODULE_DESCRIPTION("iProc RNG/RNG200 Random Number Generator driver"); -+MODULE_LICENSE("GPL v2"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig ---- a/drivers/clk/bcm/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/clk/bcm/Kconfig 2017-11-09 17:53:25.478158000 +0800 -@@ -14,3 +14,15 @@ config COMMON_CLK_IPROC - help - Enable common clock framework support for Broadcom SoCs - based on the iProc architecture -+ -+config CLK_XGS_IPROC -+ bool "BRCM XGS iProc clock support" -+ depends on COMMON_CLK && ARCH_XGS_IPROC -+ select COMMON_CLK_IPROC -+ default ARCH_XGS_IPROC -+ help -+ Enable XGS iProc clock -+ -+ -+ -+ -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile ---- a/drivers/clk/bcm/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/clk/bcm/Makefile 2017-11-09 17:53:25.479153000 +0800 -@@ -8,3 +8,4 @@ obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns - obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o - obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o - obj-$(CONFIG_ARCH_BCM_5301X) += clk-nsp.o -+obj-$(CONFIG_CLK_XGS_IPROC) += clk-xgs-iproc.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/clk-iproc-armpll.c b/drivers/clk/bcm/clk-iproc-armpll.c ---- a/drivers/clk/bcm/clk-iproc-armpll.c 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/clk/bcm/clk-iproc-armpll.c 2017-11-09 17:53:25.494157000 +0800 -@@ -224,8 +224,10 @@ static unsigned long iproc_arm_pll_recal - pll->rate = 0; - return 0; - } -+ -+ /* To avoid pll->rate overflow, do divide before multiply */ -+ parent_rate = (parent_rate / pdiv) / mdiv; - pll->rate = (ndiv * parent_rate) >> 20; -- pll->rate = (pll->rate / pdiv) / mdiv; - - pr_debug("%s: ARM PLL rate: %lu. parent rate: %lu\n", __func__, - pll->rate, parent_rate); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/clk/bcm/clk-xgs-iproc.c b/drivers/clk/bcm/clk-xgs-iproc.c ---- a/drivers/clk/bcm/clk-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/clk/bcm/clk-xgs-iproc.c 2017-11-09 17:53:25.512166000 +0800 -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (C) 2014 Broadcom 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 version 2. -+ * -+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any -+ * kind, whether express or implied; 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 "clk-iproc.h" -+ -+#define SB2_GEN_PLL_CTRL_1_OFFSET 0x04 -+#define SB2_GEN_PLL_CTRL_3_OFFSET 0x0C -+#define SB2_GEN_PLL_CTRL_5_OFFSET 0x14 -+#define SB2_GEN_PLL_CTRL_1_PDIV_R 27 -+#define SB2_GEN_PLL_CTRL_3_NDIV_INT_R 20 -+#define SB2_GEN_PLL_CTRL_5_CH1_MDIV_R 8 -+#define SB2_GEN_PLL_CTRL_1_PDIV_WIDTH 4 -+#define SB2_GEN_PLL_CTRL_3_NDIV_INT_WIDTH 10 -+#define SB2_GEN_PLL_CTRL_5_CH1_MDIV_WIDTH 8 -+ -+#define GEN_PLL_CTRL1_OFFSET 0x4 -+#define GEN_PLL_CTRL2_OFFSET 0x8 -+#define GEN_PLL_CTRL1_NDIV_INT_R 0 -+#define GEN_PLL_CTRL1_NDIV_INT_WIDTH 10 -+#define GEN_PLL_CTRL1_PDIV_R 10 -+#define GEN_PLL_CTRL2_CH3_MDIV_R 8 -+#define GEN_PLL_CTRL2_CH3_MDIV_WIDTH 8 -+#define GEN_PLL_CTRL1_PDIV_WIDTH_3 3 -+#define GEN_PLL_CTRL1_PDIV_WIDTH_4 4 -+ -+ -+struct iproc_gen_pll { -+ struct clk_hw hw; -+ void __iomem *base; -+ unsigned long rate; -+}; -+ -+#define to_iproc_gen_pll(phw) container_of(phw, struct iproc_gen_pll, hw) -+ -+static u32 genpll_pdiv_width; -+ -+static unsigned long iproc_axi_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ uint32_t ndiv, mdiv, pdiv; -+ struct iproc_gen_pll *pll = to_iproc_gen_pll(hw); -+ -+ -+ ndiv = readl(pll->base + GEN_PLL_CTRL1_OFFSET) >> -+ GEN_PLL_CTRL1_NDIV_INT_R; -+ ndiv &= (1 << GEN_PLL_CTRL1_NDIV_INT_WIDTH) - 1; -+ if (ndiv == 0) -+ ndiv = 1 << GEN_PLL_CTRL1_NDIV_INT_WIDTH; -+ -+ pdiv = readl(pll->base + GEN_PLL_CTRL1_OFFSET) >> GEN_PLL_CTRL1_PDIV_R; -+ pdiv &= (1 << genpll_pdiv_width) -1; -+ if (pdiv == 0) -+ pdiv = 1 << genpll_pdiv_width; -+ -+ mdiv = readl(pll->base + GEN_PLL_CTRL2_OFFSET) >> -+ GEN_PLL_CTRL2_CH3_MDIV_R; -+ mdiv &= (1 << GEN_PLL_CTRL2_CH3_MDIV_WIDTH) - 1; -+ if (mdiv == 0) -+ mdiv = 1 << GEN_PLL_CTRL2_CH3_MDIV_WIDTH; -+ -+ pll->rate = parent_rate * ndiv / pdiv / mdiv; -+ return pll->rate; -+} -+ -+static unsigned long iproc_sb2_axi_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ uint32_t ndiv, mdiv, pdiv; -+ struct iproc_gen_pll *pll = to_iproc_gen_pll(hw); -+ -+ ndiv = readl(pll->base + SB2_GEN_PLL_CTRL_3_OFFSET) >> -+ SB2_GEN_PLL_CTRL_3_NDIV_INT_R; -+ ndiv &= (1 << SB2_GEN_PLL_CTRL_3_NDIV_INT_WIDTH) - 1; -+ -+ mdiv = readl(pll->base + SB2_GEN_PLL_CTRL_5_OFFSET) >> -+ SB2_GEN_PLL_CTRL_5_CH1_MDIV_R; -+ mdiv &= (1 << SB2_GEN_PLL_CTRL_5_CH1_MDIV_WIDTH) - 1; -+ -+ pdiv = readl(pll->base + SB2_GEN_PLL_CTRL_1_OFFSET) >> -+ SB2_GEN_PLL_CTRL_1_PDIV_R; -+ pdiv &= (1 << SB2_GEN_PLL_CTRL_1_PDIV_WIDTH) - 1; -+ -+ pll->rate = parent_rate * ndiv / pdiv / mdiv; -+ return pll->rate; -+} -+ -+ -+static struct clk_ops iproc_axi_clk_ops = { -+ .recalc_rate = iproc_axi_clk_recalc_rate, -+}; -+ -+void __init xgs_iproc_axi_clk_setup(struct device_node *node) -+{ -+ int ret; -+ struct clk *clk; -+ struct iproc_gen_pll *pll; -+ struct clk_init_data init; -+ const char *parent_name; -+ -+ pll = kzalloc(sizeof(*pll), GFP_KERNEL); -+ if (WARN_ON(!pll)) -+ return; -+ -+ pll->base = of_iomap(node, 0); -+ if (WARN_ON(!pll->base)) -+ goto err_free_pll; -+ -+ init.name = node->name; -+ if ( of_device_is_compatible(node, "axi-clk-sb2") ) -+ iproc_axi_clk_ops.recalc_rate = iproc_sb2_axi_clk_recalc_rate; -+ if ( of_device_is_compatible(node, "axi-clk-hx4") || -+ of_device_is_compatible(node, "axi-clk-hr2") ) -+ genpll_pdiv_width = GEN_PLL_CTRL1_PDIV_WIDTH_3; -+ else -+ genpll_pdiv_width = GEN_PLL_CTRL1_PDIV_WIDTH_4; -+ -+ init.ops = &iproc_axi_clk_ops; -+ init.flags = 0; -+ parent_name = of_clk_get_parent_name(node, 0); -+ init.parent_names = (parent_name ? &parent_name : NULL); -+ init.num_parents = (parent_name ? 1 : 0); -+ pll->hw.init = &init; -+ -+ clk = clk_register(NULL, &pll->hw); -+ if (WARN_ON(IS_ERR(clk))) -+ goto err_iounmap; -+ -+ ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); -+ if (WARN_ON(ret)) -+ goto err_clk_unregister; -+ -+ return; -+ -+err_clk_unregister: -+ clk_unregister(clk); -+err_iounmap: -+ iounmap(pll->base); -+err_free_pll: -+ kfree(pll); -+} -+ -+CLK_OF_DECLARE(xgs_iproc_axi_clk, "brcm,xgs-iproc-axi-clk", -+ xgs_iproc_axi_clk_setup); -+ -+ -+static void __init xgs_iproc_armpll_init(struct device_node *node) -+{ -+ iproc_armpll_setup(node); -+} -+CLK_OF_DECLARE(xgs_iproc_armpll, "brcm,xgs-iproc-armpll", -+ xgs_iproc_armpll_init); -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/dma/Kconfig b/drivers/dma/Kconfig ---- a/drivers/dma/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/dma/Kconfig 2017-11-09 17:53:27.047177000 +0800 -@@ -397,6 +397,14 @@ config PL330_DMA - You need to provide platform specific settings via - platform_data for a dma-pl330 device. - -+config XGS_IPROC_DMA330_DMA -+ tristate "DMA API Driver for XGS IPROC DMA330" -+ select DMA_ENGINE -+ depends on ARM_AMBA -+ help -+ Support the DMA engine for BRCM IPROC CoreLink -+ DMA Controller (DMA-330). -+ - config PXA_DMA - bool "PXA DMA support" - depends on (ARCH_MMP || ARCH_PXA) -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/dma/Makefile b/drivers/dma/Makefile ---- a/drivers/dma/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/dma/Makefile 2017-11-09 17:53:27.048171000 +0800 -@@ -50,6 +50,7 @@ obj-$(CONFIG_MX3_IPU) += ipu/ - obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o - obj-$(CONFIG_PCH_DMA) += pch_dma.o - obj-$(CONFIG_PL330_DMA) += pl330.o -+obj-$(CONFIG_XGS_IPROC_DMA330_DMA) += iproc-dma330.o - obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ - obj-$(CONFIG_PXA_DMA) += pxa_dma.o - obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/dma/iproc-dma330.c b/drivers/dma/iproc-dma330.c ---- a/drivers/dma/iproc-dma330.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/dma/iproc-dma330.c 2017-11-09 17:53:27.192174000 +0800 -@@ -0,0 +1,3067 @@ -+/* -+ * BRCM IPROC DMA330 support -+ * -+ * This driver, modified from pl330.c, supports CoreLink DMA Controller -+ * (DMA-330). -+ * -+ * Copyright (C) 2016 Broadcom Corporation -+ * -+ * Copyright (C) 2010 Samsung Electronics Co. Ltd. -+ * Jaswinder Singh -+ * -+ * This program is free software; you can 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 "dmaengine.h" -+#define DMA330_MAX_CHAN 8 -+#define DMA330_MAX_IRQS 32 -+#define DMA330_MAX_PERI 32 -+ -+struct dma_dma330_platdata { -+ u8 nr_valid_peri; -+ u8 *peri_id; -+ dma_cap_mask_t cap_mask; -+ unsigned mcbuf_sz; -+}; -+ -+enum dma330_cachectrl { -+ CCTRL0, /* Noncacheable and nonbufferable */ -+ CCTRL1, /* Bufferable only */ -+ CCTRL2, /* Cacheable, but do not allocate */ -+ CCTRL3, /* Cacheable and bufferable, but do not allocate */ -+ INVALID1, /* AWCACHE = 0x1000 */ -+ INVALID2, -+ CCTRL6, /* Cacheable write-through, allocate on writes only */ -+ CCTRL7, /* Cacheable write-back, allocate on writes only */ -+}; -+ -+enum dma330_byteswap { -+ SWAP_NO, -+ SWAP_2, -+ SWAP_4, -+ SWAP_8, -+ SWAP_16, -+}; -+ -+/* Register and Bit field Definitions */ -+#define DS 0x0 -+#define DS_ST_STOP 0x0 -+#define DS_ST_EXEC 0x1 -+#define DS_ST_CMISS 0x2 -+#define DS_ST_UPDTPC 0x3 -+#define DS_ST_WFE 0x4 -+#define DS_ST_ATBRR 0x5 -+#define DS_ST_QBUSY 0x6 -+#define DS_ST_WFP 0x7 -+#define DS_ST_KILL 0x8 -+#define DS_ST_CMPLT 0x9 -+#define DS_ST_FLTCMP 0xe -+#define DS_ST_FAULT 0xf -+ -+#define DPC 0x4 -+#define INTEN 0x20 -+#define ES 0x24 -+#define INTSTATUS 0x28 -+#define INTCLR 0x2c -+#define FSM 0x30 -+#define FSC 0x34 -+#define FTM 0x38 -+ -+#define _FTC 0x40 -+#define FTC(n) (_FTC + (n)*0x4) -+ -+#define _CS 0x100 -+#define CS(n) (_CS + (n)*0x8) -+#define CS_CNS (1 << 21) -+ -+#define _CPC 0x104 -+#define CPC(n) (_CPC + (n)*0x8) -+ -+#define _SA 0x400 -+#define SA(n) (_SA + (n)*0x20) -+ -+#define _DA 0x404 -+#define DA(n) (_DA + (n)*0x20) -+ -+#define _CC 0x408 -+#define CC(n) (_CC + (n)*0x20) -+ -+#define CC_SRCINC (1 << 0) -+#define CC_DSTINC (1 << 14) -+#define CC_SRCPRI (1 << 8) -+#define CC_DSTPRI (1 << 22) -+#define CC_SRCNS (1 << 9) -+#define CC_DSTNS (1 << 23) -+#define CC_SRCIA (1 << 10) -+#define CC_DSTIA (1 << 24) -+#define CC_SRCBRSTLEN_SHFT 4 -+#define CC_DSTBRSTLEN_SHFT 18 -+#define CC_SRCBRSTSIZE_SHFT 1 -+#define CC_DSTBRSTSIZE_SHFT 15 -+#define CC_SRCCCTRL_SHFT 11 -+#define CC_SRCCCTRL_MASK 0x7 -+#define CC_DSTCCTRL_SHFT 25 -+#define CC_DRCCCTRL_MASK 0x7 -+#define CC_SWAP_SHFT 28 -+ -+#define _LC0 0x40c -+#define LC0(n) (_LC0 + (n)*0x20) -+ -+#define _LC1 0x410 -+#define LC1(n) (_LC1 + (n)*0x20) -+ -+#define DBGSTATUS 0xd00 -+#define DBG_BUSY (1 << 0) -+ -+#define DBGCMD 0xd04 -+#define DBGINST0 0xd08 -+#define DBGINST1 0xd0c -+ -+#define CR0 0xe00 -+#define CR1 0xe04 -+#define CR2 0xe08 -+#define CR3 0xe0c -+#define CR4 0xe10 -+#define CRD 0xe14 -+ -+#define PERIPH_ID 0xfe0 -+#define PERIPH_REV_SHIFT 20 -+#define PERIPH_REV_MASK 0xf -+#define PERIPH_REV_R0P0 0 -+#define PERIPH_REV_R1P0 1 -+#define PERIPH_REV_R1P1 2 -+ -+#define CR0_PERIPH_REQ_SET (1 << 0) -+#define CR0_BOOT_EN_SET (1 << 1) -+#define CR0_BOOT_MAN_NS (1 << 2) -+#define CR0_NUM_CHANS_SHIFT 4 -+#define CR0_NUM_CHANS_MASK 0x7 -+#define CR0_NUM_PERIPH_SHIFT 12 -+#define CR0_NUM_PERIPH_MASK 0x1f -+#define CR0_NUM_EVENTS_SHIFT 17 -+#define CR0_NUM_EVENTS_MASK 0x1f -+ -+#define CR1_ICACHE_LEN_SHIFT 0 -+#define CR1_ICACHE_LEN_MASK 0x7 -+#define CR1_NUM_ICACHELINES_SHIFT 4 -+#define CR1_NUM_ICACHELINES_MASK 0xf -+ -+#define CRD_DATA_WIDTH_SHIFT 0 -+#define CRD_DATA_WIDTH_MASK 0x7 -+#define CRD_WR_CAP_SHIFT 4 -+#define CRD_WR_CAP_MASK 0x7 -+#define CRD_WR_Q_DEP_SHIFT 8 -+#define CRD_WR_Q_DEP_MASK 0xf -+#define CRD_RD_CAP_SHIFT 12 -+#define CRD_RD_CAP_MASK 0x7 -+#define CRD_RD_Q_DEP_SHIFT 16 -+#define CRD_RD_Q_DEP_MASK 0xf -+#define CRD_DATA_BUFF_SHIFT 20 -+#define CRD_DATA_BUFF_MASK 0x3ff -+ -+#define PART 0x330 -+#define DESIGNER 0x41 -+#define REVISION 0x2 -+#define INTEG_CFG 0x0 -+#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12) | (REVISION << 20)) -+ -+#define DMA330_STATE_STOPPED (1 << 0) -+#define DMA330_STATE_EXECUTING (1 << 1) -+#define DMA330_STATE_WFE (1 << 2) -+#define DMA330_STATE_FAULTING (1 << 3) -+#define DMA330_STATE_COMPLETING (1 << 4) -+#define DMA330_STATE_WFP (1 << 5) -+#define DMA330_STATE_KILLING (1 << 6) -+#define DMA330_STATE_FAULT_COMPLETING (1 << 7) -+#define DMA330_STATE_CACHEMISS (1 << 8) -+#define DMA330_STATE_UPDTPC (1 << 9) -+#define DMA330_STATE_ATBARRIER (1 << 10) -+#define DMA330_STATE_QUEUEBUSY (1 << 11) -+#define DMA330_STATE_INVALID (1 << 15) -+ -+#define DMA330_STABLE_STATES (DMA330_STATE_STOPPED | DMA330_STATE_EXECUTING \ -+ | DMA330_STATE_WFE | DMA330_STATE_FAULTING) -+ -+#define CMD_DMAADDH 0x54 -+#define CMD_DMAEND 0x00 -+#define CMD_DMAFLUSHP 0x35 -+#define CMD_DMAGO 0xa0 -+#define CMD_DMALD 0x04 -+#define CMD_DMALDP 0x25 -+#define CMD_DMALP 0x20 -+#define CMD_DMALPEND 0x28 -+#define CMD_DMAKILL 0x01 -+#define CMD_DMAMOV 0xbc -+#define CMD_DMANOP 0x18 -+#define CMD_DMARMB 0x12 -+#define CMD_DMASEV 0x34 -+#define CMD_DMAST 0x08 -+#define CMD_DMASTP 0x29 -+#define CMD_DMASTZ 0x0c -+#define CMD_DMAWFE 0x36 -+#define CMD_DMAWFP 0x30 -+#define CMD_DMAWMB 0x13 -+ -+#define SZ_DMAADDH 3 -+#define SZ_DMAEND 1 -+#define SZ_DMAFLUSHP 2 -+#define SZ_DMALD 1 -+#define SZ_DMALDP 2 -+#define SZ_DMALP 2 -+#define SZ_DMALPEND 2 -+#define SZ_DMAKILL 1 -+#define SZ_DMAMOV 6 -+#define SZ_DMANOP 1 -+#define SZ_DMARMB 1 -+#define SZ_DMASEV 2 -+#define SZ_DMAST 1 -+#define SZ_DMASTP 2 -+#define SZ_DMASTZ 1 -+#define SZ_DMAWFE 2 -+#define SZ_DMAWFP 2 -+#define SZ_DMAWMB 1 -+#define SZ_DMAGO 6 -+ -+#define BRST_LEN(ccr) ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1) -+#define BRST_SIZE(ccr) (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7)) -+ -+#define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr)) -+#define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr)) -+ -+/* -+ * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req -+ * at 1byte/burst for P<->M and M<->M respectively. -+ * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req -+ * should be enough for P<->M and M<->M respectively. -+ */ -+#define MCODE_BUFF_PER_REQ 256 -+ -+/* Use this _only_ to wait on transient states */ -+#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax(); -+ -+#ifdef DMA330_DEBUG_MCGEN -+static unsigned cmd_line; -+#define DMA330_DBGCMD_DUMP(off, x...) do { \ -+ printk("%x:", cmd_line); \ -+ printk(x); \ -+ cmd_line += off; \ -+ } while (0) -+#define DMA330_DBGMC_START(addr) (cmd_line = addr) -+#else -+#define DMA330_DBGCMD_DUMP(off, x...) do {} while (0) -+#define DMA330_DBGMC_START(addr) do {} while (0) -+#endif -+ -+/* The number of default descriptors */ -+ -+#define NR_DEFAULT_DESC 16 -+ -+/* Delay for runtime PM autosuspend, ms */ -+#define DMA330_AUTOSUSPEND_DELAY 20 -+ -+/* Populated by the DMA330 core driver for DMA API driver's info */ -+struct dma330_config { -+ u32 periph_id; -+#define DMAC_MODE_NS (1 << 0) -+ unsigned int mode; -+ unsigned int data_bus_width:10; /* In number of bits */ -+ unsigned int data_buf_dep:11; -+ unsigned int num_chan:4; -+ unsigned int num_peri:6; -+ u32 peri_ns; -+ unsigned int num_events:6; -+ u32 irq_ns; -+}; -+ -+/** -+ * Request Configuration. -+ * The DMA330 core does not modify this and uses the last -+ * working configuration if the request doesn't provide any. -+ * -+ * The Client may want to provide this info only for the -+ * first request and a request with new settings. -+ */ -+struct dma330_reqcfg { -+ /* Address Incrementing */ -+ unsigned dst_inc:1; -+ unsigned src_inc:1; -+ -+ /* -+ * For now, the SRC & DST protection levels -+ * and burst size/length are assumed same. -+ */ -+ bool nonsecure; -+ bool privileged; -+ bool insnaccess; -+ unsigned brst_len:5; -+ unsigned brst_size:3; /* in power of 2 */ -+ -+ enum dma330_cachectrl dcctl; -+ enum dma330_cachectrl scctl; -+ enum dma330_byteswap swap; -+ struct dma330_config *pcfg; -+}; -+ -+/* -+ * One cycle of DMAC operation. -+ * There may be more than one xfer in a request. -+ */ -+struct dma330_xfer { -+ u32 src_addr; -+ u32 dst_addr; -+ /* Size to xfer */ -+ u32 bytes; -+}; -+ -+/* The xfer callbacks are made with one of these arguments. */ -+enum dma330_op_err { -+ /* The all xfers in the request were success. */ -+ DMA330_ERR_NONE, -+ /* If req aborted due to global error. */ -+ DMA330_ERR_ABORT, -+ /* If req failed due to problem with Channel. */ -+ DMA330_ERR_FAIL, -+}; -+ -+enum dmamov_dst { -+ SAR = 0, -+ CCR, -+ DAR, -+}; -+ -+enum dma330_dst { -+ SRC = 0, -+ DST, -+}; -+ -+enum dma330_cond { -+ SINGLE, -+ BURST, -+ ALWAYS, -+}; -+ -+struct dma_dma330_desc; -+ -+struct _dma330_req { -+ u32 mc_bus; -+ void *mc_cpu; -+ struct dma_dma330_desc *desc; -+}; -+ -+/* ToBeDone for tasklet */ -+struct _dma330_tbd { -+ bool reset_dmac; -+ bool reset_mngr; -+ u8 reset_chan; -+}; -+ -+/* A DMAC Thread */ -+struct dma330_thread { -+ u8 id; -+ int ev; -+ /* If the channel is not yet acquired by any client */ -+ bool free; -+ /* Parent DMAC */ -+ struct dma330_dmac *dmac; -+ /* Only two at a time */ -+ struct _dma330_req req[2]; -+ /* Index of the last enqueued request */ -+ unsigned lstenq; -+ /* Index of the last submitted request or -1 if the DMA is stopped */ -+ int req_running; -+}; -+ -+enum dma330_dmac_state { -+ UNINIT, -+ INIT, -+ DYING, -+}; -+ -+enum desc_status { -+ /* In the DMAC pool */ -+ FREE, -+ /* -+ * Allocated to some channel during prep_xxx -+ * Also may be sitting on the work_list. -+ */ -+ PREP, -+ /* -+ * Sitting on the work_list and already submitted -+ * to the DMA330 core. Not more than two descriptors -+ * of a channel can be BUSY at any time. -+ */ -+ BUSY, -+ /* -+ * Sitting on the channel work_list but xfer done -+ * by DMA330 core -+ */ -+ DONE, -+}; -+ -+struct dma_dma330_chan { -+ /* Schedule desc completion */ -+ struct tasklet_struct task; -+ -+ /* DMA-Engine Channel */ -+ struct dma_chan chan; -+ -+ /* List of submitted descriptors */ -+ struct list_head submitted_list; -+ /* List of issued descriptors */ -+ struct list_head work_list; -+ /* List of completed descriptors */ -+ struct list_head completed_list; -+ -+ /* Pointer to the DMAC that manages this channel, -+ * NULL if the channel is available to be acquired. -+ * As the parent, this DMAC also provides descriptors -+ * to the channel. -+ */ -+ struct dma330_dmac *dmac; -+ -+ /* To protect channel manipulation */ -+ spinlock_t lock; -+ -+ /* -+ * Hardware channel thread of DMA330 DMAC. NULL if the channel is -+ * available. -+ */ -+ struct dma330_thread *thread; -+ -+ /* For D-to-M and M-to-D channels */ -+ int burst_sz; /* the peripheral fifo width */ -+ int burst_len; /* the number of burst */ -+ dma_addr_t fifo_addr; -+ -+ /* for cyclic capability */ -+ bool cyclic; -+}; -+ -+struct dma330_dmac { -+ /* DMA-Engine Device */ -+ struct dma_device ddma; -+ -+ /* Holds info about sg limitations */ -+ struct device_dma_parameters dma_parms; -+ -+ /* Pool of descriptors available for the DMAC's channels */ -+ struct list_head desc_pool; -+ /* To protect desc_pool manipulation */ -+ spinlock_t pool_lock; -+ -+ /* Size of MicroCode buffers for each channel. */ -+ unsigned mcbufsz; -+ /* ioremap'ed address of DMA330 registers. */ -+ void __iomem *base; -+ /* Populated by the DMA330 core driver during dma330_add */ -+ struct dma330_config pcfg; -+ -+ spinlock_t lock; -+ /* Maximum possible events/irqs */ -+ int events[32]; -+ /* BUS address of MicroCode buffer */ -+ dma_addr_t mcode_bus; -+ /* CPU address of MicroCode buffer */ -+ void *mcode_cpu; -+ /* List of all Channel threads */ -+ struct dma330_thread *channels; -+ /* Pointer to the MANAGER thread */ -+ struct dma330_thread *manager; -+ /* To handle bad news in interrupt */ -+ struct tasklet_struct tasks; -+ struct _dma330_tbd dmac_tbd; -+ /* State of DMAC operation */ -+ enum dma330_dmac_state state; -+ /* Holds list of reqs with due callbacks */ -+ struct list_head req_done; -+ -+ /* Peripheral channels connected to this DMAC */ -+ unsigned int num_peripherals; -+ struct dma_dma330_chan *peripherals; /* keep at end */ -+}; -+ -+struct dma_dma330_desc { -+ /* To attach to a queue as child */ -+ struct list_head node; -+ -+ /* Descriptor for the DMA Engine API */ -+ struct dma_async_tx_descriptor txd; -+ -+ /* Xfer for DMA330 core */ -+ struct dma330_xfer px; -+ -+ struct dma330_reqcfg rqcfg; -+ -+ enum desc_status status; -+ -+ int bytes_requested; -+ bool last; -+ -+ /* The channel which currently holds this desc */ -+ struct dma_dma330_chan *pchan; -+ -+ enum dma_transfer_direction rqtype; -+ /* Index of peripheral for the xfer. */ -+ unsigned peri:5; -+ /* Hook to attach to DMAC's list of reqs with due callback */ -+ struct list_head rqd; -+}; -+ -+struct _xfer_spec { -+ u32 ccr; -+ struct dma_dma330_desc *desc; -+}; -+ -+static inline bool _queue_empty(struct dma330_thread *thrd) -+{ -+ return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL; -+} -+ -+static inline bool _queue_full(struct dma330_thread *thrd) -+{ -+ return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL; -+} -+ -+static inline bool is_manager(struct dma330_thread *thrd) -+{ -+ return thrd->dmac->manager == thrd; -+} -+ -+/* If manager of the thread is in Non-Secure mode */ -+static inline bool _manager_ns(struct dma330_thread *thrd) -+{ -+ return (thrd->dmac->pcfg.mode & DMAC_MODE_NS) ? true : false; -+} -+ -+static inline u32 get_revision(u32 periph_id) -+{ -+ return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; -+} -+ -+static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], -+ enum dma330_dst da, u16 val) -+{ -+ if (dry_run) -+ return SZ_DMAADDH; -+ -+ buf[0] = CMD_DMAADDH; -+ buf[0] |= (da << 1); -+ *((__le16 *)&buf[1]) = cpu_to_le16(val); -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", -+ da == 1 ? "DA" : "SA", val); -+ -+ return SZ_DMAADDH; -+} -+ -+static inline u32 _emit_END(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMAEND; -+ -+ buf[0] = CMD_DMAEND; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n"); -+ -+ return SZ_DMAEND; -+} -+ -+static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri) -+{ -+ if (dry_run) -+ return SZ_DMAFLUSHP; -+ -+ buf[0] = CMD_DMAFLUSHP; -+ -+ peri &= 0x1f; -+ peri <<= 3; -+ buf[1] = peri; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3); -+ -+ return SZ_DMAFLUSHP; -+} -+ -+static inline u32 _emit_LD(unsigned dry_run, u8 buf[], enum dma330_cond cond) -+{ -+ if (dry_run) -+ return SZ_DMALD; -+ -+ buf[0] = CMD_DMALD; -+ -+ if (cond == SINGLE) -+ buf[0] |= (0 << 1) | (1 << 0); -+ else if (cond == BURST) -+ buf[0] |= (1 << 1) | (1 << 0); -+ -+ DMA330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n", -+ cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A')); -+ -+ return SZ_DMALD; -+} -+ -+static inline u32 _emit_LDP(unsigned dry_run, u8 buf[], -+ enum dma330_cond cond, u8 peri) -+{ -+ if (dry_run) -+ return SZ_DMALDP; -+ -+ buf[0] = CMD_DMALDP; -+ -+ if (cond == BURST) -+ buf[0] |= (1 << 1); -+ -+ peri &= 0x1f; -+ peri <<= 3; -+ buf[1] = peri; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n", -+ cond == SINGLE ? 'S' : 'B', peri >> 3); -+ -+ return SZ_DMALDP; -+} -+ -+static inline u32 _emit_LP(unsigned dry_run, u8 buf[], -+ unsigned loop, u8 cnt) -+{ -+ if (dry_run) -+ return SZ_DMALP; -+ -+ buf[0] = CMD_DMALP; -+ -+ if (loop) -+ buf[0] |= (1 << 1); -+ -+ cnt--; /* DMAC increments by 1 internally */ -+ buf[1] = cnt; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt); -+ -+ return SZ_DMALP; -+} -+ -+struct _arg_LPEND { -+ enum dma330_cond cond; -+ bool forever; -+ unsigned loop; -+ u8 bjump; -+}; -+ -+static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[], -+ const struct _arg_LPEND *arg) -+{ -+ enum dma330_cond cond = arg->cond; -+ bool forever = arg->forever; -+ unsigned loop = arg->loop; -+ u8 bjump = arg->bjump; -+ -+ if (dry_run) -+ return SZ_DMALPEND; -+ -+ buf[0] = CMD_DMALPEND; -+ -+ if (loop) -+ buf[0] |= (1 << 2); -+ -+ if (!forever) -+ buf[0] |= (1 << 4); -+ -+ if (cond == SINGLE) -+ buf[0] |= (0 << 1) | (1 << 0); -+ else if (cond == BURST) -+ buf[0] |= (1 << 1) | (1 << 0); -+ -+ buf[1] = bjump; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n", -+ forever ? "FE" : "END", -+ cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'), -+ loop ? '1' : '0', -+ bjump); -+ -+ return SZ_DMALPEND; -+} -+ -+static inline u32 _emit_KILL(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMAKILL; -+ -+ buf[0] = CMD_DMAKILL; -+ -+ return SZ_DMAKILL; -+} -+ -+static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], -+ enum dmamov_dst dst, u32 val) -+{ -+ if (dry_run) -+ return SZ_DMAMOV; -+ -+ buf[0] = CMD_DMAMOV; -+ buf[1] = dst; -+ *((__le32 *)&buf[2]) = cpu_to_le32(val); -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n", -+ dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val); -+ -+ return SZ_DMAMOV; -+} -+ -+static inline u32 _emit_NOP(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMANOP; -+ -+ buf[0] = CMD_DMANOP; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n"); -+ -+ return SZ_DMANOP; -+} -+ -+static inline u32 _emit_RMB(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMARMB; -+ -+ buf[0] = CMD_DMARMB; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n"); -+ -+ return SZ_DMARMB; -+} -+ -+static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev) -+{ -+ if (dry_run) -+ return SZ_DMASEV; -+ -+ buf[0] = CMD_DMASEV; -+ -+ ev &= 0x1f; -+ ev <<= 3; -+ buf[1] = ev; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3); -+ -+ return SZ_DMASEV; -+} -+ -+static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum dma330_cond cond) -+{ -+ if (dry_run) -+ return SZ_DMAST; -+ -+ buf[0] = CMD_DMAST; -+ -+ if (cond == SINGLE) -+ buf[0] |= (0 << 1) | (1 << 0); -+ else if (cond == BURST) -+ buf[0] |= (1 << 1) | (1 << 0); -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n", -+ cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A')); -+ -+ return SZ_DMAST; -+} -+ -+static inline u32 _emit_STP(unsigned dry_run, u8 buf[], -+ enum dma330_cond cond, u8 peri) -+{ -+ if (dry_run) -+ return SZ_DMASTP; -+ -+ buf[0] = CMD_DMASTP; -+ -+ if (cond == BURST) -+ buf[0] |= (1 << 1); -+ -+ peri &= 0x1f; -+ peri <<= 3; -+ buf[1] = peri; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n", -+ cond == SINGLE ? 'S' : 'B', peri >> 3); -+ -+ return SZ_DMASTP; -+} -+ -+static inline u32 _emit_STZ(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMASTZ; -+ -+ buf[0] = CMD_DMASTZ; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n"); -+ -+ return SZ_DMASTZ; -+} -+ -+static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev, -+ unsigned invalidate) -+{ -+ if (dry_run) -+ return SZ_DMAWFE; -+ -+ buf[0] = CMD_DMAWFE; -+ -+ ev &= 0x1f; -+ ev <<= 3; -+ buf[1] = ev; -+ -+ if (invalidate) -+ buf[1] |= (1 << 1); -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n", -+ ev >> 3, invalidate ? ", I" : ""); -+ -+ return SZ_DMAWFE; -+} -+ -+static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], -+ enum dma330_cond cond, u8 peri) -+{ -+ if (dry_run) -+ return SZ_DMAWFP; -+ -+ buf[0] = CMD_DMAWFP; -+ -+ if (cond == SINGLE) -+ buf[0] |= (0 << 1) | (0 << 0); -+ else if (cond == BURST) -+ buf[0] |= (1 << 1) | (0 << 0); -+ else -+ buf[0] |= (0 << 1) | (1 << 0); -+ -+ peri &= 0x1f; -+ peri <<= 3; -+ buf[1] = peri; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n", -+ cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3); -+ -+ return SZ_DMAWFP; -+} -+ -+static inline u32 _emit_WMB(unsigned dry_run, u8 buf[]) -+{ -+ if (dry_run) -+ return SZ_DMAWMB; -+ -+ buf[0] = CMD_DMAWMB; -+ -+ DMA330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n"); -+ -+ return SZ_DMAWMB; -+} -+ -+struct _arg_GO { -+ u8 chan; -+ u32 addr; -+ unsigned ns; -+}; -+ -+static inline u32 _emit_GO(unsigned dry_run, u8 buf[], -+ const struct _arg_GO *arg) -+{ -+ u8 chan = arg->chan; -+ u32 addr = arg->addr; -+ unsigned ns = arg->ns; -+ -+ if (dry_run) -+ return SZ_DMAGO; -+ -+ buf[0] = CMD_DMAGO; -+ buf[0] |= (ns << 1); -+ -+ buf[1] = chan & 0x7; -+ -+ *((__le32 *)&buf[2]) = cpu_to_le32(addr); -+ -+ return SZ_DMAGO; -+} -+ -+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) -+ -+/* Returns Time-Out */ -+static bool _until_dmac_idle(struct dma330_thread *thrd) -+{ -+ void __iomem *regs = thrd->dmac->base; -+ unsigned long loops = msecs_to_loops(5); -+ -+ do { -+ /* Until Manager is Idle */ -+ if (!(readl(regs + DBGSTATUS) & DBG_BUSY)) -+ break; -+ -+ cpu_relax(); -+ } while (--loops); -+ -+ if (!loops) -+ return true; -+ -+ return false; -+} -+ -+static inline void _execute_DBGINSN(struct dma330_thread *thrd, -+ u8 insn[], bool as_manager) -+{ -+ void __iomem *regs = thrd->dmac->base; -+ u32 val; -+ -+ val = (insn[0] << 16) | (insn[1] << 24); -+ if (!as_manager) { -+ val |= (1 << 0); -+ val |= (thrd->id << 8); /* Channel Number */ -+ } -+ writel(val, regs + DBGINST0); -+ -+ val = le32_to_cpu(*((__le32 *)&insn[2])); -+ writel(val, regs + DBGINST1); -+ -+ /* If timed out due to halted state-machine */ -+ if (_until_dmac_idle(thrd)) { -+ dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n"); -+ return; -+ } -+ -+ /* Get going */ -+ writel(0, regs + DBGCMD); -+} -+ -+static inline u32 _state(struct dma330_thread *thrd) -+{ -+ void __iomem *regs = thrd->dmac->base; -+ u32 val; -+ -+ if (is_manager(thrd)) -+ val = readl(regs + DS) & 0xf; -+ else -+ val = readl(regs + CS(thrd->id)) & 0xf; -+ -+ switch (val) { -+ case DS_ST_STOP: -+ return DMA330_STATE_STOPPED; -+ case DS_ST_EXEC: -+ return DMA330_STATE_EXECUTING; -+ case DS_ST_CMISS: -+ return DMA330_STATE_CACHEMISS; -+ case DS_ST_UPDTPC: -+ return DMA330_STATE_UPDTPC; -+ case DS_ST_WFE: -+ return DMA330_STATE_WFE; -+ case DS_ST_FAULT: -+ return DMA330_STATE_FAULTING; -+ case DS_ST_ATBRR: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_ATBARRIER; -+ case DS_ST_QBUSY: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_QUEUEBUSY; -+ case DS_ST_WFP: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_WFP; -+ case DS_ST_KILL: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_KILLING; -+ case DS_ST_CMPLT: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_COMPLETING; -+ case DS_ST_FLTCMP: -+ if (is_manager(thrd)) -+ return DMA330_STATE_INVALID; -+ else -+ return DMA330_STATE_FAULT_COMPLETING; -+ default: -+ return DMA330_STATE_INVALID; -+ } -+} -+ -+static void _stop(struct dma330_thread *thrd) -+{ -+ void __iomem *regs = thrd->dmac->base; -+ u8 insn[6] = {0, 0, 0, 0, 0, 0}; -+ -+ if (_state(thrd) == DMA330_STATE_FAULT_COMPLETING) -+ UNTIL(thrd, DMA330_STATE_FAULTING | DMA330_STATE_KILLING); -+ -+ /* Return if nothing needs to be done */ -+ if (_state(thrd) == DMA330_STATE_COMPLETING -+ || _state(thrd) == DMA330_STATE_KILLING -+ || _state(thrd) == DMA330_STATE_STOPPED) -+ return; -+ -+ _emit_KILL(0, insn); -+ -+ /* Stop generating interrupts for SEV */ -+ writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN); -+ -+ _execute_DBGINSN(thrd, insn, is_manager(thrd)); -+} -+ -+/* Start doing req 'idx' of thread 'thrd' */ -+static bool _trigger(struct dma330_thread *thrd) -+{ -+ void __iomem *regs = thrd->dmac->base; -+ struct _dma330_req *req; -+ struct dma_dma330_desc *desc; -+ struct _arg_GO go; -+ unsigned ns; -+ u8 insn[6] = {0, 0, 0, 0, 0, 0}; -+ int idx; -+ -+ /* Return if already ACTIVE */ -+ if (_state(thrd) != DMA330_STATE_STOPPED) -+ return true; -+ -+ idx = 1 - thrd->lstenq; -+ if (thrd->req[idx].desc != NULL) { -+ req = &thrd->req[idx]; -+ } else { -+ idx = thrd->lstenq; -+ if (thrd->req[idx].desc != NULL) -+ req = &thrd->req[idx]; -+ else -+ req = NULL; -+ } -+ -+ /* Return if no request */ -+ if (!req) -+ return true; -+ -+ /* Return if req is running */ -+ if (idx == thrd->req_running) -+ return true; -+ -+ desc = req->desc; -+ -+ ns = desc->rqcfg.nonsecure ? 1 : 0; -+ -+ /* See 'Abort Sources' point-4 at Page 2-25 */ -+ if (_manager_ns(thrd) && !ns) -+ dev_info(thrd->dmac->ddma.dev, "%s:%d Recipe for ABORT!\n", -+ __func__, __LINE__); -+ -+ go.chan = thrd->id; -+ go.addr = req->mc_bus; -+ go.ns = ns; -+ _emit_GO(0, insn, &go); -+ -+ /* Set to generate interrupts for SEV */ -+ writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN); -+ -+ /* Only manager can execute GO */ -+ _execute_DBGINSN(thrd, insn, true); -+ -+ thrd->req_running = idx; -+ -+ return true; -+} -+ -+static bool _start(struct dma330_thread *thrd) -+{ -+ switch (_state(thrd)) { -+ case DMA330_STATE_FAULT_COMPLETING: -+ UNTIL(thrd, DMA330_STATE_FAULTING | DMA330_STATE_KILLING); -+ -+ if (_state(thrd) == DMA330_STATE_KILLING) -+ UNTIL(thrd, DMA330_STATE_STOPPED) -+ -+ case DMA330_STATE_FAULTING: -+ _stop(thrd); -+ -+ case DMA330_STATE_KILLING: -+ case DMA330_STATE_COMPLETING: -+ UNTIL(thrd, DMA330_STATE_STOPPED) -+ -+ case DMA330_STATE_STOPPED: -+ return _trigger(thrd); -+ -+ case DMA330_STATE_WFP: -+ case DMA330_STATE_QUEUEBUSY: -+ case DMA330_STATE_ATBARRIER: -+ case DMA330_STATE_UPDTPC: -+ case DMA330_STATE_CACHEMISS: -+ case DMA330_STATE_EXECUTING: -+ return true; -+ -+ case DMA330_STATE_WFE: /* For RESUME, nothing yet */ -+ default: -+ return false; -+ } -+} -+ -+static inline int _ldst_memtomem(unsigned dry_run, u8 buf[], -+ const struct _xfer_spec *pxs, int cyc) -+{ -+ int off = 0; -+ -+ while (cyc--) { -+ off += _emit_LD(dry_run, &buf[off], ALWAYS); -+ off += _emit_ST(dry_run, &buf[off], ALWAYS); -+ } -+ -+ return off; -+} -+ -+static inline int _ldst_devtomem(unsigned dry_run, u8 buf[], -+ const struct _xfer_spec *pxs, int cyc) -+{ -+ int off = 0; -+ -+ while (cyc--) { -+ off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri); -+ off += _emit_LD(dry_run, &buf[off], ALWAYS); -+ off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->desc->peri); -+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); -+ } -+ -+ return off; -+} -+ -+static inline int _ldst_memtodev(unsigned dry_run, u8 buf[], -+ const struct _xfer_spec *pxs, int cyc) -+{ -+ int off = 0; -+ -+ while (cyc--) { -+ off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri); -+ off += _emit_LD(dry_run, &buf[off], ALWAYS); -+ off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->desc->peri); -+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); -+ } -+ -+ return off; -+} -+ -+static int _bursts(unsigned dry_run, u8 buf[], -+ const struct _xfer_spec *pxs, int cyc) -+{ -+ int off = 0; -+ -+ switch (pxs->desc->rqtype) { -+ case DMA_MEM_TO_DEV: -+ off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc); -+ break; -+ case DMA_DEV_TO_MEM: -+ off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc); -+ break; -+ case DMA_MEM_TO_MEM: -+ off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc); -+ break; -+ default: -+ off += 0x40000000; /* Scare off the Client */ -+ break; -+ } -+ -+ return off; -+} -+ -+/* Returns bytes consumed and updates bursts */ -+static inline int _loop(unsigned dry_run, u8 buf[], -+ unsigned long *bursts, const struct _xfer_spec *pxs) -+{ -+ int cyc, cycmax, szlp, szlpend, szbrst, off; -+ unsigned lcnt0, lcnt1, ljmp0, ljmp1; -+ struct _arg_LPEND lpend; -+ -+ if (*bursts == 1) -+ return _bursts(dry_run, buf, pxs, 1); -+ -+ /* Max iterations possible in DMALP is 256 */ -+ if (*bursts >= 256*256) { -+ lcnt1 = 256; -+ lcnt0 = 256; -+ cyc = *bursts / lcnt1 / lcnt0; -+ } else if (*bursts > 256) { -+ lcnt1 = 256; -+ lcnt0 = *bursts / lcnt1; -+ cyc = 1; -+ } else { -+ lcnt1 = *bursts; -+ lcnt0 = 0; -+ cyc = 1; -+ } -+ -+ szlp = _emit_LP(1, buf, 0, 0); -+ szbrst = _bursts(1, buf, pxs, 1); -+ -+ lpend.cond = ALWAYS; -+ lpend.forever = false; -+ lpend.loop = 0; -+ lpend.bjump = 0; -+ szlpend = _emit_LPEND(1, buf, &lpend); -+ -+ if (lcnt0) { -+ szlp *= 2; -+ szlpend *= 2; -+ } -+ -+ /* -+ * Max bursts that we can unroll due to limit on the -+ * size of backward jump that can be encoded in DMALPEND -+ * which is 8-bits and hence 255 -+ */ -+ cycmax = (255 - (szlp + szlpend)) / szbrst; -+ -+ cyc = (cycmax < cyc) ? cycmax : cyc; -+ -+ off = 0; -+ -+ if (lcnt0) { -+ off += _emit_LP(dry_run, &buf[off], 0, lcnt0); -+ ljmp0 = off; -+ } -+ -+ off += _emit_LP(dry_run, &buf[off], 1, lcnt1); -+ ljmp1 = off; -+ -+ off += _bursts(dry_run, &buf[off], pxs, cyc); -+ -+ lpend.cond = ALWAYS; -+ lpend.forever = false; -+ lpend.loop = 1; -+ lpend.bjump = off - ljmp1; -+ off += _emit_LPEND(dry_run, &buf[off], &lpend); -+ -+ if (lcnt0) { -+ lpend.cond = ALWAYS; -+ lpend.forever = false; -+ lpend.loop = 0; -+ lpend.bjump = off - ljmp0; -+ off += _emit_LPEND(dry_run, &buf[off], &lpend); -+ } -+ -+ *bursts = lcnt1 * cyc; -+ if (lcnt0) -+ *bursts *= lcnt0; -+ -+ return off; -+} -+ -+static inline int _req_loop(unsigned dry_run, u8 buf[], enum dma330_cond cond, -+ unsigned long *count, const struct _xfer_spec *pxs) -+{ -+ unsigned ljmp0; -+ struct _arg_LPEND lpend; -+ int off = 0; -+ -+ off += _emit_LP(dry_run, &buf[off], 0, *count); -+ ljmp0 = off; -+ -+ off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); -+ off += _emit_LD(dry_run, &buf[off], cond); -+ off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri); -+ -+ lpend.cond = cond; -+ lpend.forever = false; -+ lpend.loop = 0; -+ lpend.bjump = off - ljmp0; -+ off += _emit_LPEND(dry_run, &buf[off], &lpend); -+ -+ return off; -+} -+ -+static inline u32 _prepare_ccr(const struct dma330_reqcfg *rqc, -+ enum dma330_cond cond) -+{ -+ u32 ccr = 0; -+ -+ if (rqc->src_inc) -+ ccr |= CC_SRCINC; -+ -+ if (rqc->dst_inc) -+ ccr |= CC_DSTINC; -+ -+ /* We set same protection levels for Src and DST for now */ -+ if (rqc->privileged) -+ ccr |= CC_SRCPRI | CC_DSTPRI; -+ if (rqc->nonsecure) -+ ccr |= CC_SRCNS | CC_DSTNS; -+ if (rqc->insnaccess) -+ ccr |= CC_SRCIA | CC_DSTIA; -+ -+ if (cond != SINGLE) { -+ ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT); -+ ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT); -+ } -+ -+ ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT); -+ ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT); -+ -+ ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT); -+ ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT); -+ -+ ccr |= (rqc->swap << CC_SWAP_SHFT); -+ -+ return ccr; -+} -+ -+ -+static inline int _setup_xfer(unsigned dry_run, u8 buf[], -+ const struct _xfer_spec *pxs) -+{ -+ u32 bytes = pxs->desc->px.bytes; -+ u32 bursts = BYTE_TO_BURST(bytes, pxs->ccr); -+ u32 singles = (bytes - BURST_TO_BYTE(bursts, pxs->ccr)) >> 2; -+ u32 ccr = pxs->ccr; -+ u32 src_addr = pxs->desc->px.src_addr; -+ u32 dst_addr = pxs->desc->px.dst_addr; -+ unsigned long c; -+ int off = 0; -+ -+ if ((pxs->desc->rqtype == DMA_DEV_TO_MEM) || -+ (pxs->desc->rqtype == DMA_MEM_TO_DEV)) { -+ if(bursts) { -+ off += _emit_MOV(dry_run, &buf[off], CCR, ccr); -+ off += _emit_MOV(dry_run, &buf[off], SAR, src_addr); -+ off += _emit_MOV(dry_run, &buf[off], DAR, dst_addr); -+ -+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); -+ -+ while(bursts) { -+ c = (bursts > 256) ? 256 : bursts; -+ off += _req_loop(dry_run, &buf[off], BURST, &c, pxs); -+ bursts -= c; -+ } -+ } -+ -+ if (singles) { -+ ccr = _prepare_ccr(&pxs->desc->rqcfg, SINGLE); -+ if (pxs->desc->rqtype == DMA_MEM_TO_DEV) { -+ src_addr += bytes - singles * 4; -+ } else { -+ dst_addr += bytes - singles * 4; -+ } -+ off += _emit_MOV(dry_run, &buf[off], CCR, ccr); -+ off += _emit_MOV(dry_run, &buf[off], SAR, src_addr); -+ off += _emit_MOV(dry_run, &buf[off], DAR, dst_addr); -+ -+ while(singles) { -+ c = (singles > 256) ? 256 : singles; -+ off += _req_loop(dry_run, &buf[off], SINGLE, &c, pxs); -+ singles -= c; -+ } -+ -+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); -+ } -+ } else { -+ /* Error if xfer length is not aligned at burst size */ -+ if (bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) -+ return -EINVAL; -+ -+ off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); -+ off += _emit_MOV(dry_run, &buf[off], SAR, src_addr); -+ off += _emit_MOV(dry_run, &buf[off], DAR, dst_addr); -+ -+ while (bursts) { -+ c = bursts; -+ off += _loop(dry_run, &buf[off], &c, pxs); -+ bursts -= c; -+ } -+ } -+ -+ return off; -+} -+ -+/* -+ * A req is a sequence of one or more xfer units. -+ * Returns the number of bytes taken to setup the MC for the req. -+ */ -+static int _setup_req(unsigned dry_run, struct dma330_thread *thrd, -+ unsigned index, struct _xfer_spec *pxs) -+{ -+ struct _dma330_req *req = &thrd->req[index]; -+ u8 *buf = req->mc_cpu; -+ int off = 0; -+ -+ DMA330_DBGMC_START(req->mc_bus); -+ -+ off += _setup_xfer(dry_run, &buf[off], pxs); -+ -+ /* DMASEV peripheral/event */ -+ off += _emit_SEV(dry_run, &buf[off], thrd->ev); -+ /* DMAEND */ -+ off += _emit_END(dry_run, &buf[off]); -+ -+ return off; -+} -+ -+/* -+ * Submit a list of xfers after which the client wants notification. -+ * Client is not notified after each xfer unit, just once after all -+ * xfer units are done or some error occurs. -+ */ -+static int dma330_submit_req(struct dma330_thread *thrd, -+ struct dma_dma330_desc *desc) -+{ -+ struct dma330_dmac *dma330 = thrd->dmac; -+ struct _xfer_spec xs; -+ unsigned long flags; -+ unsigned idx; -+ u32 ccr; -+ int ret = 0; -+ -+ if (dma330->state == DYING -+ || dma330->dmac_tbd.reset_chan & (1 << thrd->id)) { -+ dev_info(thrd->dmac->ddma.dev, "%s:%d\n", -+ __func__, __LINE__); -+ return -EAGAIN; -+ } -+ -+ /* If request for non-existing peripheral */ -+ if (desc->rqtype != DMA_MEM_TO_MEM && -+ desc->peri >= dma330->pcfg.num_peri) { -+ dev_info(thrd->dmac->ddma.dev, -+ "%s:%d Invalid peripheral(%u)!\n", -+ __func__, __LINE__, desc->peri); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&dma330->lock, flags); -+ -+ if (_queue_full(thrd)) { -+ ret = -EAGAIN; -+ goto xfer_exit; -+ } -+ -+ /* Prefer Secure Channel */ -+ if (!_manager_ns(thrd)) -+ desc->rqcfg.nonsecure = 0; -+ else -+ desc->rqcfg.nonsecure = 1; -+ -+ ccr = _prepare_ccr(&desc->rqcfg, BURST); -+ -+ idx = thrd->req[0].desc == NULL ? 0 : 1; -+ -+ xs.ccr = ccr; -+ xs.desc = desc; -+ -+ /* First dry run to check if req is acceptable */ -+ ret = _setup_req(1, thrd, idx, &xs); -+ if (ret < 0) -+ goto xfer_exit; -+ -+ if (ret > dma330->mcbufsz / 2) { -+ dev_info(dma330->ddma.dev, "%s:%d Try increasing mcbufsz (%i/%i)\n", -+ __func__, __LINE__, ret, dma330->mcbufsz / 2); -+ ret = -ENOMEM; -+ goto xfer_exit; -+ } -+ -+ /* Hook the request */ -+ thrd->lstenq = idx; -+ thrd->req[idx].desc = desc; -+ _setup_req(0, thrd, idx, &xs); -+ -+ ret = 0; -+ -+xfer_exit: -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ -+ return ret; -+} -+ -+static void dma_dma330_rqcb(struct dma_dma330_desc *desc, enum dma330_op_err err) -+{ -+ struct dma_dma330_chan *pch; -+ unsigned long flags; -+ -+ if (!desc) -+ return; -+ -+ pch = desc->pchan; -+ -+ /* If desc aborted */ -+ if (!pch) -+ return; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ desc->status = DONE; -+ -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+ tasklet_schedule(&pch->task); -+} -+ -+static void dma330_dotask(unsigned long data) -+{ -+ struct dma330_dmac *dma330 = (struct dma330_dmac *) data; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&dma330->lock, flags); -+ -+ /* The DMAC itself gone nuts */ -+ if (dma330->dmac_tbd.reset_dmac) { -+ dma330->state = DYING; -+ /* Reset the manager too */ -+ dma330->dmac_tbd.reset_mngr = true; -+ /* Clear the reset flag */ -+ dma330->dmac_tbd.reset_dmac = false; -+ } -+ -+ if (dma330->dmac_tbd.reset_mngr) { -+ _stop(dma330->manager); -+ /* Reset all channels */ -+ dma330->dmac_tbd.reset_chan = (1 << dma330->pcfg.num_chan) - 1; -+ /* Clear the reset flag */ -+ dma330->dmac_tbd.reset_mngr = false; -+ } -+ -+ for (i = 0; i < dma330->pcfg.num_chan; i++) { -+ -+ if (dma330->dmac_tbd.reset_chan & (1 << i)) { -+ struct dma330_thread *thrd = &dma330->channels[i]; -+ void __iomem *regs = dma330->base; -+ enum dma330_op_err err; -+ -+ _stop(thrd); -+ -+ if (readl(regs + FSC) & (1 << thrd->id)) -+ err = DMA330_ERR_FAIL; -+ else -+ err = DMA330_ERR_ABORT; -+ -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ dma_dma330_rqcb(thrd->req[1 - thrd->lstenq].desc, err); -+ dma_dma330_rqcb(thrd->req[thrd->lstenq].desc, err); -+ spin_lock_irqsave(&dma330->lock, flags); -+ -+ thrd->req[0].desc = NULL; -+ thrd->req[1].desc = NULL; -+ thrd->req_running = -1; -+ -+ /* Clear the reset flag */ -+ dma330->dmac_tbd.reset_chan &= ~(1 << i); -+ } -+ } -+ -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ -+ return; -+} -+ -+/* Returns 1 if state was updated, 0 otherwise */ -+static int dma330_update(struct dma330_dmac *dma330) -+{ -+ struct dma_dma330_desc *descdone, *tmp; -+ unsigned long flags; -+ void __iomem *regs; -+ u32 val; -+ int id, ev, ret = 0; -+ -+ regs = dma330->base; -+ -+ spin_lock_irqsave(&dma330->lock, flags); -+ -+ val = readl(regs + FSM) & 0x1; -+ if (val) -+ dma330->dmac_tbd.reset_mngr = true; -+ else -+ dma330->dmac_tbd.reset_mngr = false; -+ -+ val = readl(regs + FSC) & ((1 << dma330->pcfg.num_chan) - 1); -+ dma330->dmac_tbd.reset_chan |= val; -+ if (val) { -+ int i = 0; -+ while (i < dma330->pcfg.num_chan) { -+ if (val & (1 << i)) { -+ dev_info(dma330->ddma.dev, -+ "Reset Channel-%d\t CS-%x FTC-%x\n", -+ i, readl(regs + CS(i)), -+ readl(regs + FTC(i))); -+ _stop(&dma330->channels[i]); -+ } -+ i++; -+ } -+ } -+ -+ /* Check which event happened i.e, thread notified */ -+ val = readl(regs + ES); -+ if (dma330->pcfg.num_events < 32 -+ && val & ~((1 << dma330->pcfg.num_events) - 1)) { -+ dma330->dmac_tbd.reset_dmac = true; -+ dev_err(dma330->ddma.dev, "%s:%d Unexpected!\n", __func__, -+ __LINE__); -+ ret = 1; -+ goto updt_exit; -+ } -+ -+ for (ev = 0; ev < dma330->pcfg.num_events; ev++) { -+ if (val & (1 << ev)) { /* Event occurred */ -+ struct dma330_thread *thrd; -+ u32 inten = readl(regs + INTEN); -+ int active; -+ -+ /* Clear the event */ -+ if (inten & (1 << ev)) -+ writel(1 << ev, regs + INTCLR); -+ -+ ret = 1; -+ -+ id = dma330->events[ev]; -+ -+ thrd = &dma330->channels[id]; -+ -+ active = thrd->req_running; -+ if (active == -1) /* Aborted */ -+ continue; -+ -+ /* Detach the req */ -+ descdone = thrd->req[active].desc; -+ thrd->req[active].desc = NULL; -+ -+ thrd->req_running = -1; -+ -+ /* Get going again ASAP */ -+ _start(thrd); -+ -+ /* For now, just make a list of callbacks to be done */ -+ list_add_tail(&descdone->rqd, &dma330->req_done); -+ } -+ } -+ -+ /* Now that we are in no hurry, do the callbacks */ -+ list_for_each_entry_safe(descdone, tmp, &dma330->req_done, rqd) { -+ list_del(&descdone->rqd); -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ dma_dma330_rqcb(descdone, DMA330_ERR_NONE); -+ spin_lock_irqsave(&dma330->lock, flags); -+ } -+ -+updt_exit: -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ -+ if (dma330->dmac_tbd.reset_dmac -+ || dma330->dmac_tbd.reset_mngr -+ || dma330->dmac_tbd.reset_chan) { -+ ret = 1; -+ tasklet_schedule(&dma330->tasks); -+ } -+ -+ return ret; -+} -+ -+/* Reserve an event */ -+static inline int _alloc_event(struct dma330_thread *thrd) -+{ -+ struct dma330_dmac *dma330 = thrd->dmac; -+ int ev; -+ -+ for (ev = 0; ev < dma330->pcfg.num_events; ev++) -+ if (dma330->events[ev] == -1) { -+ dma330->events[ev] = thrd->id; -+ return ev; -+ } -+ -+ return -1; -+} -+ -+static bool _chan_ns(const struct dma330_dmac *dma330, int i) -+{ -+ return dma330->pcfg.irq_ns & (1 << i); -+} -+ -+/* Upon success, returns IdentityToken for the -+ * allocated channel, NULL otherwise. -+ */ -+static struct dma330_thread *dma330_request_channel(struct dma330_dmac *dma330) -+{ -+ struct dma330_thread *thrd = NULL; -+ unsigned long flags; -+ int chans, i; -+ -+ if (dma330->state == DYING) -+ return NULL; -+ -+ chans = dma330->pcfg.num_chan; -+ -+ spin_lock_irqsave(&dma330->lock, flags); -+ -+ for (i = 0; i < chans; i++) { -+ thrd = &dma330->channels[i]; -+ if ((thrd->free) && (!_manager_ns(thrd) || -+ _chan_ns(dma330, i))) { -+ thrd->ev = _alloc_event(thrd); -+ if (thrd->ev >= 0) { -+ thrd->free = false; -+ thrd->lstenq = 1; -+ thrd->req[0].desc = NULL; -+ thrd->req[1].desc = NULL; -+ thrd->req_running = -1; -+ break; -+ } -+ } -+ thrd = NULL; -+ } -+ -+ spin_unlock_irqrestore(&dma330->lock, flags); -+ -+ return thrd; -+} -+ -+/* Release an event */ -+static inline void _free_event(struct dma330_thread *thrd, int ev) -+{ -+ struct dma330_dmac *dma330 = thrd->dmac; -+ -+ /* If the event is valid and was held by the thread */ -+ if (ev >= 0 && ev < dma330->pcfg.num_events -+ && dma330->events[ev] == thrd->id) -+ dma330->events[ev] = -1; -+} -+ -+static void dma330_release_channel(struct dma330_thread *thrd) -+{ -+ struct dma330_dmac *dma330; -+ unsigned long flags; -+ -+ if (!thrd || thrd->free) -+ return; -+ -+ _stop(thrd); -+ -+ dma_dma330_rqcb(thrd->req[1 - thrd->lstenq].desc, DMA330_ERR_ABORT); -+ dma_dma330_rqcb(thrd->req[thrd->lstenq].desc, DMA330_ERR_ABORT); -+ -+ dma330 = thrd->dmac; -+ -+ spin_lock_irqsave(&dma330->lock, flags); -+ _free_event(thrd, thrd->ev); -+ thrd->free = true; -+ spin_unlock_irqrestore(&dma330->lock, flags); -+} -+ -+/* Initialize the structure for DMA330 configuration, that can be used -+ * by the client driver the make best use of the DMAC -+ */ -+static void read_dmac_config(struct dma330_dmac *dma330) -+{ -+ void __iomem *regs = dma330->base; -+ u32 val; -+ -+ val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT; -+ val &= CRD_DATA_WIDTH_MASK; -+ dma330->pcfg.data_bus_width = 8 * (1 << val); -+ -+ val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT; -+ val &= CRD_DATA_BUFF_MASK; -+ dma330->pcfg.data_buf_dep = val + 1; -+ -+ val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT; -+ val &= CR0_NUM_CHANS_MASK; -+ val += 1; -+ dma330->pcfg.num_chan = val; -+ -+ val = readl(regs + CR0); -+ if (val & CR0_PERIPH_REQ_SET) { -+ val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK; -+ val += 1; -+ dma330->pcfg.num_peri = val; -+ dma330->pcfg.peri_ns = readl(regs + CR4); -+ } else { -+ dma330->pcfg.num_peri = 0; -+ } -+ -+ val = readl(regs + CR0); -+ if (val & CR0_BOOT_MAN_NS) -+ dma330->pcfg.mode |= DMAC_MODE_NS; -+ else -+ dma330->pcfg.mode &= ~DMAC_MODE_NS; -+ -+ val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT; -+ val &= CR0_NUM_EVENTS_MASK; -+ val += 1; -+ dma330->pcfg.num_events = val; -+ -+ dma330->pcfg.irq_ns = readl(regs + CR3); -+} -+ -+static inline void _reset_thread(struct dma330_thread *thrd) -+{ -+ struct dma330_dmac *dma330 = thrd->dmac; -+ -+ thrd->req[0].mc_cpu = dma330->mcode_cpu -+ + (thrd->id * dma330->mcbufsz); -+ thrd->req[0].mc_bus = dma330->mcode_bus -+ + (thrd->id * dma330->mcbufsz); -+ thrd->req[0].desc = NULL; -+ -+ thrd->req[1].mc_cpu = thrd->req[0].mc_cpu -+ + dma330->mcbufsz / 2; -+ thrd->req[1].mc_bus = thrd->req[0].mc_bus -+ + dma330->mcbufsz / 2; -+ thrd->req[1].desc = NULL; -+ -+ thrd->req_running = -1; -+} -+ -+static int dmac_alloc_threads(struct dma330_dmac *dma330) -+{ -+ int chans = dma330->pcfg.num_chan; -+ struct dma330_thread *thrd; -+ int i; -+ -+ /* Allocate 1 Manager and 'chans' Channel threads */ -+ dma330->channels = kzalloc((1 + chans) * sizeof(*thrd), -+ GFP_KERNEL); -+ if (!dma330->channels) -+ return -ENOMEM; -+ -+ /* Init Channel threads */ -+ for (i = 0; i < chans; i++) { -+ thrd = &dma330->channels[i]; -+ thrd->id = i; -+ thrd->dmac = dma330; -+ _reset_thread(thrd); -+ thrd->free = true; -+ } -+ -+ /* MANAGER is indexed at the end */ -+ thrd = &dma330->channels[chans]; -+ thrd->id = chans; -+ thrd->dmac = dma330; -+ thrd->free = false; -+ dma330->manager = thrd; -+ -+ return 0; -+} -+ -+static int dmac_alloc_resources(struct dma330_dmac *dma330) -+{ -+ int chans = dma330->pcfg.num_chan; -+ int ret; -+ -+ /* -+ * Alloc MicroCode buffer for 'chans' Channel threads. -+ * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN) -+ */ -+ dma330->mcode_cpu = dma_alloc_coherent(dma330->ddma.dev, -+ chans * dma330->mcbufsz, -+ &dma330->mcode_bus, GFP_KERNEL); -+ if (!dma330->mcode_cpu) { -+ dev_err(dma330->ddma.dev, "%s:%d Can't allocate memory!\n", -+ __func__, __LINE__); -+ return -ENOMEM; -+ } -+ -+ ret = dmac_alloc_threads(dma330); -+ if (ret) { -+ dev_err(dma330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n", -+ __func__, __LINE__); -+ dma_free_coherent(dma330->ddma.dev, -+ chans * dma330->mcbufsz, -+ dma330->mcode_cpu, dma330->mcode_bus); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int dma330_add(struct dma330_dmac *dma330) -+{ -+ void __iomem *regs; -+ int i, ret; -+ -+ regs = dma330->base; -+ -+ /* Check if we can handle this DMAC */ -+ if ((dma330->pcfg.periph_id & 0xffffff) != PERIPH_ID_VAL) { -+ dev_err(dma330->ddma.dev, "PERIPH_ID 0x%x !\n", -+ dma330->pcfg.periph_id); -+ return -EINVAL; -+ } -+ -+ /* Read the configuration of the DMAC */ -+ read_dmac_config(dma330); -+ -+ if (dma330->pcfg.num_events == 0) { -+ dev_err(dma330->ddma.dev, "%s:%d Can't work without events!\n", -+ __func__, __LINE__); -+ return -EINVAL; -+ } -+ -+ spin_lock_init(&dma330->lock); -+ -+ INIT_LIST_HEAD(&dma330->req_done); -+ -+ /* Use default MC buffer size if not provided */ -+ if (!dma330->mcbufsz) -+ dma330->mcbufsz = MCODE_BUFF_PER_REQ * 2; -+ -+ /* Mark all events as free */ -+ for (i = 0; i < dma330->pcfg.num_events; i++) -+ dma330->events[i] = -1; -+ -+ /* Allocate resources needed by the DMAC */ -+ ret = dmac_alloc_resources(dma330); -+ if (ret) { -+ dev_err(dma330->ddma.dev, "Unable to create channels for DMAC\n"); -+ return ret; -+ } -+ -+ tasklet_init(&dma330->tasks, dma330_dotask, (unsigned long) dma330); -+ -+ dma330->state = INIT; -+ -+ return 0; -+} -+ -+static int dmac_free_threads(struct dma330_dmac *dma330) -+{ -+ struct dma330_thread *thrd; -+ int i; -+ -+ /* Release Channel threads */ -+ for (i = 0; i < dma330->pcfg.num_chan; i++) { -+ thrd = &dma330->channels[i]; -+ dma330_release_channel(thrd); -+ } -+ -+ /* Free memory */ -+ kfree(dma330->channels); -+ -+ return 0; -+} -+ -+static void dma330_del(struct dma330_dmac *dma330) -+{ -+ dma330->state = UNINIT; -+ -+ tasklet_kill(&dma330->tasks); -+ -+ /* Free DMAC resources */ -+ dmac_free_threads(dma330); -+ -+ dma_free_coherent(dma330->ddma.dev, -+ dma330->pcfg.num_chan * dma330->mcbufsz, dma330->mcode_cpu, -+ dma330->mcode_bus); -+} -+ -+/* forward declaration */ -+static struct amba_driver iproc_dma330_driver; -+ -+static inline struct dma_dma330_chan * -+to_pchan(struct dma_chan *ch) -+{ -+ if (!ch) -+ return NULL; -+ -+ return container_of(ch, struct dma_dma330_chan, chan); -+} -+ -+static inline struct dma_dma330_desc * -+to_desc(struct dma_async_tx_descriptor *tx) -+{ -+ return container_of(tx, struct dma_dma330_desc, txd); -+} -+ -+static inline void fill_queue(struct dma_dma330_chan *pch) -+{ -+ struct dma_dma330_desc *desc; -+ int ret; -+ -+ list_for_each_entry(desc, &pch->work_list, node) { -+ -+ /* If already submitted */ -+ if (desc->status == BUSY) -+ continue; -+ -+ ret = dma330_submit_req(pch->thread, desc); -+ if (!ret) { -+ desc->status = BUSY; -+ } else if (ret == -EAGAIN) { -+ /* QFull or DMAC Dying */ -+ break; -+ } else { -+ /* Unacceptable request */ -+ desc->status = DONE; -+ dev_err(pch->dmac->ddma.dev, "%s:%d Bad Desc(%d)\n", -+ __func__, __LINE__, desc->txd.cookie); -+ tasklet_schedule(&pch->task); -+ } -+ } -+} -+ -+static void dma330_tasklet(unsigned long data) -+{ -+ struct dma_dma330_chan *pch = (struct dma_dma330_chan *)data; -+ struct dma_dma330_desc *desc, *_dt; -+ unsigned long flags; -+ bool power_down = false; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ /* Pick up ripe tomatoes */ -+ list_for_each_entry_safe(desc, _dt, &pch->work_list, node) -+ if (desc->status == DONE) { -+ if (!pch->cyclic) -+ dma_cookie_complete(&desc->txd); -+ list_move_tail(&desc->node, &pch->completed_list); -+ } -+ -+ /* Try to submit a req imm. next to the last completed cookie */ -+ fill_queue(pch); -+ -+ if (list_empty(&pch->work_list)) { -+ spin_lock(&pch->thread->dmac->lock); -+ _stop(pch->thread); -+ spin_unlock(&pch->thread->dmac->lock); -+ power_down = true; -+ } else { -+ /* Make sure the DMA330 Channel thread is active */ -+ spin_lock(&pch->thread->dmac->lock); -+ _start(pch->thread); -+ spin_unlock(&pch->thread->dmac->lock); -+ } -+ -+ while (!list_empty(&pch->completed_list)) { -+ dma_async_tx_callback callback; -+ void *callback_param; -+ -+ desc = list_first_entry(&pch->completed_list, -+ struct dma_dma330_desc, node); -+ -+ callback = desc->txd.callback; -+ callback_param = desc->txd.callback_param; -+ -+ if (pch->cyclic) { -+ desc->status = PREP; -+ list_move_tail(&desc->node, &pch->work_list); -+ if (power_down) { -+ spin_lock(&pch->thread->dmac->lock); -+ _start(pch->thread); -+ spin_unlock(&pch->thread->dmac->lock); -+ power_down = false; -+ } -+ } else { -+ desc->status = FREE; -+ list_move_tail(&desc->node, &pch->dmac->desc_pool); -+ } -+ -+ dma_descriptor_unmap(&desc->txd); -+ -+ if (callback) { -+ spin_unlock_irqrestore(&pch->lock, flags); -+ callback(callback_param); -+ spin_lock_irqsave(&pch->lock, flags); -+ } -+ } -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+ /* If work list empty, power down */ -+ if (power_down) { -+ pm_runtime_mark_last_busy(pch->dmac->ddma.dev); -+ pm_runtime_put_autosuspend(pch->dmac->ddma.dev); -+ } -+} -+ -+bool dma330_filter(struct dma_chan *chan, void *param) -+{ -+ u8 *peri_id; -+ -+ if (chan->device->dev->driver != &iproc_dma330_driver.drv) -+ return false; -+ -+ peri_id = chan->private; -+ return *peri_id == (unsigned long)param; -+} -+EXPORT_SYMBOL(dma330_filter); -+ -+static struct dma_chan *of_dma_dma330_xlate(struct of_phandle_args *dma_spec, -+ struct of_dma *ofdma) -+{ -+ int count = dma_spec->args_count; -+ struct dma330_dmac *dma330 = ofdma->of_dma_data; -+ unsigned int chan_id; -+ -+ if (!dma330) -+ return NULL; -+ -+ if (count != 1) -+ return NULL; -+ -+ chan_id = dma_spec->args[0]; -+ if (chan_id >= dma330->num_peripherals) -+ return NULL; -+ -+ return dma_get_slave_channel(&dma330->peripherals[chan_id].chan); -+} -+ -+static int dma330_alloc_chan_resources(struct dma_chan *chan) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct dma330_dmac *dma330 = pch->dmac; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ dma_cookie_init(chan); -+ pch->cyclic = false; -+ -+ pch->thread = dma330_request_channel(dma330); -+ if (!pch->thread) { -+ spin_unlock_irqrestore(&pch->lock, flags); -+ return -ENOMEM; -+ } -+ -+ tasklet_init(&pch->task, dma330_tasklet, (unsigned long) pch); -+ -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+ return 1; -+} -+ -+static int dma330_config(struct dma_chan *chan, -+ struct dma_slave_config *slave_config) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ -+ if (slave_config->direction == DMA_MEM_TO_DEV) { -+ if (slave_config->dst_addr) -+ pch->fifo_addr = slave_config->dst_addr; -+ if (slave_config->dst_addr_width) -+ pch->burst_sz = __ffs(slave_config->dst_addr_width); -+ if (slave_config->dst_maxburst) -+ pch->burst_len = slave_config->dst_maxburst; -+ } else if (slave_config->direction == DMA_DEV_TO_MEM) { -+ if (slave_config->src_addr) -+ pch->fifo_addr = slave_config->src_addr; -+ if (slave_config->src_addr_width) -+ pch->burst_sz = __ffs(slave_config->src_addr_width); -+ if (slave_config->src_maxburst) -+ pch->burst_len = slave_config->src_maxburst; -+ } -+ -+ return 0; -+} -+ -+static int dma330_terminate_all(struct dma_chan *chan) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct dma_dma330_desc *desc; -+ unsigned long flags; -+ struct dma330_dmac *dma330 = pch->dmac; -+ LIST_HEAD(list); -+ -+ pm_runtime_get_sync(dma330->ddma.dev); -+ spin_lock_irqsave(&pch->lock, flags); -+ spin_lock(&dma330->lock); -+ _stop(pch->thread); -+ spin_unlock(&dma330->lock); -+ -+ pch->thread->req[0].desc = NULL; -+ pch->thread->req[1].desc = NULL; -+ pch->thread->req_running = -1; -+ -+ /* Mark all desc done */ -+ list_for_each_entry(desc, &pch->submitted_list, node) { -+ desc->status = FREE; -+ dma_cookie_complete(&desc->txd); -+ } -+ -+ list_for_each_entry(desc, &pch->work_list , node) { -+ desc->status = FREE; -+ dma_cookie_complete(&desc->txd); -+ } -+ -+ list_splice_tail_init(&pch->submitted_list, &dma330->desc_pool); -+ list_splice_tail_init(&pch->work_list, &dma330->desc_pool); -+ list_splice_tail_init(&pch->completed_list, &dma330->desc_pool); -+ spin_unlock_irqrestore(&pch->lock, flags); -+ pm_runtime_mark_last_busy(dma330->ddma.dev); -+ pm_runtime_put_autosuspend(dma330->ddma.dev); -+ -+ return 0; -+} -+ -+/* -+ * We don't support DMA_RESUME command because of hardware -+ * limitations, so after pausing the channel we cannot restore -+ * it to active state. We have to terminate channel and setup -+ * DMA transfer again. This pause feature was implemented to -+ * allow safely read residue before channel termination. -+ */ -+static int dma330_pause(struct dma_chan *chan) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct dma330_dmac *dma330 = pch->dmac; -+ unsigned long flags; -+ -+ pm_runtime_get_sync(dma330->ddma.dev); -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ spin_lock(&dma330->lock); -+ _stop(pch->thread); -+ spin_unlock(&dma330->lock); -+ -+ spin_unlock_irqrestore(&pch->lock, flags); -+ pm_runtime_mark_last_busy(dma330->ddma.dev); -+ pm_runtime_put_autosuspend(dma330->ddma.dev); -+ -+ return 0; -+} -+ -+static void dma330_free_chan_resources(struct dma_chan *chan) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ unsigned long flags; -+ -+ tasklet_kill(&pch->task); -+ -+ pm_runtime_get_sync(pch->dmac->ddma.dev); -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ dma330_release_channel(pch->thread); -+ pch->thread = NULL; -+ -+ if (pch->cyclic) -+ list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); -+ -+ spin_unlock_irqrestore(&pch->lock, flags); -+ pm_runtime_mark_last_busy(pch->dmac->ddma.dev); -+ pm_runtime_put_autosuspend(pch->dmac->ddma.dev); -+} -+ -+static int dma330_get_current_xferred_count(struct dma_dma330_chan *pch, -+ struct dma_dma330_desc *desc) -+{ -+ struct dma330_thread *thrd = pch->thread; -+ struct dma330_dmac *dma330 = pch->dmac; -+ void __iomem *regs = thrd->dmac->base; -+ u32 val, addr; -+ -+ pm_runtime_get_sync(dma330->ddma.dev); -+ val = addr = 0; -+ if (desc->rqcfg.src_inc) { -+ val = readl(regs + SA(thrd->id)); -+ addr = desc->px.src_addr; -+ } else { -+ val = readl(regs + DA(thrd->id)); -+ addr = desc->px.dst_addr; -+ } -+ pm_runtime_mark_last_busy(pch->dmac->ddma.dev); -+ pm_runtime_put_autosuspend(dma330->ddma.dev); -+ return val - addr; -+} -+ -+static enum dma_status -+dma330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, -+ struct dma_tx_state *txstate) -+{ -+ enum dma_status ret; -+ unsigned long flags; -+ struct dma_dma330_desc *desc, *running = NULL; -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ unsigned int transferred, residual = 0; -+ -+ ret = dma_cookie_status(chan, cookie, txstate); -+ -+ if (!txstate) -+ return ret; -+ -+ if (ret == DMA_COMPLETE) -+ goto out; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ if (pch->thread->req_running != -1) -+ running = pch->thread->req[pch->thread->req_running].desc; -+ -+ /* Check in pending list */ -+ list_for_each_entry(desc, &pch->work_list, node) { -+ if (desc->status == DONE) -+ transferred = desc->bytes_requested; -+ else if (running && desc == running) -+ transferred = -+ dma330_get_current_xferred_count(pch, desc); -+ else -+ transferred = 0; -+ residual += desc->bytes_requested - transferred; -+ if (desc->txd.cookie == cookie) { -+ switch (desc->status) { -+ case DONE: -+ ret = DMA_COMPLETE; -+ break; -+ case PREP: -+ case BUSY: -+ ret = DMA_IN_PROGRESS; -+ break; -+ default: -+ WARN_ON(1); -+ } -+ break; -+ } -+ if (desc->last) -+ residual = 0; -+ } -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+out: -+ dma_set_residue(txstate, residual); -+ -+ return ret; -+} -+ -+static void dma330_issue_pending(struct dma_chan *chan) -+{ -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ if (list_empty(&pch->work_list)) { -+ /* -+ * Warn on nothing pending. Empty submitted_list may -+ * break our pm_runtime usage counter as it is -+ * updated on work_list emptiness status. -+ */ -+ WARN_ON(list_empty(&pch->submitted_list)); -+ pm_runtime_get_sync(pch->dmac->ddma.dev); -+ } -+ list_splice_tail_init(&pch->submitted_list, &pch->work_list); -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+ dma330_tasklet((unsigned long)pch); -+} -+ -+/* -+ * We returned the last one of the circular list of descriptor(s) -+ * from prep_xxx, so the argument to submit corresponds to the last -+ * descriptor of the list. -+ */ -+static dma_cookie_t dma330_tx_submit(struct dma_async_tx_descriptor *tx) -+{ -+ struct dma_dma330_desc *desc, *last = to_desc(tx); -+ struct dma_dma330_chan *pch = to_pchan(tx->chan); -+ dma_cookie_t cookie; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pch->lock, flags); -+ -+ /* Assign cookies to all nodes */ -+ while (!list_empty(&last->node)) { -+ desc = list_entry(last->node.next, struct dma_dma330_desc, node); -+ if (pch->cyclic) { -+ desc->txd.callback = last->txd.callback; -+ desc->txd.callback_param = last->txd.callback_param; -+ } -+ desc->last = false; -+ -+ dma_cookie_assign(&desc->txd); -+ -+ list_move_tail(&desc->node, &pch->submitted_list); -+ } -+ -+ last->last = true; -+ cookie = dma_cookie_assign(&last->txd); -+ list_add_tail(&last->node, &pch->submitted_list); -+ spin_unlock_irqrestore(&pch->lock, flags); -+ -+ return cookie; -+} -+ -+static inline void _init_desc(struct dma_dma330_desc *desc) -+{ -+#ifdef __LITTLE_ENDIAN -+ desc->rqcfg.swap = SWAP_NO; -+#else -+ desc->rqcfg.swap = SWAP_4; -+#endif /* __LITTLE_ENDIAN */ -+ desc->rqcfg.scctl = CCTRL0; -+ desc->rqcfg.dcctl = CCTRL0; -+ desc->txd.tx_submit = dma330_tx_submit; -+ -+ INIT_LIST_HEAD(&desc->node); -+} -+ -+/* Returns the number of descriptors added to the DMAC pool */ -+static int add_desc(struct dma330_dmac *dma330, gfp_t flg, int count) -+{ -+ struct dma_dma330_desc *desc; -+ unsigned long flags; -+ int i; -+ -+ desc = kcalloc(count, sizeof(*desc), flg); -+ if (!desc) -+ return 0; -+ -+ spin_lock_irqsave(&dma330->pool_lock, flags); -+ -+ for (i = 0; i < count; i++) { -+ _init_desc(&desc[i]); -+ list_add_tail(&desc[i].node, &dma330->desc_pool); -+ } -+ -+ spin_unlock_irqrestore(&dma330->pool_lock, flags); -+ -+ return count; -+} -+ -+static struct dma_dma330_desc *pluck_desc(struct dma330_dmac *dma330) -+{ -+ struct dma_dma330_desc *desc = NULL; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dma330->pool_lock, flags); -+ -+ if (!list_empty(&dma330->desc_pool)) { -+ desc = list_entry(dma330->desc_pool.next, -+ struct dma_dma330_desc, node); -+ -+ list_del_init(&desc->node); -+ -+ desc->status = PREP; -+ desc->txd.callback = NULL; -+ } -+ -+ spin_unlock_irqrestore(&dma330->pool_lock, flags); -+ -+ return desc; -+} -+ -+static struct dma_dma330_desc *dma330_get_desc(struct dma_dma330_chan *pch) -+{ -+ struct dma330_dmac *dma330 = pch->dmac; -+ u8 *peri_id = pch->chan.private; -+ struct dma_dma330_desc *desc; -+ -+ /* Pluck one desc from the pool of DMAC */ -+ desc = pluck_desc(dma330); -+ -+ /* If the DMAC pool is empty, alloc new */ -+ if (!desc) { -+ if (!add_desc(dma330, GFP_ATOMIC, 1)) -+ return NULL; -+ -+ /* Try again */ -+ desc = pluck_desc(dma330); -+ if (!desc) { -+ dev_err(pch->dmac->ddma.dev, -+ "%s:%d ALERT!\n", __func__, __LINE__); -+ return NULL; -+ } -+ } -+ -+ /* Initialize the descriptor */ -+ desc->pchan = pch; -+ desc->txd.cookie = 0; -+ async_tx_ack(&desc->txd); -+ -+ desc->peri = peri_id ? pch->chan.chan_id : 0; -+ desc->rqcfg.pcfg = &pch->dmac->pcfg; -+ -+ dma_async_tx_descriptor_init(&desc->txd, &pch->chan); -+ -+ return desc; -+} -+ -+static inline void fill_px(struct dma330_xfer *px, -+ dma_addr_t dst, dma_addr_t src, size_t len) -+{ -+ px->bytes = len; -+ px->dst_addr = dst; -+ px->src_addr = src; -+} -+ -+static struct dma_dma330_desc * -+__dma330_prep_dma_memcpy(struct dma_dma330_chan *pch, dma_addr_t dst, -+ dma_addr_t src, size_t len) -+{ -+ struct dma_dma330_desc *desc = dma330_get_desc(pch); -+ -+ if (!desc) { -+ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n", -+ __func__, __LINE__); -+ return NULL; -+ } -+ -+ /* -+ * Ideally we should lookout for reqs bigger than -+ * those that can be programmed with 256 bytes of -+ * MC buffer, but considering a req size is seldom -+ * going to be word-unaligned and more than 200MB, -+ * we take it easy. -+ * Also, should the limit is reached we'd rather -+ * have the platform increase MC buffer size than -+ * complicating this API driver. -+ */ -+ fill_px(&desc->px, dst, src, len); -+ -+ return desc; -+} -+ -+/* Call after fixing burst size */ -+static inline int get_burst_len(struct dma_dma330_desc *desc, size_t len) -+{ -+ struct dma_dma330_chan *pch = desc->pchan; -+ struct dma330_dmac *dma330 = pch->dmac; -+ int burst_len; -+ -+ burst_len = dma330->pcfg.data_bus_width / 8; -+ burst_len *= dma330->pcfg.data_buf_dep / dma330->pcfg.num_chan; -+ burst_len >>= desc->rqcfg.brst_size; -+ -+ /* src/dst_burst_len can't be more than 16 */ -+ if (burst_len > 16) -+ burst_len = 16; -+ -+ while (burst_len > 1) { -+ if (!(len % (burst_len << desc->rqcfg.brst_size))) -+ break; -+ burst_len--; -+ } -+ -+ return burst_len; -+} -+ -+static struct dma_async_tx_descriptor *dma330_prep_dma_cyclic( -+ struct dma_chan *chan, dma_addr_t dma_addr, size_t len, -+ size_t period_len, enum dma_transfer_direction direction, -+ unsigned long flags) -+{ -+ struct dma_dma330_desc *desc = NULL, *first = NULL; -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct dma330_dmac *dma330 = pch->dmac; -+ unsigned int i; -+ dma_addr_t dst; -+ dma_addr_t src; -+ -+ if (len % period_len != 0) -+ return NULL; -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(pch->dmac->ddma.dev, "%s:%d Invalid dma direction\n", -+ __func__, __LINE__); -+ return NULL; -+ } -+ -+ for (i = 0; i < len / period_len; i++) { -+ desc = dma330_get_desc(pch); -+ if (!desc) { -+ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n", -+ __func__, __LINE__); -+ -+ if (!first) -+ return NULL; -+ -+ spin_lock_irqsave(&dma330->pool_lock, flags); -+ -+ while (!list_empty(&first->node)) { -+ desc = list_entry(first->node.next, -+ struct dma_dma330_desc, node); -+ list_move_tail(&desc->node, &dma330->desc_pool); -+ } -+ -+ list_move_tail(&first->node, &dma330->desc_pool); -+ -+ spin_unlock_irqrestore(&dma330->pool_lock, flags); -+ -+ return NULL; -+ } -+ -+ switch (direction) { -+ case DMA_MEM_TO_DEV: -+ desc->rqcfg.src_inc = 1; -+ desc->rqcfg.dst_inc = 0; -+ src = dma_addr; -+ dst = pch->fifo_addr; -+ break; -+ case DMA_DEV_TO_MEM: -+ desc->rqcfg.src_inc = 0; -+ desc->rqcfg.dst_inc = 1; -+ src = pch->fifo_addr; -+ dst = dma_addr; -+ break; -+ default: -+ break; -+ } -+ -+ desc->rqtype = direction; -+ desc->rqcfg.brst_size = pch->burst_sz; -+ desc->rqcfg.brst_len = pch->burst_len; -+ desc->bytes_requested = period_len; -+ fill_px(&desc->px, dst, src, period_len); -+ -+ if (!first) -+ first = desc; -+ else -+ list_add_tail(&desc->node, &first->node); -+ -+ dma_addr += period_len; -+ } -+ -+ if (!desc) -+ return NULL; -+ -+ pch->cyclic = true; -+ desc->txd.flags = flags; -+ -+ return &desc->txd; -+} -+ -+static struct dma_async_tx_descriptor * -+dma330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, -+ dma_addr_t src, size_t len, unsigned long flags) -+{ -+ struct dma_dma330_desc *desc; -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct dma330_dmac *dma330; -+ int burst; -+ -+ if (unlikely(!pch || !len)) -+ return NULL; -+ -+ dma330 = pch->dmac; -+ -+ desc = __dma330_prep_dma_memcpy(pch, dst, src, len); -+ if (!desc) -+ return NULL; -+ -+ desc->rqcfg.src_inc = 1; -+ desc->rqcfg.dst_inc = 1; -+ desc->rqtype = DMA_MEM_TO_MEM; -+ -+ /* Select max possible burst size */ -+ burst = dma330->pcfg.data_bus_width / 8; -+ -+ /* -+ * Make sure we use a burst size that aligns with all the memcpy -+ * parameters because our DMA programming algorithm doesn't cope with -+ * transfers which straddle an entry in the DMA device's MFIFO. -+ */ -+ while ((src | dst | len) & (burst - 1)) -+ burst /= 2; -+ -+ desc->rqcfg.brst_size = 0; -+ while (burst != (1 << desc->rqcfg.brst_size)) -+ desc->rqcfg.brst_size++; -+ -+ /* -+ * If burst size is smaller than bus width then make sure we only -+ * transfer one at a time to avoid a burst stradling an MFIFO entry. -+ */ -+ if (desc->rqcfg.brst_size * 8 < dma330->pcfg.data_bus_width) -+ desc->rqcfg.brst_len = 1; -+ -+ desc->rqcfg.brst_len = get_burst_len(desc, len); -+ desc->bytes_requested = len; -+ -+ desc->txd.flags = flags; -+ -+ return &desc->txd; -+} -+ -+static void __dma330_giveback_desc(struct dma330_dmac *dma330, -+ struct dma_dma330_desc *first) -+{ -+ unsigned long flags; -+ struct dma_dma330_desc *desc; -+ -+ if (!first) -+ return; -+ -+ spin_lock_irqsave(&dma330->pool_lock, flags); -+ -+ while (!list_empty(&first->node)) { -+ desc = list_entry(first->node.next, -+ struct dma_dma330_desc, node); -+ list_move_tail(&desc->node, &dma330->desc_pool); -+ } -+ -+ list_move_tail(&first->node, &dma330->desc_pool); -+ -+ spin_unlock_irqrestore(&dma330->pool_lock, flags); -+} -+ -+static struct dma_async_tx_descriptor * -+dma330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, -+ unsigned int sg_len, enum dma_transfer_direction direction, -+ unsigned long flg, void *context) -+{ -+ struct dma_dma330_desc *first, *desc = NULL; -+ struct dma_dma330_chan *pch = to_pchan(chan); -+ struct scatterlist *sg; -+ int i; -+ dma_addr_t addr; -+ -+ if (unlikely(!pch || !sgl || !sg_len)) -+ return NULL; -+ -+ addr = pch->fifo_addr; -+ -+ first = NULL; -+ -+ for_each_sg(sgl, sg, sg_len, i) { -+ -+ desc = dma330_get_desc(pch); -+ if (!desc) { -+ struct dma330_dmac *dma330 = pch->dmac; -+ -+ dev_err(pch->dmac->ddma.dev, -+ "%s:%d Unable to fetch desc\n", -+ __func__, __LINE__); -+ __dma330_giveback_desc(dma330, first); -+ -+ return NULL; -+ } -+ -+ if (!first) -+ first = desc; -+ else -+ list_add_tail(&desc->node, &first->node); -+ -+ if (direction == DMA_MEM_TO_DEV) { -+ desc->rqcfg.src_inc = 1; -+ desc->rqcfg.dst_inc = 0; -+ fill_px(&desc->px, -+ addr, sg_dma_address(sg), sg_dma_len(sg)); -+ } else { -+ desc->rqcfg.src_inc = 0; -+ desc->rqcfg.dst_inc = 1; -+ fill_px(&desc->px, -+ sg_dma_address(sg), addr, sg_dma_len(sg)); -+ } -+ -+ desc->rqcfg.brst_size = pch->burst_sz; -+ desc->rqcfg.brst_len = pch->burst_len; -+ desc->rqtype = direction; -+ desc->bytes_requested = sg_dma_len(sg); -+ } -+ -+ /* Return the last desc in the chain */ -+ desc->txd.flags = flg; -+ return &desc->txd; -+} -+ -+static irqreturn_t dma330_irq_handler(int irq, void *data) -+{ -+ if (dma330_update(data)) -+ return IRQ_HANDLED; -+ else -+ return IRQ_NONE; -+} -+ -+#define DMA330_DMA_BUSWIDTHS \ -+ BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \ -+ BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ -+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ -+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ -+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES) -+ -+/* -+ * Runtime PM callbacks are provided by amba/bus.c driver. -+ * -+ * It is assumed here that IRQ safe runtime PM is chosen in probe and amba -+ * bus driver will only disable/enable the clock in runtime PM callbacks. -+ */ -+static int __maybe_unused iproc_dma330_suspend(struct device *dev) -+{ -+ struct amba_device *pcdev = to_amba_device(dev); -+ -+ pm_runtime_disable(dev); -+ -+ if (!pm_runtime_status_suspended(dev)) { -+ /* amba did not disable the clock */ -+ amba_pclk_disable(pcdev); -+ } -+ amba_pclk_unprepare(pcdev); -+ -+ return 0; -+} -+ -+static int __maybe_unused iproc_dma330_resume(struct device *dev) -+{ -+ struct amba_device *pcdev = to_amba_device(dev); -+ int ret; -+ -+ ret = amba_pclk_prepare(pcdev); -+ if (ret) -+ return ret; -+ -+ if (!pm_runtime_status_suspended(dev)) -+ ret = amba_pclk_enable(pcdev); -+ -+ pm_runtime_enable(dev); -+ -+ return ret; -+} -+ -+static SIMPLE_DEV_PM_OPS(iproc_dma330_pm, iproc_dma330_suspend, iproc_dma330_resume); -+ -+static int -+iproc_dma330_probe(struct amba_device *adev, const struct amba_id *id) -+{ -+ struct dma_dma330_platdata *pdat; -+ struct dma330_config *pcfg; -+ struct dma330_dmac *dma330; -+ struct dma_dma330_chan *pch, *_p; -+ struct dma_device *pd; -+ struct resource *res; -+ int i, ret, irq; -+ int num_chan; -+ -+ pdat = dev_get_platdata(&adev->dev); -+ -+ ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32)); -+ if (ret) -+ return ret; -+ -+ /* Allocate a new DMAC and its Channels */ -+ dma330 = devm_kzalloc(&adev->dev, sizeof(*dma330), GFP_KERNEL); -+ if (!dma330) { -+ dev_err(&adev->dev, "unable to allocate mem\n"); -+ return -ENOMEM; -+ } -+ -+ pd = &dma330->ddma; -+ pd->dev = &adev->dev; -+ -+ dma330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; -+ -+ res = &adev->res; -+ dma330->base = devm_ioremap_resource(&adev->dev, res); -+ if (IS_ERR(dma330->base)) -+ return PTR_ERR(dma330->base); -+ -+ amba_set_drvdata(adev, dma330); -+ -+ for (i = 0; i < AMBA_NR_IRQS; i++) { -+ irq = adev->irq[i]; -+ if (irq) { -+ ret = devm_request_irq(&adev->dev, irq, -+ dma330_irq_handler, 0, -+ dev_name(&adev->dev), dma330); -+ if (ret) -+ return ret; -+ } else { -+ break; -+ } -+ } -+ -+ pcfg = &dma330->pcfg; -+ -+ pcfg->periph_id = adev->periphid; -+ ret = dma330_add(dma330); -+ if (ret) -+ return ret; -+ -+ INIT_LIST_HEAD(&dma330->desc_pool); -+ spin_lock_init(&dma330->pool_lock); -+ -+ /* Create a descriptor pool of default size */ -+ if (!add_desc(dma330, GFP_KERNEL, NR_DEFAULT_DESC)) -+ dev_warn(&adev->dev, "unable to allocate desc\n"); -+ -+ INIT_LIST_HEAD(&pd->channels); -+ -+ /* Initialize channel parameters */ -+ if (pdat) -+ num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan); -+ else -+ num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan); -+ -+ dma330->num_peripherals = num_chan; -+ -+ dma330->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); -+ if (!dma330->peripherals) { -+ ret = -ENOMEM; -+ dev_err(&adev->dev, "unable to allocate dma330->peripherals\n"); -+ goto probe_err2; -+ } -+ -+ for (i = 0; i < num_chan; i++) { -+ pch = &dma330->peripherals[i]; -+ if (!adev->dev.of_node) -+ pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; -+ else -+ pch->chan.private = adev->dev.of_node; -+ -+ INIT_LIST_HEAD(&pch->submitted_list); -+ INIT_LIST_HEAD(&pch->work_list); -+ INIT_LIST_HEAD(&pch->completed_list); -+ spin_lock_init(&pch->lock); -+ pch->thread = NULL; -+ pch->chan.device = pd; -+ pch->dmac = dma330; -+ -+ /* Add the channel to the DMAC list */ -+ list_add_tail(&pch->chan.device_node, &pd->channels); -+ } -+ -+ if (pdat) { -+ pd->cap_mask = pdat->cap_mask; -+ } else { -+ dma_cap_set(DMA_MEMCPY, pd->cap_mask); -+ if (pcfg->num_peri) { -+ dma_cap_set(DMA_SLAVE, pd->cap_mask); -+ dma_cap_set(DMA_CYCLIC, pd->cap_mask); -+ dma_cap_set(DMA_PRIVATE, pd->cap_mask); -+ } -+ } -+ -+ pd->device_alloc_chan_resources = dma330_alloc_chan_resources; -+ pd->device_free_chan_resources = dma330_free_chan_resources; -+ pd->device_prep_dma_memcpy = dma330_prep_dma_memcpy; -+ pd->device_prep_dma_cyclic = dma330_prep_dma_cyclic; -+ pd->device_tx_status = dma330_tx_status; -+ pd->device_prep_slave_sg = dma330_prep_slave_sg; -+ pd->device_config = dma330_config; -+ pd->device_pause = dma330_pause; -+ pd->device_terminate_all = dma330_terminate_all; -+ pd->device_issue_pending = dma330_issue_pending; -+ pd->src_addr_widths = DMA330_DMA_BUSWIDTHS; -+ pd->dst_addr_widths = DMA330_DMA_BUSWIDTHS; -+ pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ pd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; -+ -+ ret = dma_async_device_register(pd); -+ if (ret) { -+ dev_err(&adev->dev, "unable to register DMAC\n"); -+ goto probe_err3; -+ } -+ -+ if (adev->dev.of_node) { -+ ret = of_dma_controller_register(adev->dev.of_node, -+ of_dma_dma330_xlate, dma330); -+ if (ret) { -+ dev_err(&adev->dev, -+ "unable to register DMA to the generic DT DMA helpers\n"); -+ } -+ } -+ -+ adev->dev.dma_parms = &dma330->dma_parms; -+ -+ /* -+ * This is the limit for transfers with a buswidth of 1, larger -+ * buswidths will have larger limits. -+ */ -+ ret = dma_set_max_seg_size(&adev->dev, 1900800); -+ if (ret) -+ dev_err(&adev->dev, "unable to set the seg size\n"); -+ -+ -+ dev_info(&adev->dev, -+ "Loaded driver for DMA330 DMAC-%x\n", adev->periphid); -+ dev_info(&adev->dev, -+ "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", -+ pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan, -+ pcfg->num_peri, pcfg->num_events); -+ -+ pm_runtime_irq_safe(&adev->dev); -+ pm_runtime_use_autosuspend(&adev->dev); -+ pm_runtime_set_autosuspend_delay(&adev->dev, DMA330_AUTOSUSPEND_DELAY); -+ pm_runtime_mark_last_busy(&adev->dev); -+ pm_runtime_put_autosuspend(&adev->dev); -+ -+ return 0; -+probe_err3: -+ /* Idle the DMAC */ -+ list_for_each_entry_safe(pch, _p, &dma330->ddma.channels, -+ chan.device_node) { -+ -+ /* Remove the channel */ -+ list_del(&pch->chan.device_node); -+ -+ /* Flush the channel */ -+ if (pch->thread) { -+ dma330_terminate_all(&pch->chan); -+ dma330_free_chan_resources(&pch->chan); -+ } -+ } -+probe_err2: -+ dma330_del(dma330); -+ -+ return ret; -+} -+ -+static int iproc_dma330_remove(struct amba_device *adev) -+{ -+ struct dma330_dmac *dma330 = amba_get_drvdata(adev); -+ struct dma_dma330_chan *pch, *_p; -+ -+ pm_runtime_get_noresume(dma330->ddma.dev); -+ -+ if (adev->dev.of_node) -+ of_dma_controller_free(adev->dev.of_node); -+ -+ dma_async_device_unregister(&dma330->ddma); -+ -+ /* Idle the DMAC */ -+ list_for_each_entry_safe(pch, _p, &dma330->ddma.channels, -+ chan.device_node) { -+ -+ /* Remove the channel */ -+ list_del(&pch->chan.device_node); -+ -+ /* Flush the channel */ -+ if (pch->thread) { -+ dma330_terminate_all(&pch->chan); -+ dma330_free_chan_resources(&pch->chan); -+ } -+ } -+ -+ dma330_del(dma330); -+ -+ return 0; -+} -+ -+static struct amba_id iproc_dma330_ids[] = { -+ { -+ .id = 0x00241330, -+ .mask = 0x00ffffff, -+ }, -+ { 0, 0 }, -+}; -+ -+MODULE_DEVICE_TABLE(amba, iproc_dma330_ids); -+ -+static struct amba_driver iproc_dma330_driver = { -+ .drv = { -+ .owner = THIS_MODULE, -+ .name = "dma-dma330", -+ .pm = &iproc_dma330_pm, -+ }, -+ .id_table = iproc_dma330_ids, -+ .probe = iproc_dma330_probe, -+ .remove = iproc_dma330_remove, -+}; -+ -+module_amba_driver(iproc_dma330_driver); -+ -+MODULE_DESCRIPTION("API Driver for DMA330 DMAC"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig ---- a/drivers/gpio/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/gpio/Kconfig 2017-11-09 17:53:27.600169000 +0800 -@@ -142,6 +142,15 @@ config GPIO_BRCMSTB - help - Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. - -+config GPIO_XGS_IPROC -+ tristate "BRCM XGS iProc GPIO support" -+ default y if ARCH_XGS_IPROC -+ depends on OF_GPIO && (ARCH_XGS_IPROC || COMPILE_TEST) -+ select GPIO_GENERIC -+ select GPIOLIB_IRQCHIP -+ help -+ Say yes here to enable GPIO support for Broadcom XGS iProc SoCs. -+ - config GPIO_CLPS711X - tristate "CLPS711X GPIO support" - depends on ARCH_CLPS711X || COMPILE_TEST -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/gpio/Makefile b/drivers/gpio/Makefile ---- a/drivers/gpio/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/gpio/Makefile 2017-11-09 17:53:27.601169000 +0800 -@@ -25,6 +25,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizo - obj-$(CONFIG_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o -+obj-$(CONFIG_GPIO_XGS_IPROC) += gpio-xgs-iproc.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o - obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c ---- a/drivers/gpio/gpio-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/gpio/gpio-xgs-iproc.c 2017-11-09 17:53:27.757170000 +0800 -@@ -0,0 +1,815 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "gpio-xgs-iproc.h" -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) -+#define irq_get_chip_data get_irq_chip_data -+#define irq_set_chip_data set_irq_chip_data -+#define irq_set_chip set_irq_chip -+#define irq_set_handler set_irq_handler -+#define status_use_accessors status -+#endif -+ -+ -+#define IPROC_CCA_INT_F_GPIOINT 1 -+#define IPROC_CCA_INT_MASK 0x24 -+#define IPROC_GPIO_CCA_DIN 0x0 -+#define IPROC_GPIO_CCA_INT_LEVEL 0x10 -+#define IPROC_GPIO_CCA_INT_LEVEL_MASK 0x14 -+#define IPROC_GPIO_CCA_INT_EVENT 0x18 -+#define IPROC_GPIO_CCA_INT_EVENT_MASK 0x1C -+#define IPROC_CCA_INT_STS 0x20 -+#define IPROC_GPIO_CCA_INT_EDGE 0x24 -+ -+#define IPROC_GPIO_CCB_INT_TYPE 0xC -+#define IPROC_GPIO_CCB_INT_DE 0x10 -+#define IPROC_GPIO_CCB_INT_EDGE 0x14 -+#define IPROC_GPIO_CCB_INT_MSTAT 0x20 -+#define IPROC_GPIO_CCB_INT_CLR 0x24 -+#define IPROC_GPIO_CCB_INT_MASK 0x18 -+ -+ -+static unsigned int _iproc_gpio_readl(struct iproc_gpio_chip *chip, int reg) -+{ -+ return readl(chip->ioaddr + reg); -+} -+ -+static void _iproc_gpio_writel(struct iproc_gpio_chip *chip, unsigned int val, int reg) -+{ -+ writel(val, chip->ioaddr + reg); -+} -+ -+ -+/* -+@ pin : the actual pin number of the gpiochip -+*/ -+static int iproc_gpio_to_irq(struct iproc_gpio_chip *chip, unsigned int pin) { -+ return irq_linear_revmap(chip->irq_domain, pin - chip->pin_offset); -+} -+ -+/* -+returns the actual pin number of the gpiochip -+*/ -+static int iproc_irq_to_gpio(struct iproc_gpio_chip *chip, unsigned int irq) { -+ struct irq_data *data = irq_domain_get_irq_data(chip->irq_domain, irq); -+ -+ return data->hwirq + chip->pin_offset; -+} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) -+static void iproc_gpio_irq_ack(unsigned int irq) -+{ -+#else -+static void iproc_gpio_irq_ack(struct irq_data *d) -+{ -+ unsigned int irq = d->irq; -+#endif -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ -+ if (ourchip) { -+ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; -+ if (irqcfg && irqcfg->ack) -+ irqcfg->ack(irq); -+ -+ } -+} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) -+static void iproc_gpio_irq_unmask(unsigned int irq) -+{ -+#else -+static void iproc_gpio_irq_unmask(struct irq_data *d) -+{ -+ unsigned int irq = d->irq; -+#endif -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ -+ if (ourchip) { -+ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; -+ if (irqcfg && irqcfg->unmask) -+ irqcfg->unmask(irq); -+ } -+} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) -+static void iproc_gpio_irq_mask(unsigned int irq) -+{ -+#else -+static void iproc_gpio_irq_mask(struct irq_data *d) -+{ -+ unsigned int irq = d->irq; -+#endif -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ -+ if (ourchip) { -+ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; -+ if (irqcfg && irqcfg->mask) -+ irqcfg->mask(irq); -+ } -+} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) -+static int iproc_gpio_irq_set_type(unsigned int irq, unsigned int type) -+{ -+#else -+static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) -+{ -+ unsigned int irq = d->irq; -+#endif -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ -+ if (ourchip) { -+ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; -+ if (irqcfg && irqcfg->set_type) -+ return irqcfg->set_type(irq, type); -+ } -+ return -EINVAL; -+} -+ -+#if defined(IPROC_GPIO_CCA) -+static irqreturn_t iproc_gpio_irq_handler_cca(int irq, void *data) -+{ -+ struct iproc_gpio_chip *iproc_gpio = (struct iproc_gpio_chip *)data; -+ struct gpio_chip gc = iproc_gpio->chip; -+ int bit; -+ unsigned long int_bits = 0; -+ u32 int_status; -+ -+ /* go through the entire GPIOs and handle all interrupts */ -+ int_status = readl(iproc_gpio->intr_ioaddr + IPROC_CCA_INT_STS); -+ if (int_status & IPROC_CCA_INT_F_GPIOINT) { -+ unsigned int event, level; -+ -+ /* Get level and edge interrupts */ -+ event = readl(iproc_gpio->ioaddr + IPROC_GPIO_CCA_INT_EVENT_MASK) & readl(iproc_gpio->ioaddr + IPROC_GPIO_CCA_INT_EVENT); -+ level = readl(iproc_gpio->ioaddr + IPROC_GPIO_CCA_DIN) ^ -+ readl(iproc_gpio->ioaddr + IPROC_GPIO_CCA_INT_LEVEL); -+ level &= readl(iproc_gpio->ioaddr + IPROC_GPIO_CCA_INT_LEVEL_MASK); -+ int_bits = level | event; -+ -+ for_each_set_bit(bit, &int_bits, gc.ngpio) -+ generic_handle_irq( -+ irq_linear_revmap(iproc_gpio->irq_domain, bit)); -+ } -+ -+ return int_bits ? IRQ_HANDLED : IRQ_NONE; -+} -+ -+ -+static void iproc_gpio_irq_ack_cca(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if (ourchip->id == IPROC_GPIO_CCA_ID) { -+ unsigned int event_status, irq_type; -+ -+ event_status = 0; -+ irq_type = irq_get_trigger_type(irq); -+ if (irq_type & IRQ_TYPE_EDGE_BOTH) -+ { -+ event_status |= (1 << pin); -+ _iproc_gpio_writel(ourchip, event_status, -+ IPROC_GPIO_CCA_INT_EVENT); -+ } -+ -+ } -+} -+ -+static void iproc_gpio_irq_unmask_cca(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ unsigned int int_mask, irq_type; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ irq_type = irq_get_trigger_type(irq); -+ -+ if (ourchip->id == IPROC_GPIO_CCA_ID) { -+ unsigned int event_mask; -+ -+ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); -+ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); -+ -+ if (irq_type & IRQ_TYPE_EDGE_BOTH) { -+ event_mask |= 1 << pin; -+ _iproc_gpio_writel(ourchip, event_mask, -+ IPROC_GPIO_CCA_INT_EVENT_MASK); -+ } else { -+ int_mask |= 1 << pin; -+ _iproc_gpio_writel(ourchip, int_mask, -+ IPROC_GPIO_CCA_INT_LEVEL_MASK); -+ } -+ } -+ -+} -+ -+static void iproc_gpio_irq_mask_cca(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ unsigned int irq_type, int_mask; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ irq_type = irq_get_trigger_type(irq); -+ -+ if (ourchip->id == IPROC_GPIO_CCA_ID) { -+ unsigned int event_mask; -+ -+ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); -+ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); -+ -+ if (irq_type & IRQ_TYPE_EDGE_BOTH) { -+ event_mask &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, event_mask, -+ IPROC_GPIO_CCA_INT_EVENT_MASK); -+ } else { -+ int_mask &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, int_mask, -+ IPROC_GPIO_CCA_INT_LEVEL_MASK); -+ } -+ } -+} -+ -+static int iproc_gpio_irq_set_type_cca(unsigned int irq, unsigned int type) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if (ourchip->id == IPROC_GPIO_CCA_ID) { -+ unsigned int event_pol, int_pol; -+ -+ switch (type & IRQ_TYPE_SENSE_MASK) { -+ case IRQ_TYPE_EDGE_RISING: -+ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); -+ event_pol &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); -+ break; -+ case IRQ_TYPE_EDGE_FALLING: -+ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); -+ event_pol |= (1 << pin); -+ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); -+ int_pol &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ int_pol = _iproc_gpio_readl(ourchip,IPROC_GPIO_CCA_INT_LEVEL); -+ int_pol |= (1 << pin); -+ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); -+ break; -+ default: -+ printk(KERN_ERR "unsupport irq type !\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq); -+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) -+ irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq); -+ -+ return 0; -+} -+ -+struct iproc_gpio_irqcfg cca_gpio_irqcfg = { -+ /* Remove IRQF_NO_SUSPEND to be consistent with 8250_core.c setting -+ * since CCA gpio and uart share the same IRQ. -+ */ -+ .flags = IRQF_SHARED, -+ .handler = iproc_gpio_irq_handler_cca, -+ .ack = iproc_gpio_irq_ack_cca, -+ .mask = iproc_gpio_irq_mask_cca, -+ .unmask = iproc_gpio_irq_unmask_cca, -+ .set_type = iproc_gpio_irq_set_type_cca, -+}; -+#endif /* IPROC_GPIO_CCA */ -+ -+#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) -+static irqreturn_t -+iproc_gpio_irq_handler_ccb(int irq, void *dev) -+{ -+ struct iproc_gpio_chip *ourchip = dev; -+ int iter, max_pin; -+ unsigned int val; -+ -+ val = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MSTAT); -+ if(!val){ -+ return IRQ_NONE; -+ } -+ -+ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; -+ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { -+ if (val & (1 << iter)) { -+ //writel(1 << iter, ourchip->ioaddr + IPROC_GPIO_CCB_INT_CLR); -+ generic_handle_irq(iproc_gpio_to_irq(ourchip, iter)); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void iproc_gpio_irq_ack_ccb(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if ((ourchip->id == IPROC_GPIO_CCB_ID) || -+ (ourchip->id == IPROC_GPIO_CCG_ID)) { -+ unsigned int int_clear = 0; -+ -+ int_clear |= (1 << pin); -+ _iproc_gpio_writel(ourchip, int_clear, IPROC_GPIO_CCB_INT_CLR); -+ -+ } -+} -+ -+static void iproc_gpio_irq_unmask_ccb(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ unsigned int int_mask; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if ((ourchip->id == IPROC_GPIO_CCB_ID) || -+ (ourchip->id == IPROC_GPIO_CCG_ID)) { -+ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); -+ int_mask |= (1 << pin); -+ _iproc_gpio_writel(ourchip, int_mask, IPROC_GPIO_CCB_INT_MASK); -+ } -+ -+} -+ -+static void iproc_gpio_irq_mask_ccb(unsigned int irq) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ unsigned int int_mask; -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if ((ourchip->id == IPROC_GPIO_CCB_ID) || -+ (ourchip->id == IPROC_GPIO_CCG_ID)) { -+ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); -+ int_mask &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, int_mask,IPROC_GPIO_CCB_INT_MASK); -+ } -+} -+ -+static int iproc_gpio_irq_set_type_ccb(unsigned int irq, unsigned int type) -+{ -+ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); -+ int pin; -+ -+ -+ pin = iproc_irq_to_gpio(ourchip, irq); -+ -+ if ((ourchip->id == IPROC_GPIO_CCB_ID) || -+ (ourchip->id == IPROC_GPIO_CCG_ID)) { -+ unsigned int int_type, int_de, int_edge; -+ int_type = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_TYPE); -+ int_edge = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_EDGE); -+ switch (type) { -+ case IRQ_TYPE_EDGE_BOTH: -+ int_type &= ~(1 << pin); -+ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); -+ int_de |= (1 << pin); -+ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); -+ break; -+ case IRQ_TYPE_EDGE_RISING: -+ int_type &= ~(1 << pin); -+ int_edge |= (1 << pin); -+ -+ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); -+ int_de &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); -+ break; -+ case IRQ_TYPE_EDGE_FALLING: -+ int_type &= ~(1 << pin); -+ int_edge &= ~(1 << pin); -+ -+ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); -+ int_de &= ~(1 << pin); -+ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ int_type |= (1 << pin); -+ int_edge |= (1 << pin); -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ int_type |= (1 << pin); -+ int_edge &= ~(1 << pin); -+ break; -+ default: -+ printk(KERN_ERR "unsupport irq type !\n"); -+ return -EINVAL; -+ } -+ _iproc_gpio_writel(ourchip, int_type, IPROC_GPIO_CCB_INT_TYPE); -+ _iproc_gpio_writel(ourchip, int_edge, IPROC_GPIO_CCB_INT_EDGE); -+ } -+ -+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq); -+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) -+ irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq); -+ -+ return 0; -+} -+ -+struct iproc_gpio_irqcfg ccb_gpio_irqcfg = { -+ .flags = IRQF_NO_SUSPEND, -+ .handler = iproc_gpio_irq_handler_ccb, -+ .ack = iproc_gpio_irq_ack_ccb, -+ .mask = iproc_gpio_irq_mask_ccb, -+ .unmask = iproc_gpio_irq_unmask_ccb, -+ .set_type = iproc_gpio_irq_set_type_ccb, -+}; -+#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG*/ -+ -+static struct irq_chip iproc_gpio_irq_chip = { -+ .name = "IPROC-GPIO", -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) -+ .ack = (void *) iproc_gpio_irq_ack, -+ .mask = (void *) iproc_gpio_irq_mask, -+ .unmask = (void *) iproc_gpio_irq_unmask, -+ .set_type = (void *) iproc_gpio_irq_set_type, -+#else -+ .irq_ack = (void *) iproc_gpio_irq_ack, -+ .irq_mask = (void *) iproc_gpio_irq_mask, -+ .irq_unmask = (void *) iproc_gpio_irq_unmask, -+ .irq_set_type = (void *) iproc_gpio_irq_set_type, -+#endif -+}; -+ -+ -+static int iproc_gpiolib_input(struct gpio_chip *chip, unsigned gpio) -+{ -+ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); -+ unsigned long flags; -+ unsigned int val, nBitMask; -+ int reg_offset; -+ unsigned int pin_offset = gpio + ourchip->pin_offset; -+ -+ iproc_gpio_lock(ourchip, flags); -+ -+ nBitMask = 1 << pin_offset; -+ reg_offset = REGOFFSET_GPIO_EN; -+ -+ val = _iproc_gpio_readl(ourchip, reg_offset); -+ val &= ~nBitMask; -+ _iproc_gpio_writel(ourchip, val, reg_offset); -+ -+ iproc_gpio_unlock(ourchip, flags); -+ return 0; -+} -+ -+static int iproc_gpiolib_output(struct gpio_chip *chip, -+ unsigned gpio, int value) -+{ -+ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); -+ unsigned long flags, val; -+ unsigned int nBitMask; -+ int reg_offset; -+ unsigned int pin_offset = gpio + ourchip->pin_offset; -+ -+ iproc_gpio_lock(ourchip, flags); -+ -+ nBitMask = 1 << pin_offset; -+ reg_offset = REGOFFSET_GPIO_EN; -+ -+ val = _iproc_gpio_readl(ourchip, reg_offset); -+ val |= nBitMask; -+ _iproc_gpio_writel(ourchip, val, reg_offset); -+ -+ iproc_gpio_unlock(ourchip, flags); -+ return 0; -+} -+ -+static void iproc_gpiolib_set(struct gpio_chip *chip, -+ unsigned gpio, int value) -+{ -+ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); -+ unsigned long flags, val; -+ unsigned int nBitMask; -+ int reg_offset = 0; -+ unsigned int pin_offset = gpio + ourchip->pin_offset; -+ -+ iproc_gpio_lock(ourchip, flags); -+ -+ nBitMask = 1 << pin_offset; -+ -+ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN + reg_offset); -+ val &= nBitMask; -+ -+ /* this function only applies to output pin -+ */ -+ if (!val) -+ return; -+ -+ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT + reg_offset); -+ -+ if ( value == 0 ){ -+ /* Set the pin to zero */ -+ val &= ~nBitMask; -+ }else{ -+ /* Set the pin to 1 */ -+ val |= nBitMask; -+ } -+ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_DOUT + reg_offset); -+ -+ iproc_gpio_unlock(ourchip, flags); -+ -+} -+ -+ -+static int iproc_gpiolib_get(struct gpio_chip *chip, unsigned gpio) -+{ -+ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); -+ unsigned long flags; -+ unsigned int val, offset, nBitMask; -+ int reg_offset = 0; -+ unsigned int pin_offset = gpio + ourchip->pin_offset; -+ -+ iproc_gpio_lock(ourchip, flags); -+ -+ nBitMask = 1 << pin_offset; -+ -+ /* determine the GPIO pin direction -+ */ -+ offset = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN + reg_offset); -+ offset &= nBitMask; -+ -+ if (offset){ -+ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT + reg_offset); -+ } else { -+ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DIN + reg_offset); -+ } -+ -+ val >>= pin_offset; -+ -+ val &= 1; -+ -+ iproc_gpio_unlock(ourchip, flags); -+ -+ return val; -+} -+ -+/* -+@offset : the gpio pin index number from gpiolib view (minus gpio base only) -+*/ -+static int iproc_gpiolib_to_irq(struct gpio_chip *chip, -+ unsigned offset) -+{ -+ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); -+ return irq_linear_revmap(ourchip->irq_domain, offset); -+} -+ -+static struct __initconst of_device_id bcm_iproc_gpio_of_match[] = { -+ { .compatible = "brcm,iproc-gpio,cca" }, -+ { .compatible = "brcm,iproc-gpio,ccb" }, -+ { .compatible = "brcm,iproc-gpio,ccg" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_gpio_of_match); -+ -+void iproc_gpiolib_add(struct iproc_gpio_chip *chip) -+{ -+ struct gpio_chip *gc = &chip->chip; -+ int ret; -+ -+ BUG_ON(!gc->label); -+ BUG_ON(!gc->ngpio); -+ -+ /* -+ * The register offsets for data in, out, and enable are the same for -+ * all GPIO's. -+ */ -+ if (!gc->direction_input) -+ gc->direction_input = iproc_gpiolib_input; -+ if (!gc->direction_output) -+ gc->direction_output = iproc_gpiolib_output; -+ if (!gc->set) -+ gc->set = iproc_gpiolib_set; -+ if (!gc->get) -+ gc->get = iproc_gpiolib_get; -+ if (!gc->to_irq) -+ gc->to_irq = iproc_gpiolib_to_irq; -+ -+ ret = gpiochip_add(gc); -+ if (ret >= 0) -+ printk(KERN_INFO "iproc gpiochip add %s\n", gc->label); -+ -+ return; -+} -+ -+/* -+ * Handles CCA, CCB, and CCG type GPIO's and registers the gpio -+ * controller. -+ */ -+ -+static int iproc_gpio_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *match; -+ struct device_node *dn = pdev->dev.of_node; -+ struct iproc_gpio_chip *iproc_gpio; -+ u32 num_gpios, pin_base, pin_offset, count/*, irq_base*/; -+ int ret; -+ -+ match = of_match_device(bcm_iproc_gpio_of_match, &pdev->dev); -+ if (!match) { -+ dev_err(&pdev->dev, "Failed to find gpio controller\n"); -+ return -ENODEV; -+ } -+ -+ iproc_gpio = devm_kzalloc(&pdev->dev, sizeof(*iproc_gpio), GFP_KERNEL); -+ if (!iproc_gpio) { -+ dev_err(&pdev->dev, "Error allocating memory\n"); -+ return -ENOMEM; -+ } -+ -+ platform_set_drvdata(pdev, iproc_gpio); -+ -+ /* Determine type of gpio controller to allocate. */ -+#if defined(IPROC_GPIO_CCA) -+ if (strstr(match->compatible, "cca")) { -+ iproc_gpio->chip.label = "gpio_cca"; -+ iproc_gpio->id = IPROC_GPIO_CCA_ID; -+ iproc_gpio->irqcfg = &cca_gpio_irqcfg; -+ -+ iproc_gpio->intr_ioaddr = of_iomap(dn, 1); -+ if (!iproc_gpio->intr_ioaddr) { -+ dev_err(&pdev->dev, "can't iomap gpio interrupt base address\n"); -+ return -ENOMEM; -+ } -+ -+ dev_info(&pdev->dev, "%s intr_ioaddr: %p\n", -+ iproc_gpio->chip.label, iproc_gpio->intr_ioaddr); -+ } -+ else -+#endif -+#if defined(IPROC_GPIO_CCB) -+ if (strstr(match->compatible, "ccb")) { -+ iproc_gpio->chip.label = "gpio_ccb"; -+ iproc_gpio->id = IPROC_GPIO_CCB_ID; -+ iproc_gpio->irqcfg = &ccb_gpio_irqcfg; -+ } -+ else -+#endif -+#if defined(IPROC_GPIO_CCG) -+ if (strstr(match->compatible, "ccg")) { -+ iproc_gpio->chip.label = "gpio_ccg"; -+ iproc_gpio->id = IPROC_GPIO_CCG_ID; -+ iproc_gpio->irqcfg = &ccb_gpio_irqcfg; -+ } -+ else -+#endif -+ { -+ dev_err(&pdev->dev, "Error parsing device tree of GPIO\n"); -+ return -ENODEV; -+ } -+ -+ /* Map gpio base ioaddr address. */ -+ iproc_gpio->ioaddr = of_iomap(dn, 0); -+ if (!iproc_gpio->ioaddr) { -+ dev_err(&pdev->dev, "can't iomap gpio base address\n"); -+ return -ENOMEM; -+ } -+ dev_info(&pdev->dev, "%s iaddr: %p\n", iproc_gpio->chip.label, iproc_gpio->ioaddr); -+ -+ if (of_property_read_u32(dn, "pin-base", &pin_base)) { -+ dev_err(&pdev->dev, "Missing pin-base property\n"); -+ return -EINVAL; -+ } -+ iproc_gpio->chip.base = pin_base; -+ -+ /* get pin_offset */ -+ if (of_property_read_u32(dn, "pin-offset", &pin_offset)) { -+ dev_err(&pdev->dev, "Missing pin-offset property\n"); -+ return -EINVAL; -+ } -+ iproc_gpio->pin_offset = pin_offset; -+ -+ /* Get number of GPIO's from device tree for gpiolib. */ -+ if (of_property_read_u32(dn, "ngpios", &num_gpios)) { -+ dev_err(&pdev->dev, "Missing ngpios property\n"); -+ return -EINVAL; -+ } -+ iproc_gpio->chip.ngpio = num_gpios; -+ -+ /* Register controller with gpiolib. */ -+ iproc_gpio->chip.dev = &pdev->dev; -+ iproc_gpiolib_add(iproc_gpio); -+ -+ /* Get interrupt number from device tree. */ -+ iproc_gpio->irq = irq_of_parse_and_map(dn, 0); -+ -+ /* Install ISR for this GPIO controller. */ -+ if (iproc_gpio->irq > 0) { -+ /* Create irq domain so that each pin can be assigned an IRQ.*/ -+ iproc_gpio->irq_domain = irq_domain_add_linear(dn, num_gpios, -+ &irq_domain_simple_ops, iproc_gpio); -+ -+ if (!iproc_gpio->irq_domain) { -+ dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n"); -+ return -ENXIO; -+ } -+ -+ /* Map each gpio to an IRQ and set the handler for gpiolib. */ -+ for (count = 0; count < num_gpios; count++) { -+ int irq; -+ -+ irq = irq_create_mapping(iproc_gpio->irq_domain, count); -+ irq_set_chip_and_handler(irq, &iproc_gpio_irq_chip, -+ handle_simple_irq); -+ irq_set_chip_data(irq, iproc_gpio); -+ } -+ -+ /* Enable GPIO interrupts in CCA interrupt mask. */ -+#if defined(IPROC_GPIO_CCA) -+ if (iproc_gpio->id == IPROC_GPIO_CCA_ID) { -+ unsigned int val; -+ val = readl(iproc_gpio->intr_ioaddr + IPROC_CCA_INT_MASK); -+ val |= IPROC_CCA_INT_F_GPIOINT; -+ writel(val, iproc_gpio->intr_ioaddr + IPROC_CCA_INT_MASK); -+ } -+#endif /* IPROC_GPIO_CCA */ -+ if (iproc_gpio->irqcfg) { -+ struct iproc_gpio_irqcfg *irqcfg = iproc_gpio->irqcfg; -+ if (irqcfg->handler) { -+ ret = request_irq(iproc_gpio->irq, -+ irqcfg->handler, irqcfg->flags, -+ iproc_gpio->chip.label, iproc_gpio); -+ if (ret) { -+ printk(KERN_ERR "Unable to request IRQ%d: %d\n", iproc_gpio->irq, ret); -+ return -ENODEV; -+ } -+ } -+ else -+ printk(KERN_ERR "%s is added without isr!\n", iproc_gpio->chip.label); -+ } -+ } -+ else -+ dev_warn(&pdev->dev, "IRQ not specified. No ISR installed\n"); -+ -+ return 0; -+} -+ -+static int __exit iproc_gpio_remove(struct platform_device *pdev) -+{ -+ struct iproc_gpio_chip *iproc_gpio; -+ -+ iproc_gpio = platform_get_drvdata(pdev); -+ if (iproc_gpio == NULL) -+ return -ENODEV; -+ -+ if (iproc_gpio->intr_ioaddr) { -+#if defined(IPROC_GPIO_CCA) -+ if (iproc_gpio->id == IPROC_GPIO_CCA_ID) { -+ unsigned int val; -+ val = readl(iproc_gpio->intr_ioaddr + IPROC_CCA_INT_MASK); -+ val &= ~(IPROC_CCA_INT_F_GPIOINT); -+ writel(val, iproc_gpio->intr_ioaddr + IPROC_CCA_INT_MASK); -+ } -+#endif -+ } -+ -+ gpiochip_remove(&iproc_gpio->chip); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_iproc_gpio_driver = { -+ .driver = { -+ .name = "iproc-gpio", -+ .owner = THIS_MODULE, -+ .of_match_table = bcm_iproc_gpio_of_match, -+ }, -+ .probe = iproc_gpio_probe, -+ .remove = iproc_gpio_remove, -+}; -+ -+module_platform_driver(bcm_iproc_gpio_driver); -+ -+MODULE_DESCRIPTION("IPROC GPIO driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/gpio/gpio-xgs-iproc.h b/drivers/gpio/gpio-xgs-iproc.h ---- a/drivers/gpio/gpio-xgs-iproc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/gpio/gpio-xgs-iproc.h 2017-11-09 17:53:27.757186000 +0800 -@@ -0,0 +1,61 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#ifndef __IPROC_PLAT_GPIO_H -+#define __IPROC_PLAT_GPIO_H -+ -+#if defined(CONFIG_MACH_IPROC_P7) -+#define IPROC_GPIO_CCG -+#else -+#define IPROC_GPIO_CCA -+#define IPROC_GPIO_CCB -+#endif -+ -+#define IPROC_GPIO_REG_SIZE (0x50) -+ -+#define REGOFFSET_GPIO_DIN 0x000 /* GPIO Data in register */ -+#define REGOFFSET_GPIO_DOUT 0x004 /* GPIO Data out register */ -+#define REGOFFSET_GPIO_EN 0x008 /* GPIO output enable register */ -+ -+#define IPROC_GPIO_CCA_ID (0) -+#define IPROC_GPIO_CCB_ID (1) -+#define IPROC_GPIO_CCG_ID (2) -+ -+struct iproc_gpio_irqcfg { -+ unsigned long flags; -+ irqreturn_t (*handler)(int irq, void *dev); -+ void (*ack)(unsigned int irq); -+ void (*unmask)(unsigned int irq); -+ void (*mask)(unsigned int irq); -+ int (*set_type)(unsigned int irq, unsigned int type); -+}; -+ -+struct iproc_gpio_chip { -+ int id; -+ struct gpio_chip chip; -+ struct iproc_gpio_cfg *config; -+ void __iomem *ioaddr; -+ void __iomem *intr_ioaddr; -+ spinlock_t lock; -+ struct irq_domain *irq_domain; -+ struct resource * resource; -+ int irq; -+ struct iproc_gpio_irqcfg *irqcfg; -+ int pin_offset; -+}; -+ -+ -+static inline struct iproc_gpio_chip *to_iproc_gpio(struct gpio_chip *gpc) -+{ -+ return container_of(gpc, struct iproc_gpio_chip, chip); -+} -+ -+ -+/* locking wrappers to deal with multiple access to the same gpio bank */ -+#define iproc_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) -+#define iproc_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) -+ -+extern void iproc_gpiolib_add(struct iproc_gpio_chip *chip); -+ -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig ---- a/drivers/i2c/busses/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/i2c/busses/Kconfig 2017-11-09 17:53:33.506215000 +0800 -@@ -385,6 +385,26 @@ config I2C_BCM_IPROC - - If you don't know what to do here, say N. - -+config I2C_XGS_IPROC -+ tristate "Broadcom XGS iProc I2C controller" -+ depends on ARCH_XGS_IPROC -+ default ARCH_XGS_IPROC -+ help -+ If you say yes to this option, support will be included for the -+ Broadcom XGS iProc I2C controller. -+ -+ If you don't know what to do here, say N. -+ -+config SMBUS_XGS_IPROC -+ tristate "Broadcom XGS iProc SMBUS controller" -+ depends on ARCH_XGS_IPROC -+ default !I2C_XGS_IPROC -+ help -+ If you say yes to this option, support will be included for the -+ Broadcom XGS iProc SMBUS controller. -+ -+ If you don't know what to do here, say N. -+ - config I2C_BCM_KONA - tristate "BCM Kona I2C adapter" - depends on ARCH_BCM_MOBILE -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile ---- a/drivers/i2c/busses/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/i2c/busses/Makefile 2017-11-09 17:53:33.507214000 +0800 -@@ -92,6 +92,8 @@ obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-unip - obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o - obj-$(CONFIG_I2C_WMT) += i2c-wmt.o - obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o -+obj-$(CONFIG_I2C_XGS_IPROC) += i2c-xgs-iproc.o -+obj-$(CONFIG_SMBUS_XGS_IPROC) += xgs_iproc_smbus.o - obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o - obj-$(CONFIG_I2C_XLR) += i2c-xlr.o - obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/i2c-xgs-iproc.c b/drivers/i2c/busses/i2c-xgs-iproc.c ---- a/drivers/i2c/busses/i2c-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/i2c/busses/i2c-xgs-iproc.c 2017-11-09 17:53:33.700222000 +0800 -@@ -0,0 +1,598 @@ -+/* -+ * Copyright (C) 2014 Broadcom 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 version 2. -+ * -+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any -+ * kind, whether express or implied; 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 -+ -+#define CFG_OFFSET 0x00 -+#define CFG_RESET_SHIFT 31 -+#define CFG_EN_SHIFT 30 -+#define CFG_M_RETRY_CNT_SHIFT 16 -+#define CFG_M_RETRY_CNT_MASK 0x0f -+ -+#define TIM_CFG_OFFSET 0x04 -+#define TIM_CFG_MODE_400_SHIFT 31 -+ -+#define M_FIFO_CTRL_OFFSET 0x0c -+#define M_FIFO_RX_FLUSH_SHIFT 31 -+#define M_FIFO_TX_FLUSH_SHIFT 30 -+#define M_FIFO_RX_CNT_SHIFT 16 -+#define M_FIFO_RX_CNT_MASK 0x7f -+#define M_FIFO_RX_THLD_SHIFT 8 -+#define M_FIFO_RX_THLD_MASK 0x3f -+ -+#define M_CMD_OFFSET 0x30 -+#define M_CMD_START_BUSY_SHIFT 31 -+#define M_CMD_STATUS_SHIFT 25 -+#define M_CMD_STATUS_MASK 0x07 -+#define M_CMD_STATUS_SUCCESS 0x0 -+#define M_CMD_STATUS_LOST_ARB 0x1 -+#define M_CMD_STATUS_NACK_ADDR 0x2 -+#define M_CMD_STATUS_NACK_DATA 0x3 -+#define M_CMD_STATUS_TIMEOUT 0x4 -+#define M_CMD_PROTOCOL_SHIFT 9 -+#define M_CMD_PROTOCOL_MASK 0xf -+#define M_CMD_PROTOCOL_BLK_WR 0x7 -+#define M_CMD_PROTOCOL_BLK_RD 0x8 -+#define M_CMD_PEC_SHIFT 8 -+#define M_CMD_RD_CNT_SHIFT 0 -+#define M_CMD_RD_CNT_MASK 0xff -+ -+#define IE_OFFSET 0x38 -+#define IE_M_RX_FIFO_FULL_SHIFT 31 -+#define IE_M_RX_THLD_SHIFT 30 -+#define IE_M_START_BUSY_SHIFT 28 -+ -+#define IS_OFFSET 0x3c -+#define IS_M_RX_FIFO_FULL_SHIFT 31 -+#define IS_M_RX_THLD_SHIFT 30 -+#define IS_M_START_BUSY_SHIFT 28 -+ -+#define M_TX_OFFSET 0x40 -+#define M_TX_WR_STATUS_SHIFT 31 -+#define M_TX_DATA_SHIFT 0 -+#define M_TX_DATA_MASK 0xff -+ -+#define M_RX_OFFSET 0x44 -+#define M_RX_STATUS_SHIFT 30 -+#define M_RX_STATUS_MASK 0x03 -+#define M_RX_PEC_ERR_SHIFT 29 -+#define M_RX_DATA_SHIFT 0 -+#define M_RX_DATA_MASK 0xff -+ -+#define I2C_TIMEOUT_MESC 100 -+ -+#define M_TX_RX_FIFO_SIZE 64 -+#define I2C_MAX_DATA_READ_LEN (M_TX_RX_FIFO_SIZE - 1) -+#define I2C_MAX_DATA_WRITE_LEN (M_TX_RX_FIFO_SIZE - 1) -+ -+/* -+ * Enable support of EEPROM I2C devices with 2 byte addressing mode and page -+ * size >= 64B. -+ */ -+#define CONFIG_ENABLE_WRITE_MSG_SPLIT 1 -+ -+ -+enum bus_speed_index { -+ I2C_SPD_100K = 0, -+ I2C_SPD_400K, -+}; -+ -+struct bcm_iproc_i2c_dev { -+ struct device *device; -+ int irq; -+ -+ void __iomem *base; -+ -+ struct i2c_adapter adapter; -+ unsigned int bus_speed; -+ -+ struct completion done; -+ int xfer_is_done; -+}; -+ -+/* -+ * Can be expanded in the future if more interrupt status bits are utilized -+ */ -+#define ISR_MASK (1 << IS_M_START_BUSY_SHIFT) -+ -+static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) -+{ -+ struct bcm_iproc_i2c_dev *iproc_i2c = data; -+ u32 status = readl(iproc_i2c->base + IS_OFFSET); -+ -+ status &= ISR_MASK; -+ -+ if (!status) -+ return IRQ_NONE; -+ -+ writel(status, iproc_i2c->base + IS_OFFSET); -+ iproc_i2c->xfer_is_done = 1; -+ complete_all(&iproc_i2c->done); -+ -+ return IRQ_HANDLED; -+} -+ -+static int bcm_iproc_i2c_check_status(struct bcm_iproc_i2c_dev *iproc_i2c, -+ struct i2c_msg *msg) -+{ -+ u32 val; -+ -+ val = readl(iproc_i2c->base + M_CMD_OFFSET); -+ val = (val >> M_CMD_STATUS_SHIFT) & M_CMD_STATUS_MASK; -+ -+ switch (val) { -+ case M_CMD_STATUS_SUCCESS: -+ return 0; -+ -+ case M_CMD_STATUS_LOST_ARB: -+ dev_dbg(iproc_i2c->device, "lost bus arbitration\n"); -+ return -EAGAIN; -+ -+ case M_CMD_STATUS_NACK_ADDR: -+ dev_dbg(iproc_i2c->device, "NAK addr:0x%02x\n", msg->addr); -+ return -ENXIO; -+ -+ case M_CMD_STATUS_NACK_DATA: -+ dev_dbg(iproc_i2c->device, "NAK data\n"); -+ return -ENXIO; -+ -+ case M_CMD_STATUS_TIMEOUT: -+ dev_dbg(iproc_i2c->device, "bus timeout\n"); -+ return -ETIMEDOUT; -+ -+ default: -+ dev_dbg(iproc_i2c->device, "unknown error code=%d\n", val); -+ return -EIO; -+ } -+} -+ -+static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, -+ struct i2c_msg *msg) -+{ -+ int ret, i; -+ u8 addr; -+ u32 val; -+ unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MESC); -+ -+ /* check if bus is busy */ -+ if (!!(readl(iproc_i2c->base + M_CMD_OFFSET) & -+ BIT(M_CMD_START_BUSY_SHIFT))) { -+ dev_warn(iproc_i2c->device, "bus is busy\n"); -+ return -EBUSY; -+ } -+ -+ /* format and load slave address into the TX FIFO */ -+ addr = msg->addr << 1 | (msg->flags & I2C_M_RD ? 1 : 0); -+ writel(addr, iproc_i2c->base + M_TX_OFFSET); -+ -+ /* for a write transaction, load data into the TX FIFO */ -+ if (!(msg->flags & I2C_M_RD)) { -+ for (i = 0; i < msg->len; i++) { -+ val = msg->buf[i]; -+ -+ /* mark the last byte */ -+ if (i == msg->len - 1) -+ val |= 1 << M_TX_WR_STATUS_SHIFT; -+ -+ writel(val, iproc_i2c->base + M_TX_OFFSET); -+ } -+ } -+ -+ /* mark as incomplete before starting the transaction */ -+ reinit_completion(&iproc_i2c->done); -+ iproc_i2c->xfer_is_done = 0; -+ -+ /* -+ * Enable the "start busy" interrupt, which will be triggered after the -+ * transaction is done, i.e., the internal start_busy bit, transitions -+ * from 1 to 0. -+ */ -+ writel(1 << IE_M_START_BUSY_SHIFT, iproc_i2c->base + IE_OFFSET); -+ -+ /* -+ * Now we can activate the transfer. For a read operation, specify the -+ * number of bytes to read -+ */ -+ val = 1 << M_CMD_START_BUSY_SHIFT; -+ if (msg->flags & I2C_M_RD) { -+ val |= (M_CMD_PROTOCOL_BLK_RD << M_CMD_PROTOCOL_SHIFT) | -+ (msg->len << M_CMD_RD_CNT_SHIFT); -+ } else { -+ val |= (M_CMD_PROTOCOL_BLK_WR << M_CMD_PROTOCOL_SHIFT); -+ } -+ writel(val, iproc_i2c->base + M_CMD_OFFSET); -+ -+ time_left = wait_for_completion_timeout(&iproc_i2c->done, time_left); -+ -+ /* disable all interrupts */ -+ writel(0, iproc_i2c->base + IE_OFFSET); -+ /* read it back to flush the write */ -+ readl(iproc_i2c->base + IE_OFFSET); -+ -+ /* make sure the interrupt handler isn't running */ -+ synchronize_irq(iproc_i2c->irq); -+ -+ if (!time_left && !iproc_i2c->xfer_is_done) { -+ dev_err(iproc_i2c->device, "transaction timed out\n"); -+ -+ /* flush FIFOs */ -+ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | -+ (1 << M_FIFO_TX_FLUSH_SHIFT); -+ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); -+ return -ETIMEDOUT; -+ } -+ -+ ret = bcm_iproc_i2c_check_status(iproc_i2c, msg); -+ if (ret) { -+ /* flush both TX/RX FIFOs */ -+ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | -+ (1 << M_FIFO_TX_FLUSH_SHIFT); -+ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); -+ return ret; -+ } -+ -+ /* -+ * For a read operation, we now need to load the data from FIFO -+ * into the memory buffer -+ */ -+ if (msg->flags & I2C_M_RD) { -+ for (i = 0; i < msg->len; i++) { -+ msg->buf[i] = (readl(iproc_i2c->base + M_RX_OFFSET) >> -+ M_RX_DATA_SHIFT) & M_RX_DATA_MASK; -+ } -+ } -+ -+ return 0; -+} -+ -+static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg msgs[], int num) -+{ -+ struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(adapter); -+ int ret, i; -+ int xfer_msg_len, xfer_msg_len_max; -+ u8 addr_h, addr_l; -+ -+ /* go through all messages */ -+ for (i = 0; i < num; i++) { -+ xfer_msg_len = msgs[i].len; -+ if (msgs[i].flags & I2C_M_RD) -+ xfer_msg_len_max = I2C_MAX_DATA_READ_LEN; -+ else -+ xfer_msg_len_max = I2C_MAX_DATA_WRITE_LEN; -+ -+ while (xfer_msg_len) { -+ if (xfer_msg_len > xfer_msg_len_max) -+ msgs[i].len = xfer_msg_len_max; -+ ret = bcm_iproc_i2c_xfer_single_msg(iproc_i2c, &msgs[i]); -+ if (ret) { -+ dev_dbg(iproc_i2c->device, "xfer failed\n"); -+ return ret; -+ } -+ -+ if (msgs[i].len == xfer_msg_len_max) { -+ xfer_msg_len -= xfer_msg_len_max; -+ if (xfer_msg_len == 0) -+ break; -+ /* Keep the addr offset for later use */ -+ addr_h = *(msgs[i].buf); -+ addr_l = *(msgs[i].buf + 1); -+ -+ msgs[i].len = xfer_msg_len; -+ msgs[i].buf += xfer_msg_len_max; -+ -+#if defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) -+ if (!(msgs[i].flags & I2C_M_RD)) { -+ /* -+ * For write transfer with len >= 64B, -+ * assuming 2 byte addressing should be -+ * reasonable. -+ */ -+ xfer_msg_len += 2; -+ msgs[i].len = xfer_msg_len; -+ -+ /* -+ * Append new 2-byte address offset. -+ * The upper byte should be unchanged. -+ * The lower byte is increased by -+ * actually written bytes: -+ * (xfer_msg_len_max - 2) -+ */ -+ msgs[i].buf -= 2; -+ *(msgs[i].buf) = addr_h; -+ *(msgs[i].buf + 1) = addr_l - 2 + -+ xfer_msg_len_max; -+ -+ /* -+ * Wait some time so that EEPROM -+ * is ready to respond after previous -+ * partial page write. -+ */ -+ mdelay(10); -+ } -+#endif /* CONFIG_ENABLE_WRITE_MSG_SPLIT */ -+ } else { -+ /* -+ * msgs[i] is transfered completely, -+ * if msgs[i].len is less than xfer_msg_len_max. -+ */ -+ break; -+ } -+ } /* while */ -+ } /* for */ -+ -+ return num; -+} -+ -+ -+static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm bcm_iproc_algo = { -+ .master_xfer = bcm_iproc_i2c_xfer, -+ .functionality = bcm_iproc_i2c_functionality, -+}; -+ -+/* -+ * Don't limit the max write length for Linux I2C core, if support of -+ * write msg split is enabled. -+ * Read msg split is support, so max_read_len is commented out. -+ */ -+#if !defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) -+static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { -+ /* need to reserve one byte in the FIFO for the slave address */ -+ //.max_read_len = M_TX_RX_FIFO_SIZE - 1, -+ .max_write_len = M_TX_RX_FIFO_SIZE - 1, -+}; -+#endif -+ -+static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c) -+{ -+ unsigned int bus_speed; -+ u32 val; -+ int ret = of_property_read_u32(iproc_i2c->device->of_node, -+ "clock-frequency", &bus_speed); -+ if (ret < 0) { -+ dev_info(iproc_i2c->device, -+ "unable to interpret clock-frequency DT property\n"); -+ bus_speed = 100000; -+ } -+ -+ if (bus_speed < 100000) { -+ dev_err(iproc_i2c->device, "%d Hz bus speed not supported\n", -+ bus_speed); -+ dev_err(iproc_i2c->device, -+ "valid speeds are 100khz and 400khz\n"); -+ return -EINVAL; -+ } else if (bus_speed < 400000) { -+ bus_speed = 100000; -+ } else { -+ bus_speed = 400000; -+ } -+ -+ iproc_i2c->bus_speed = bus_speed; -+ val = readl(iproc_i2c->base + TIM_CFG_OFFSET); -+ val &= ~(1 << TIM_CFG_MODE_400_SHIFT); -+ val |= (bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; -+ writel(val, iproc_i2c->base + TIM_CFG_OFFSET); -+ -+ dev_info(iproc_i2c->device, "bus set to %u Hz\n", bus_speed); -+ -+ return 0; -+} -+ -+static int bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) -+{ -+ u32 val; -+ -+ /* put controller in reset */ -+ val = readl(iproc_i2c->base + CFG_OFFSET); -+ val |= 1 << CFG_RESET_SHIFT; -+ val &= ~(1 << CFG_EN_SHIFT); -+ writel(val, iproc_i2c->base + CFG_OFFSET); -+ -+ /* wait 100 usec per spec */ -+ udelay(100); -+ -+ /* bring controller out of reset */ -+ val &= ~(1 << CFG_RESET_SHIFT); -+ writel(val, iproc_i2c->base + CFG_OFFSET); -+ -+ /* flush TX/RX FIFOs and set RX FIFO threshold to zero */ -+ val = (1 << M_FIFO_RX_FLUSH_SHIFT) | (1 << M_FIFO_TX_FLUSH_SHIFT); -+ writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); -+ -+ /* disable all interrupts */ -+ writel(0, iproc_i2c->base + IE_OFFSET); -+ -+ /* clear all pending interrupts */ -+ writel(0xffffffff, iproc_i2c->base + IS_OFFSET); -+ -+ return 0; -+} -+ -+static void bcm_iproc_i2c_enable_disable(struct bcm_iproc_i2c_dev *iproc_i2c, -+ bool enable) -+{ -+ u32 val; -+ -+ val = readl(iproc_i2c->base + CFG_OFFSET); -+ if (enable) -+ val |= BIT(CFG_EN_SHIFT); -+ else -+ val &= ~BIT(CFG_EN_SHIFT); -+ writel(val, iproc_i2c->base + CFG_OFFSET); -+} -+ -+static int bcm_iproc_i2c_probe(struct platform_device *pdev) -+{ -+ int irq, ret = 0; -+ struct bcm_iproc_i2c_dev *iproc_i2c; -+ struct i2c_adapter *adap; -+ struct resource *res; -+ -+ iproc_i2c = devm_kzalloc(&pdev->dev, sizeof(*iproc_i2c), -+ GFP_KERNEL); -+ if (!iproc_i2c) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, iproc_i2c); -+ iproc_i2c->device = &pdev->dev; -+ init_completion(&iproc_i2c->done); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ iproc_i2c->base = devm_ioremap_resource(iproc_i2c->device, res); -+ if (IS_ERR(iproc_i2c->base)) -+ return PTR_ERR(iproc_i2c->base); -+ -+ ret = bcm_iproc_i2c_init(iproc_i2c); -+ if (ret) -+ return ret; -+ -+ ret = bcm_iproc_i2c_cfg_speed(iproc_i2c); -+ if (ret) -+ return ret; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(iproc_i2c->device, "no irq resource\n"); -+ return irq; -+ } -+ iproc_i2c->irq = irq; -+ -+ ret = devm_request_irq(iproc_i2c->device, irq, bcm_iproc_i2c_isr, 0, -+ pdev->name, iproc_i2c); -+ if (ret < 0) { -+ dev_err(iproc_i2c->device, "unable to request irq %i\n", irq); -+ return ret; -+ } -+ -+ bcm_iproc_i2c_enable_disable(iproc_i2c, true); -+ -+ adap = &iproc_i2c->adapter; -+ i2c_set_adapdata(adap, iproc_i2c); -+ strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name)); -+ adap->algo = &bcm_iproc_algo; -+#if !defined(CONFIG_ENABLE_WRITE_MSG_SPLIT) -+ adap->quirks = &bcm_iproc_i2c_quirks; -+#endif -+ adap->dev.parent = &pdev->dev; -+ adap->dev.of_node = pdev->dev.of_node; -+ -+ ret = i2c_add_adapter(adap); -+ if (ret) { -+ dev_err(iproc_i2c->device, "failed to add adapter\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int bcm_iproc_i2c_remove(struct platform_device *pdev) -+{ -+ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); -+ -+ /* make sure there's no pending interrupt when we remove the adapter */ -+ writel(0, iproc_i2c->base + IE_OFFSET); -+ readl(iproc_i2c->base + IE_OFFSET); -+ synchronize_irq(iproc_i2c->irq); -+ -+ i2c_del_adapter(&iproc_i2c->adapter); -+ bcm_iproc_i2c_enable_disable(iproc_i2c, false); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+ -+static int bcm_iproc_i2c_suspend(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); -+ -+ /* make sure there's no pending interrupt when we go into suspend */ -+ writel(0, iproc_i2c->base + IE_OFFSET); -+ readl(iproc_i2c->base + IE_OFFSET); -+ synchronize_irq(iproc_i2c->irq); -+ -+ /* now disable the controller */ -+ bcm_iproc_i2c_enable_disable(iproc_i2c, false); -+ -+ return 0; -+} -+ -+static int bcm_iproc_i2c_resume(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); -+ int ret; -+ u32 val; -+ -+ /* -+ * Power domain could have been shut off completely in system deep -+ * sleep, so re-initialize the block here -+ */ -+ ret = bcm_iproc_i2c_init(iproc_i2c); -+ if (ret) -+ return ret; -+ -+ /* configure to the desired bus speed */ -+ val = readl(iproc_i2c->base + TIM_CFG_OFFSET); -+ val &= ~(1 << TIM_CFG_MODE_400_SHIFT); -+ val |= (iproc_i2c->bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; -+ writel(val, iproc_i2c->base + TIM_CFG_OFFSET); -+ -+ bcm_iproc_i2c_enable_disable(iproc_i2c, true); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops bcm_iproc_i2c_pm_ops = { -+ .suspend_late = &bcm_iproc_i2c_suspend, -+ .resume_early = &bcm_iproc_i2c_resume -+}; -+ -+#define BCM_IPROC_I2C_PM_OPS (&bcm_iproc_i2c_pm_ops) -+#else -+#define BCM_IPROC_I2C_PM_OPS NULL -+#endif /* CONFIG_PM_SLEEP */ -+ -+static const struct of_device_id bcm_iproc_i2c_of_match[] = { -+ { .compatible = "brcm,iproc-i2c" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_i2c_of_match); -+ -+static struct platform_driver bcm_iproc_i2c_driver = { -+ .driver = { -+ .name = "bcm-iproc-i2c", -+ .of_match_table = bcm_iproc_i2c_of_match, -+ .pm = BCM_IPROC_I2C_PM_OPS, -+ }, -+ .probe = bcm_iproc_i2c_probe, -+ .remove = bcm_iproc_i2c_remove, -+}; -+module_platform_driver(bcm_iproc_i2c_driver); -+ -+MODULE_AUTHOR("Ray Jui "); -+MODULE_DESCRIPTION("Broadcom iProc I2C Driver"); -+MODULE_LICENSE("GPL v2"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/iproc_smbus.h b/drivers/i2c/busses/iproc_smbus.h ---- a/drivers/i2c/busses/iproc_smbus.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/i2c/busses/iproc_smbus.h 2017-11-09 17:53:33.705215000 +0800 -@@ -0,0 +1,189 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ */ -+ -+#ifndef __IPROC_SMBUS_H__ -+#define __IPROC_SMBUS_H__ -+ -+#define IPROC_I2C_INVALID_ADDR 0xFF -+ -+#define MAX_PROC_BUF_SIZE 256 -+#define MAX_PROC_NAME_SIZE 15 -+#define PROC_GLOBAL_PARENT_DIR "iproc-i2c" -+#define PROC_ENTRY_DEBUG "iproc-i2c-dbg" -+ -+#define IPROC_SMB_MAX_RETRIES 35 -+ -+#define GETREGFLDVAL(regval, mask, startbit) (((regval) & (mask)) >> (startbit)) -+ -+#define SETREGFLDVAL(regval, fldval, mask, startbit) regval = \ -+ (regval & ~(mask)) | \ -+ ((fldval) << (startbit)) -+ -+/* Enum to specify clock speed. The user will provide it during initialization. -+ * If needed, it can be changed dynamically -+ */ -+typedef enum iproc_smb_clk_freq { -+ I2C_SPEED_100KHz = 0, -+ I2C_SPEED_400KHz = 1, -+ I2C_SPEED_INVALID = 255 -+} smb_clk_freq_t; -+ -+/* This enum will be used to notify the user of status of a data transfer -+ * request -+ */ -+typedef enum iproc_smb_error_code { -+ I2C_NO_ERR = 0, -+ I2C_TIMEOUT_ERR = 1, -+ I2C_INVALID_PARAM_ERR = 2, /* Invalid parameter(s) passed to the driver */ -+ I2C_OPER_IN_PROGRESS = 3, /* The driver API was called before the present -+ transfer was completed */ -+ I2C_OPER_ABORT_ERR = 4, /* Transfer aborted unexpectedly, for example a NACK -+ received, before last byte was read/written */ -+ I2C_FUNC_NOT_SUPPORTED = 5, /* Feature or function not supported -+ (e.g., 10-bit addresses, or clock speeds -+ other than 100KHz, 400KHz) */ -+} iproc_smb_error_code_t; -+ -+/* Counters will be used mainly for testing and debugging */ -+struct iproc_smb_counters { -+ unsigned int num_read_requests; -+ unsigned int num_write_requests; -+ unsigned int num_read_errors; -+ unsigned int num_write_errors; -+ unsigned int mstr_rx_evt_cnt; /* ISR counter to check recv event */ -+ unsigned int mstr_start_busy_cnt; /* ISR counter to checking xact sts */ -+ unsigned int mstr_rx_fifo_full_cnt; /* ISR counter to detect rx fifo full */ -+ unsigned int last_int_sts; /* last value of intr status reg */ -+}; -+ -+ -+/* This enum may be used in a call back function to provide the user of the -+ * type of request sent by the user. It can also be used for testing and -+ * debugging purposes -+ */ -+typedef enum iproc_smb_message_type { -+ I2C_DISABLE_MSG = 0, /* To be used after hardware initialization. -+ Driver will _not_ respond to API calls */ -+ I2C_ENABLE_MSG = 1, /* Used after hardware initialization, if required. -+ Driver will start responding to API calls. -+ Will not (re-)program the hardware. */ -+ I2C_READ_MSG = 2, /* I2C read request from application */ -+ I2C_WRITE_MSG = 3 /* I2C write request from application */ -+} iproc_smb_message_type_t; -+ -+/* For debugging purposes, we will store the information about the last -+ * (latest) transfer request from the client application -+ */ -+struct iproc_smb_dbg_trans_info -+{ -+ iproc_smb_message_type_t i2c_last_mesg_type; -+ unsigned int i2c_last_dev_addr; -+ unsigned int i2c_last_num_bytes_xfer_req; -+}; -+ -+struct procfs { -+ char name[MAX_PROC_NAME_SIZE]; -+ struct proc_dir_entry *parent; -+}; -+ -+/* This structure will be used internally by the driver to maintain its -+ * configuration information as well as information programmed in to the -+ * hardware -+ */ -+struct iproc_smb_drv_int_data { -+ struct device *dev; -+ struct iproc_smb_drv_int_data *next; -+ -+ int irq; -+ -+ unsigned int drv_state_init; /* 1 = Initialized, 0 = not initialized */ -+ -+ unsigned int drv_state_open; /* 1 = Accepting transaction requests, -+ 0 = Not accepting transaction requests */ -+ smb_clk_freq_t clk_speed; -+ -+ void __iomem *block_base_addr; /* iomapped virtual base address for -+ register access */ -+ -+ struct i2c_adapter adapter; -+ -+ unsigned int i2c_slave_addr; /* Up to four 7-bit SMB slave addresses can be -+ assigned, we will assume only one for now. -+ Valid only if SMBus will act as a slave -+ device */ -+ -+ struct semaphore xfer_lock; /* Lock for data transfer */ -+ -+ struct completion ses_done; /* To signal the command completion */ -+ -+ struct procfs proc; -+ -+ volatile int debug; -+ -+ unsigned int master_rx_fifo_thr; /* Master FIFO threshold. Interrupt will be -+ generated if the threshold is exceeded */ -+ -+ unsigned int slave_rx_fifo_thr; /* Slave FIFO threshold. Interrupt will be -+ generated if the threshold is exceeded */ -+ -+ unsigned int enable_evts; /* If true, enable interrupts. If false, -+ disable interrupts. Default is false */ -+ unsigned int evt_enable_bmap; /* Bit map of events enabled by the driver */ -+ -+ struct iproc_smb_counters smb_counters; /* Statistics maintained by driver. A caller -+ can request them through an API */ -+}; -+ -+/* Data to be supplied by the platform to initialise the IPROC SMBus (I2C). -+ * block -+ * init: Function called during driver initialization. Used by platform to -+ * configure GPIO functions and similar. -+ */ -+struct iproc_smb_platform_data { -+ int (*init)(struct iproc_smb_drv_int_data *iproc_i2c_info_ptr, int flags); -+ -+ unsigned int flags; -+}; -+ -+/* This structure will be used by the user during driver initialization to pass -+ * initial configuration information to the driver -+ */ -+struct iproc_smb_init_params { -+ unsigned int intr_mode; /* TRUE (1) for enabling interrupt mode, -+ FALSE (0) for polling mode */ -+ unsigned int clock_freq; /* 0=100KHz, 1=400KHz */ -+ void (*i2c_callback_func)(unsigned char *data); /* Application can -+ register a callback -+ function for driver to -+ notify the application -+ of any asynchronous -+ event(s), or exception. -+ Can be NULL */ -+}; -+ -+/* Structure used to pass information to read/write functions. */ -+struct iproc_xact_info { -+ bool cmd_valid; /* true if command field below is valid. Otherwise, false */ -+ unsigned short command; /* Passed by caller to send SMBus command code */ -+ unsigned char *data; /* actual data pased by the caller */ -+ unsigned int size; /* Size of data buffer passed */ -+ unsigned short flags; /* Sent by caller specifying PEC, 10-bit addresses */ -+ unsigned char smb_proto; /* SMBus protocol to use to perform transaction */ -+}; -+ -+#define XACT_TIMEOUT (msecs_to_jiffies(100)) /* Verify if 100 is OK */ -+ -+#endif /* __IPROC_SMBUS_H__ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/iproc_smbus_defs.h b/drivers/i2c/busses/iproc_smbus_defs.h ---- a/drivers/i2c/busses/iproc_smbus_defs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/i2c/busses/iproc_smbus_defs.h 2017-11-09 17:53:33.705243000 +0800 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ */ -+ -+#ifndef __IPROC_SMBUS_DEFS_H__ -+#define __IPROC_SMBUS_DEFS_H__ -+ -+/* Transaction error codes defined in Master command register (0x30) */ -+#define MSTR_STS_XACT_SUCCESS 0 -+#define MSTR_STS_LOST_ARB 1 -+#define MSTR_STS_NACK_FIRST_BYTE 2 -+#define MSTR_STS_NACK_NON_FIRST_BYTE 3 /* NACK on a byte other than -+ the first byte */ -+#define MSTR_STS_TTIMEOUT_EXCEEDED 4 -+#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5 -+#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6 -+ -+/* SMBUS protocol values defined in register 0x30 */ -+#define SMBUS_PROT_QUICK_CMD 0 -+#define SMBUS_PROT_SEND_BYTE 1 -+#define SMBUS_PROT_RECV_BYTE 2 -+#define SMBUS_PROT_WR_BYTE 3 -+#define SMBUS_PROT_RD_BYTE 4 -+#define SMBUS_PROT_WR_WORD 5 -+#define SMBUS_PROT_RD_WORD 6 -+#define SMBUS_PROT_BLK_WR 7 -+#define SMBUS_PROT_BLK_RD 8 -+#define SMBUS_PROT_PROC_CALL 9 -+#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 -+ -+#define BUS_BUSY_COUNT 100000 /* Number can be changed later */ -+ -+#define DISABLE_INTR 0 -+#define ENABLE_INTR 1 -+#endif /* __IPROC_SMBUS_DEFS_H__ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/iproc_smbus_regs.h b/drivers/i2c/busses/iproc_smbus_regs.h ---- a/drivers/i2c/busses/iproc_smbus_regs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/i2c/busses/iproc_smbus_regs.h 2017-11-09 17:53:33.706235000 +0800 -@@ -0,0 +1,290 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ */ -+ -+#ifndef __IPROC_SMBUS_REGS_H__ -+#define __IPROC_SMBUS_REGS_H__ -+ -+/* --- */ -+#define CCB_SMB_CFG_REG 0x0 -+ -+#define CCB_SMB_CFG_RST_MASK 0x80000000 -+#define CCB_SMB_CFG_RST_SHIFT 31 -+ -+#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 -+#define CCB_SMB_CFG_SMBEN_SHIFT 30 -+ -+#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 -+#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 -+ -+#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 -+#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 -+ -+#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 -+#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 -+ -+#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 -+#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 -+ -+#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 -+#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 -+ -+ -+/* --- */ -+#define CCB_SMB_TIMGCFG_REG 0x4 -+ -+#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 -+#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 -+ -+#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 -+#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 -+ -+#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 -+#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 -+ -+#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 -+#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 -+ -+/* --- */ -+#define CCB_SMB_ADDR_REG 0x8 -+ -+#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 -+#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 -+ -+#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 -+#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 -+ -+#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 -+#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 -+ -+#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 -+#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 -+ -+#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 -+#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 -+ -+#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 -+#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 -+ -+#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 -+#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 -+ -+#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F -+#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 -+ -+/* --- */ -+#define CCB_SMB_MSTRFIFOCTL_REG 0xC -+ -+#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 -+#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 -+ -+#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 -+#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 -+ -+#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 -+#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 -+ -+#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 -+#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 -+ -+/* --- */ -+#define CCB_SMB_SLVFIFOCTL_REG 0x10 -+ -+#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 -+#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 -+ -+#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 -+#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 -+ -+#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 -+#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 -+ -+#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 -+#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 -+ -+/* --- */ -+#define CCB_SMB_BITBANGCTL_REG 0x14 -+ -+#define CCB_SMB_SMBCLKIN_MASK 0x80000000 -+#define CCB_SMB_SMBCLKIN_SHIFT 31 -+ -+#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 -+#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 -+ -+#define CCB_SMB_SMBDATAIN_MASK 0x20000000 -+#define CCB_SMB_SMBDATAIN_SHIFT 29 -+ -+#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 -+#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 -+ -+/* --- */ -+#define CCB_SMB_MSTRCMD_REG 0x30 -+ -+#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 -+#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 -+ -+#define CCB_SMB_MSTRABORT_MASK 0x40000000 -+#define CCB_SMB_MSTRABORT_SHIFT 30 -+ -+#define CCB_SMB_MSTRSTS_MASK 0x0E000000 -+#define CCB_SMB_MSTRSTS_SHIFT 25 -+ -+#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 -+#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 -+ -+#define CCB_SMB_MSTRPEC_MASK 0x00000100 -+#define CCB_SMB_MSTRPEC_SHIFT 8 -+ -+#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF -+#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 -+ -+/* --- */ -+#define CCB_SMB_SLVCMD_REG 0x34 -+ -+#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 -+#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 -+ -+#define CCB_SMB_SLVABORT_MASK 0x40000000 -+#define CCB_SMB_SLVABORT_SHIFT 30 -+ -+#define CCB_SMB_SLVSTS_MASK 0x03800000 -+#define CCB_SMB_SLVSTS_SHIFT 23 -+ -+#define CCB_SMB_SLVPEC_MASK 0x00000100 -+#define CCB_SMB_SLVPEC_SHIFT 8 -+ -+ -+/* --- */ -+#define CCB_SMB_EVTEN_REG 0x38 -+ -+#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 -+#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 -+ -+#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 -+#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 -+ -+#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 -+#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 -+ -+#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 -+#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 -+ -+#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 -+#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 -+ -+ -+#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 -+#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 -+ -+#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 -+#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 -+ -+#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 -+#define CCB_SMB_SLVRXEVTEN_SHIFT 24 -+ -+#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 -+#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 -+ -+#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 -+#define CCB_SMB_SLVTXUNDEN_SHIFT 22 -+ -+#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 -+#define CCB_SMB_SLVRDEVTEN_SHIFT 21 -+ -+ -+/* --- */ -+#define CCB_SMB_EVTSTS_REG 0x3C -+ -+#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 -+#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 -+ -+#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 -+#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 -+ -+#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 -+#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 -+ -+#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 -+#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 -+ -+#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 -+#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 -+ -+ -+#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 -+#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 -+ -+#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 -+#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 -+ -+#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 -+#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 -+ -+#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 -+#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 -+ -+#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 -+#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 -+ -+#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 -+#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 -+ -+ -+/* --- */ -+#define CCB_SMB_MSTRDATAWR_REG 0x40 -+ -+#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 -+#define CCB_SMB_MSTRWRSTS_SHIFT 31 -+ -+#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF -+#define CCB_SMB_MSTRWRDATA_SHIFT 0 -+ -+ -+/* --- */ -+#define CCB_SMB_MSTRDATARD_REG 0x44 -+ -+#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 -+#define CCB_SMB_MSTRRDSTS_SHIFT 30 -+ -+#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 -+#define CCB_SMB_MSTRRDPECERR_SHIFT 29 -+ -+#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF -+#define CCB_SMB_MSTRRDDATA_SHIFT 0 -+ -+ -+/* --- */ -+#define CCB_SMB_SLVDATAWR_REG 0x48 -+ -+#define CCB_SMB_SLVWRSTS_MASK 0x80000000 -+#define CCB_SMB_SLVWRSTS_SHIFT 31 -+ -+#define CCB_SMB_SLVWRDATA_MASK 0x000000FF -+#define CCB_SMB_SLVWRDATA_SHIFT 0 -+ -+ -+/* --- */ -+#define CCB_SMB_SLVDATARD_REG 0x4C -+ -+#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 -+#define CCB_SMB_SLVRDSTS_SHIFT 30 -+ -+#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 -+#define CCB_SMB_SLVRDERRSTS_SHIFT 28 -+ -+#define CCB_SMB_SLVRDDATA_MASK 0x000000FF -+#define CCB_SMB_SLVRDDATA_SHIFT 0 -+ -+#endif /* __IPROC_SMBUS_REGS_H__ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/i2c/busses/xgs_iproc_smbus.c b/drivers/i2c/busses/xgs_iproc_smbus.c ---- a/drivers/i2c/busses/xgs_iproc_smbus.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/i2c/busses/xgs_iproc_smbus.c 2017-11-09 17:53:33.709223000 +0800 -@@ -0,0 +1,2014 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iproc_smbus_regs.h" -+#include "iproc_smbus_defs.h" -+#include "iproc_smbus.h" -+ -+#ifdef CONFIG_OF -+#include -+#include -+#include -+#endif /* CONFIG_OF */ -+ -+#undef IPROC_SMB_DBG -+ -+/* Support I2C devices without length field xfer*/ -+//#define SMB_BLOCK_XFER_VARIANT -+ -+#define SMB_MAX_DATA_SIZE 32 -+#define SMB_BLK_XFER_TEST -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) -+#define init_MUTEX(x) sema_init(x,1) -+#endif -+ -+static struct proc_dir_entry *gProcParent=NULL; -+//static int use_svk_version; -+#undef CONFIG_USE_SVK_VERSION -+ -+static int smb_in_intr; -+ -+static struct iproc_smb_drv_int_data *iproc_smbus_list = NULL; -+static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev); -+ -+/* Function to read a value from specified register. */ -+static unsigned int iproc_smb_reg_read(unsigned long reg_addr) -+{ -+ unsigned int val; -+ -+ val = ioread32((void *)reg_addr); -+ -+#ifdef IPROC_SMB_DBG -+ if (!smb_in_intr) { -+ printk(KERN_DEBUG "\nRd: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); -+ } -+#endif -+ -+ return(val); -+} -+ -+/* Function to write a value ('val') in to a specified register. */ -+static int iproc_smb_reg_write(unsigned long reg_addr, unsigned int val) -+{ -+ iowrite32(val, (void *)reg_addr); -+ -+#ifdef IPROC_SMB_DBG -+ if (!smb_in_intr) { -+ printk(KERN_DEBUG "\nWr: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); -+ } -+#endif -+ -+ return (0); -+} -+ -+#ifdef IPROC_SMB_DBG -+static int iproc_dump_smb_regs(struct iproc_smb_drv_int_data *dev) -+{ -+ unsigned int regval; -+ unsigned long base_addr = (unsigned long)dev->block_base_addr; -+ -+ printk(KERN_DEBUG "\n----------------------------------------------"); -+ -+ printk(KERN_DEBUG "\nBase addr=0x%08X", (unsigned int)base_addr); -+ -+ printk(KERN_DEBUG "%s: Dumping SMBus registers... ", __func__); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_CFG_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_CFG_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_TIMGCFG_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_ADDR_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_ADDR_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRFIFOCTL_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_MSTRFIFOCTL_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVFIFOCTL_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_SLVFIFOCTL_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_BITBANGCTL_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_BITBANGCTL_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRCMD_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_MSTRCMD_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVCMD_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_SLVCMD_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_EVTEN_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_EVTSTS_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATAWR_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATAWR_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATARD_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATARD_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATAWR_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_SLVDATAWR_REG=0x%08X", regval); -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATARD_REG); -+ printk(KERN_DEBUG "\nCCB_SMB_SLVDATARD_REG=0x%08X", regval); -+ -+ printk(KERN_DEBUG "\n----------------------------------------------\n\n"); -+ -+ return(0); -+} -+#endif /* IPROC_SMB_DBG */ -+ -+static irqreturn_t iproc_smb_isr(int irq, void*devid) -+{ -+ struct iproc_smb_drv_int_data *dev = -+ (struct iproc_smb_drv_int_data *)devid; -+ unsigned int intsts; -+ unsigned int regval; -+ -+ -+ smb_in_intr = 1; -+ -+ intsts = iproc_smb_reg_read((unsigned long)dev->block_base_addr + -+ CCB_SMB_EVTSTS_REG); -+ -+ dev->smb_counters.last_int_sts = intsts; -+ -+ if (!intsts) { -+ -+ /* Likely received a spurious interrupt */ -+ -+ return IRQ_NONE; -+ -+ } -+ -+ /* Clear interrupts */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + -+ CCB_SMB_EVTSTS_REG, intsts); -+ -+ /* Master read or write complete */ -+ if ((intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) || -+ (intsts & CCB_SMB_MSTRRXEVTSTS_MASK)) { -+ -+ if (intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) { -+ -+ dev->smb_counters.mstr_start_busy_cnt++; -+ -+ } -+ -+ if (intsts & CCB_SMB_MSTRRXEVTSTS_MASK) { -+ -+ dev->smb_counters.mstr_rx_evt_cnt++; -+ -+ } -+ -+ /* In case of a receive transaction, data will be copied in the recv -+ * function -+ */ -+ complete(&dev->ses_done); -+ -+ } -+ -+ /* If RX FIFO was full we can either read and then flush the FIFO. Or, only -+ * flush the FIFO (since the client process did not read the data on time), -+ * and then the client process can restart the transaction -+ * For now, we will flush the later action. -+ */ -+ if (intsts & CCB_SMB_MSTRRXFIFOFULLSTS_MASK) { -+ -+ dev->smb_counters.mstr_rx_fifo_full_cnt++; -+ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + -+ CCB_SMB_MSTRFIFOCTL_REG); -+ -+ regval |= CCB_SMB_MSTRRXFIFOFLSH_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + -+ CCB_SMB_MSTRFIFOCTL_REG, regval); -+ -+ complete(&dev->ses_done); -+ -+ } -+ -+ smb_in_intr = 0; -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Function to ensure that the previous transaction was completed before -+ * initiating a new transaction. It can also be used in polling mode to -+ * check status of completion of a command -+ */ -+static int iproc_smb_startbusy_wait(struct iproc_smb_drv_int_data *dev) -+{ -+ unsigned int regval; -+ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + -+ CCB_SMB_MSTRCMD_REG); -+ -+ /* Check if an operation is in progress. During probe it won't be. -+ * But when shutdown/remove was called we want to make sure that -+ * the transaction in progress completed -+ */ -+ if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { -+ unsigned int i = 0; -+ -+ do { -+ -+ msleep(1); /* Wait for 1 msec */ -+ -+ i++; -+ -+ regval = iproc_smb_reg_read( -+ (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); -+ -+ /* If start-busy bit cleared, exit the loop */ -+ } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && -+ (i < IPROC_SMB_MAX_RETRIES)); -+ -+ if (i >= IPROC_SMB_MAX_RETRIES) { -+ printk(KERN_ERR "%s: %s START_BUSY bit didn't clear, exiting\n", -+ __func__, dev->adapter.name); -+ return -ETIMEDOUT; -+ -+ } -+ -+ } -+ -+ return 0; -+} -+ -+ -+static unsigned int smbus0_sdaRecoveryCnt = 0, smbus0_sdaFailedCnt = 0, smbus0_startBusyCnt = 0; -+static unsigned int smbus1_sdaRecoveryCnt = 0, smbus1_sdaFailedCnt = 0, smbus1_startBusyCnt = 0; -+ -+/* -+ * Function to recover SMB hangs caused stuck master START_BUSY. -+ * Returns 0 if recovery procedure executed successfully. -+ * Returns -1 if recovery failed. -+ */ -+static int iproc_smb_startbusy_recovery(struct iproc_smb_drv_int_data *dev) -+{ -+ int rc = -1; -+ unsigned int recoveryCnt; -+ -+ if (dev->adapter.nr == 0) { -+ recoveryCnt = ++smbus0_startBusyCnt; -+ } -+ else { -+ recoveryCnt = ++smbus1_startBusyCnt; -+ } -+ -+ printk(KERN_INFO "%s: %s START_BUSY recovery #%d \n", __func__, dev->adapter.name, recoveryCnt); -+ -+ /* reset the SMBus block, wait a minimum of 50 uSecs and then re-initialize */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, CCB_SMB_CFG_RST_MASK); -+ udelay(60); -+ -+ if ( iproc_smbus_block_init(dev) == 0 ) { -+ rc = 0; -+ } -+ -+ return rc; -+} -+ -+ -+ -+/* -+ * Function to recover SMB hang caused by a slave device holding SDA low. -+ * Returns 0 if recovery procedure executed successfully. -+ * Returns -1 if recovery failed. -+ */ -+ -+static int iproc_smb_sda_low_recovery(struct iproc_smb_drv_int_data *dev) -+{ -+ unsigned int bbReg, cfgReg, cfgSave, recoveryCnt, failedCnt, i; -+ int rc = -1; -+ -+ -+ /* enable bit-bang */ -+ cfgSave = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); -+ cfgReg = cfgSave; -+ cfgReg |= CCB_SMB_CFG_BITBANGEN_MASK; -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); -+ udelay(50); -+ -+ /* start with clock and SDA set high */ -+ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); -+ -+ bbReg |= (CCB_SMB_SMBCLKOUTEN_MASK | CCB_SMB_SMBDATAOUTEN_MASK); -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(5); /* should be sufficient for 100 KHz bus */ -+ -+ /* set up to toggle the clock line with SDA out held high for 9 cycles */ -+ for (i=0; i<18; i++) -+ { -+ /* toggle CLK out */ -+ if ( (bbReg & CCB_SMB_SMBCLKOUTEN_MASK) == 0 ) { -+ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ -+ } -+ else { -+ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ -+ } -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(5); -+ } -+ -+ /* check bit 29 -- SMBDAT_IN and make sure SDA not being held low any more */ -+ for ( i=0; i<10; i++ ) -+ { -+ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); -+ bbReg &= CCB_SMB_SMBDATAIN_MASK; -+ -+ if (bbReg) -+ break; -+ -+ udelay(1); -+ } -+ -+ if ( bbReg == 0 ) { -+ /* SDA is still low */ -+ if (dev->adapter.nr == 0) { -+ failedCnt = ++smbus0_sdaFailedCnt; -+ } -+ else { -+ failedCnt = ++smbus1_sdaFailedCnt; -+ } -+ printk(KERN_INFO "\n%s: %s SDA release #%d FAILED.\n", __func__, dev->adapter.name, failedCnt); -+ } -+ else { -+ if (dev->adapter.nr == 0) { -+ recoveryCnt = ++smbus0_sdaRecoveryCnt; -+ } -+ else { -+ recoveryCnt = ++smbus1_sdaRecoveryCnt; -+ } -+ -+ printk(KERN_INFO "%s: %s SDA release #%d SUCCESSFUL.\n", __func__, dev->adapter.name, recoveryCnt); -+ rc = 0; -+ } -+ -+ -+ /* manually issue a stop by transitioning SDA from low to high with clock held high */ -+ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); -+ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(2); -+ -+ bbReg &= ~CCB_SMB_SMBDATAOUTEN_MASK; /* drop SDA low */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(2); -+ -+ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(5); -+ -+ bbReg |= CCB_SMB_SMBDATAOUTEN_MASK; /* pull SDA high */ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); -+ udelay(2); -+ -+ -+ /* disable bit-bang and then re-enable the SMB with the saved configuration */ -+ cfgReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); -+ cfgReg &= ~CCB_SMB_CFG_BITBANGEN_MASK; -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); -+ udelay(10); -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgSave); -+ -+ return rc; -+} -+ -+ -+/* -+ * Function to recover SMB hang caused by a slave device hold SDA low. -+ * Returns 0 if recovery procedure executed successfully. -+ * Returns -1 if recovery failed. -+ */ -+static int iproc_smb_timeout_recovery(struct iproc_smb_drv_int_data *dev) -+{ -+ unsigned int bbReg, mCmdReg; -+ int rc = -1; -+ -+ /* read bit-bang control. If SDA low, attempt SDA release recovery */ -+ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); -+ -+ if ( (bbReg & CCB_SMB_SMBDATAIN_MASK) == 0 ) { -+ if ( iproc_smb_sda_low_recovery( dev ) == 0 ) { -+ rc = 0; -+ } -+ } -+ -+ /* regardless of whether there was an SDA hang or not, see if START_BUSY stuck high */ -+ mCmdReg = iproc_smb_reg_read( (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG ); -+ if ( mCmdReg & CCB_SMB_MSTRSTARTBUSYCMD_MASK ) { -+ /* attempt to recover the bus */ -+ if (iproc_smb_startbusy_recovery(dev) == 0) { -+ rc = 0; -+ } -+ } -+ -+ return rc; -+ -+} -+ -+/* -+ * This function copies data to SMBus's Tx FIFO. Valid for write transactions -+ * only -+ * -+ * base_addr: Mapped address of this SMBus instance -+ * dev_addr: SMBus (I2C) device address. We are assuming 7-bit addresses -+ * initially -+ * info: Data to copy in to Tx FIFO. For read commands, the size should be -+ * set to zero by the caller -+ * -+ */ -+static void iproc_smb_write_trans_data(unsigned long base_addr, -+ unsigned short dev_addr, -+ struct iproc_xact_info *info) -+{ -+ unsigned int regval; -+ unsigned int i; -+ unsigned int num_data_bytes = 0; -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\n%s: dev_addr=0x%X, offset=%u, cmd_valid=%u, size=%u\n", __func__, dev_addr, info->command, info->cmd_valid, info->size); -+#endif /* IPROC_SMB_DBG */ -+ -+ /* Write SMBus device address first */ -+ /* Note, we are assuming 7-bit addresses for now. For 10-bit addresses, -+ * we may have one more write to send the upper 3 bits of 10-bit addr -+ */ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, dev_addr); -+ -+ /* If the protocol needs command code, copy it */ -+ if (info->cmd_valid == true) { -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->command); -+ } -+ -+ /* Depending on the SMBus protocol, we need to write additional transaction -+ * data in to Tx FIFO. Refer to section 5.5 of SMBus spec for sequence for a -+ * transaction -+ */ -+ switch (info->smb_proto) { -+ -+ case SMBUS_PROT_RECV_BYTE: -+ /* No additional data to be written */ -+ num_data_bytes = 0; -+ break; -+ -+ case SMBUS_PROT_SEND_BYTE: -+ num_data_bytes = info->size; -+ break; -+ -+ case SMBUS_PROT_RD_BYTE: -+ case SMBUS_PROT_RD_WORD: -+ case SMBUS_PROT_BLK_RD: -+ /* Write slave address with R/W~ set (bit #0) */ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, dev_addr | 0x1); -+ num_data_bytes = 0; -+ break; -+ -+ case SMBUS_PROT_WR_BYTE: -+ case SMBUS_PROT_WR_WORD: -+ /* No additional bytes to be written. Data portion is written in the -+ * 'for' loop below -+ */ -+ num_data_bytes = info->size; -+ -+ /* Note for hx4 eeprom (at24c64). the low addr bytes can be passed -+ * in to 1st byte of info->data -+ */ -+ break; -+ -+ case SMBUS_PROT_BLK_WR: -+ /* 3rd byte is byte count */ -+#ifndef SMB_BLOCK_XFER_VARIANT -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); -+#endif -+ num_data_bytes = info->size; -+ break; -+ -+ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: -+ /* Write byte count */ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); -+ num_data_bytes = info->size; -+ break; -+ -+ default: -+ break; -+ -+ } -+ -+ /* Copy actual data from caller, next. In general, for reads, no data is -+ * copied -+ */ -+ for (i = 0; num_data_bytes; --num_data_bytes, i++) { -+ -+ /* For the last byte, set MASTER_WR_STATUS bit. For block rd/wr process -+ * call, we need to program slave addr after copying data byte(s), so -+ * master status bit is set later, after the loop -+ */ -+ if ((num_data_bytes == 1) && -+ (info->smb_proto != SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { -+ regval = info->data[i] | CCB_SMB_MSTRWRSTS_MASK; -+ } -+ else { -+ regval = info->data[i]; -+ } -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, regval); -+ -+ } -+ -+ if (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL) { -+ /* Write device address needed during repeat start condition */ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, -+ CCB_SMB_MSTRWRSTS_MASK | dev_addr | 0x1); -+ } -+ -+ return; -+} -+ -+static int iproc_smb_data_send(struct i2c_adapter *adapter, -+ unsigned short addr, -+ struct iproc_xact_info *info) -+{ -+ int rc; -+ unsigned int regval; -+ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); -+ unsigned long time_left; -+ -+ -+ /* Make sure the previous transaction completed */ -+ rc = iproc_smb_startbusy_wait(dev); -+ -+ if (rc < 0) { -+ printk(KERN_ERR "%s: Send: %s bus is busy, attempt recovery \n", __func__, dev->adapter.name); -+ /* attempt to recover the bus */ -+ if (iproc_smb_startbusy_recovery(dev) != 0) { -+ return rc; -+ } -+ } -+ -+ if (dev->enable_evts == ENABLE_INTR) { -+ -+ /* Enable start_busy interrupt */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + -+ CCB_SMB_EVTEN_REG); -+ -+ regval |= CCB_SMB_MSTRSTARTBUSYEN_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + -+ CCB_SMB_EVTEN_REG, regval); -+ -+ /* Mark as incomplete before sending the data */ -+ reinit_completion(&dev->ses_done); -+ -+ } -+ -+ /* Write transaction bytes to Tx FIFO */ -+ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); -+ -+ /* Program master command register (0x30) with protocol type and set -+ * start_busy_command bit to initiate the write transaction -+ */ -+ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | -+ CCB_SMB_MSTRSTARTBUSYCMD_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG, regval); -+ if (dev->enable_evts == ENABLE_INTR) { -+ /* -+ * Block waiting for the transaction to finish. When it's finished, -+ * we'll be signaled by an interrupt -+ */ -+ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); -+ /* Disable start_busy interrupt */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG); -+ regval &= ~CCB_SMB_MSTRSTARTBUSYEN_MASK; -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ if (time_left == 0) { -+ printk (KERN_INFO "%s: Send: %s timeout accessing device x%02x\n", -+ __func__, dev->adapter.name, addr); -+ -+ /* attempt to recover the bus */ -+ rc = iproc_smb_timeout_recovery(dev); -+ if ( rc != 0 ) { -+ return -ETIMEDOUT; -+ } -+ else { -+ return -ECOMM; -+ } -+ } -+ } -+ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); -+ -+ /* If start_busy bit cleared, check if there are any errors */ -+ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { -+ /* start_busy bit cleared, check master_status field now */ -+ regval &= CCB_SMB_MSTRSTS_MASK; -+ regval >>= CCB_SMB_MSTRSTS_SHIFT; -+ -+ if (regval != MSTR_STS_XACT_SUCCESS) { -+ /* We can flush Tx FIFO here */ -+ printk(KERN_ERR "\n\n%s:Send: %s Error in transaction %d to device x%02x, exiting\n", -+ __func__, dev->adapter.name, regval, addr); -+ -+ return -EREMOTEIO; -+ } -+ } -+ -+ return(0); -+} -+ -+static int iproc_smb_data_recv(struct i2c_adapter *adapter, -+ unsigned short addr, -+ struct iproc_xact_info *info, -+ unsigned int *num_bytes_read) -+{ -+ int rc; -+ unsigned int regval; -+ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); -+ unsigned long time_left; -+ -+ /* Make sure the previous transaction completed */ -+ rc = iproc_smb_startbusy_wait(dev); -+ -+ if (rc < 0) { -+ printk(KERN_ERR "%s: Receive: %s bus is busy, attempt recovery \n", __func__, dev->adapter.name); -+ /* attempt to recover the bus */ -+ if (iproc_smb_startbusy_recovery(dev) != 0) { -+ return rc; -+ } -+ } -+ -+ if (dev->enable_evts == ENABLE_INTR) { -+ /* Enable start_busy interrupt */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG); -+ -+ /* Set Rx_event_en bit for notification of reception event */ -+ regval |= (CCB_SMB_MSTRSTARTBUSYEN_MASK); -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ /* Mark as incomplete before sending the data */ -+ reinit_completion(&dev->ses_done); -+ } -+ -+ /* Program all transaction bytes into master Tx FIFO */ -+ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); -+ -+ /* Program master command register (0x30) with protocol type and set -+ * start_busy_command bit to initiate the write transaction -+ */ -+ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | -+ CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + -+ CCB_SMB_MSTRCMD_REG, regval); -+ -+ if (dev->enable_evts == ENABLE_INTR) { -+ /* -+ * Block waiting for the transaction to finish. When it's finished, -+ * we'll be signaled by an interrupt -+ */ -+ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); -+ -+ /* Disable start_busy and rx_event interrupts. Above call has handled -+ * the interrupt -+ */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG); -+ regval &= ~(CCB_SMB_MSTRSTARTBUSYEN_MASK); -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ if (time_left == 0) { -+ printk (KERN_ERR "\n%s: Receive: %s timeout accessing device 0x%02x\n", -+ __func__, dev->adapter.name, addr); -+ /* attempt to recover the bus */ -+ rc = iproc_smb_timeout_recovery(dev); -+ if ( rc != 0 ) { -+ return -ETIMEDOUT; -+ } -+ else { -+ return -ECOMM; -+ } -+ } -+ } -+ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); -+ -+ /* If start_busy bit cleared, check if there are any errors */ -+ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { -+ /* start_busy bit cleared, check master_status field now */ -+ regval &= CCB_SMB_MSTRSTS_MASK; -+ regval >>= CCB_SMB_MSTRSTS_SHIFT; -+ -+ if (regval != MSTR_STS_XACT_SUCCESS) { -+ /* We can flush Tx FIFO here */ -+ printk(KERN_INFO "\n%s: %s Error in transaction %d to device x%02x, exiting\n", -+ __func__, dev->adapter.name, regval, addr); -+ return -EREMOTEIO; -+ } -+ } -+ -+ /* In the isr we will read the received byte, and also deal with -+ * rx fifo full event. The above check is for timeout error. If needed -+ * we may move it to rx isr -+ */ -+ -+ /* For block read, protocol (hw) returns byte count, as the first byte */ -+ if ((info->smb_proto == SMBUS_PROT_BLK_RD) || (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { -+ int i, adj; -+#ifndef SMB_BLOCK_XFER_VARIANT -+ /* Read received byte(s) */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRDATARD_REG); -+ *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; -+#else -+ *num_bytes_read = info->size; -+#endif -+ adj = 0; -+ -+ /* Limit to reading a max of 32 bytes only; just a safeguard. If -+ * # bytes read is a number > 32, check transaction set up, and contact -+ * hw engg. Assumption: PEC is disabled -+ */ -+ /* SMBUS spec ver. 3 (2015) extends max block transfer byte count from 32 to 256 */ -+ /* Use SMB_MAX_DATA_SIZE (according to HW FIFO) instead of I2C_SMBUS_BLOCK_MAX (defined in Linux)*/ -+ /* Current SMBUS HW FIFO length is 64B. For block write xfer, the first three FIFO entries are for slave adress, register ofset, and length count*/ -+ //for (i = 0; (i < *num_bytes_read) && (i < (I2C_SMBUS_BLOCK_MAX - adj)); i++) { -+ for (i = 0; (i < *num_bytes_read) && (i < (SMB_MAX_DATA_SIZE - adj)); i++) { -+ /* Read Rx FIFO for data bytes */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRDATARD_REG); -+ info->data[i + adj] = regval & CCB_SMB_MSTRRDDATA_MASK; -+ } -+ /* To make sure that atmost 32 bytes are read */ -+ *num_bytes_read = i + adj; -+ } -+ else { -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRDATARD_REG); -+ *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; -+ *num_bytes_read = 1; -+ if (info->smb_proto == SMBUS_PROT_RD_WORD) { -+ /* Read Rx FIFO for data bytes */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_MSTRDATARD_REG); -+ info->data[1] = regval & CCB_SMB_MSTRRDDATA_MASK; -+ *num_bytes_read = 2; -+ } -+ } -+ -+ return(0); -+} -+ -+static int iproc_smb_xfer(struct i2c_adapter *i2c_adap, u16 addr, -+ unsigned short flags, char read_write, -+ u8 command, int size, union i2c_smbus_data *data) -+{ -+ int rc = 0; -+ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(i2c_adap); -+ struct iproc_xact_info info; -+ unsigned int num_bytes_read = 0; -+ int smb_xfer_size; -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\n%s: dev=0x%08X\n", __func__, (unsigned int)dev); -+#endif -+ -+ down(&dev->xfer_lock); -+ -+ addr <<= 1; -+ -+ switch (size /* protocol */) { -+ -+ case I2C_SMBUS_BYTE: -+ info.cmd_valid = false; -+ info.command = command; /* not used */ -+ if (read_write == I2C_SMBUS_WRITE) { -+ info.data = &command; -+ } -+ else { -+ info.data = &data->byte; -+ } -+ info.size = 1; -+ info.flags = flags; -+ if (read_write == I2C_SMBUS_READ) { -+ addr |= 0x1; /* Read operation */ -+ info.smb_proto = SMBUS_PROT_RECV_BYTE; -+ info.data = &data->byte; -+ } -+ else { -+ info.smb_proto = SMBUS_PROT_SEND_BYTE; -+ } -+ break; -+ -+ case I2C_SMBUS_BYTE_DATA: -+ info.cmd_valid = true; -+ info.command = command; -+ info.data = &data->byte; -+ info.size = 1; -+ info.flags = flags; -+ -+ if (read_write == I2C_SMBUS_READ) { -+ info.smb_proto = SMBUS_PROT_RD_BYTE; -+ } -+ else { -+ info.smb_proto = SMBUS_PROT_WR_BYTE; -+ //info.smb_proto = SMBUS_PROT_WR_WORD; /* TEMP chg. remove later */ -+ } -+ break; -+ -+ case I2C_SMBUS_WORD_DATA: -+ info.cmd_valid = true; -+ info.command = command; -+ info.data = (unsigned char *)(&data->word); -+ info.size = 2; -+ info.flags = flags; -+ if (read_write == I2C_SMBUS_READ) { -+ info.smb_proto = SMBUS_PROT_RD_WORD; -+ /* Protocol(hw) returns data byte count as part of response, -+ for smbus compliant devices */ -+ // info.size = 0; -+ } -+ else { -+ info.smb_proto = SMBUS_PROT_WR_WORD; -+ info.size = 2; -+ } -+ break; -+ -+ case I2C_SMBUS_BLOCK_DATA: -+ case I2C_SMBUS_I2C_BLOCK_DATA: -+ info.cmd_valid = true; -+ info.command = command; -+ info.data = &data->block[1]; -+ info.flags = flags; -+ -+ if (read_write == I2C_SMBUS_READ) { -+ info.smb_proto = SMBUS_PROT_BLK_RD; -+ /* See desc for RD_BYTE_COUNT in reg 0x30 about 'block read'. -+ * If '0', protocol(hw) returns data byte count as part of -+ * response. -+ */ -+#ifdef SMB_BLOCK_XFER_VARIANT -+ info.size = data->block[0]; -+#else -+ info.size = 0; -+#endif -+ } -+ else { -+ info.smb_proto = SMBUS_PROT_BLK_WR; -+ info.size = data->block[0]; /* i2c-core passes the length in this field */ -+ } -+ -+ break; -+ -+ case I2C_SMBUS_BLOCK_PROC_CALL: -+ info.cmd_valid = true; -+ info.command = command; -+ info.data = &data->block[1]; -+ info.flags = flags; -+ info.size = data->block[0]; -+ info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: Unsupported transaction %d\n", __func__, size); -+ up(&dev->xfer_lock); -+ return -EINVAL; -+ -+ } -+ -+ /* Handle of large packet by spliting into SMB_MAX_DATA_SIZE packet */ -+ smb_xfer_size = (int)info.size; -+ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) -+ data->block[0] = 0; -+ while ( smb_xfer_size ) { -+ if (info.size >= SMB_MAX_DATA_SIZE) -+ info.size = SMB_MAX_DATA_SIZE; -+ -+ if (read_write == I2C_SMBUS_READ) { -+ /* Refer to i2c_smbus_read_byte for params passed. */ -+ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); -+ /* if failed due to bus hang, but recovered, retry once */ -+ if (rc == -ECOMM) { -+ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); -+ } -+ /* For block read call, we pass the actual amount of data sent by -+ * slave, as expected by std Linux API */ -+ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || -+ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { -+ if (rc == 0) { -+ data->block[0] += num_bytes_read; -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "%s: num bytes read=%u\n", -+ __func__, data->block[0]); -+#endif -+ } -+ } -+ } -+ else { -+ /* Refer to i2c_smbus_write_byte params passed. */ -+ rc = iproc_smb_data_send(i2c_adap, addr, &info); -+ /* if failed due to bus hang, but recovered, retry */ -+ if (rc == -ECOMM) { -+ rc = iproc_smb_data_send(i2c_adap, addr, &info); -+ } -+ } -+ -+ if (rc < 0) { -+ printk(KERN_INFO "%s %s: %s error accessing device 0x%X rc=%d", __func__, dev->adapter.name, -+ (read_write == I2C_SMBUS_READ) ? "Read" : "Write", addr, rc); -+ up(&dev->xfer_lock); -+ return -EREMOTEIO; -+ } -+ if (info.size == SMB_MAX_DATA_SIZE) { -+ smb_xfer_size -= SMB_MAX_DATA_SIZE; -+ info.size = smb_xfer_size; -+ info.data += SMB_MAX_DATA_SIZE; -+ info.command += SMB_MAX_DATA_SIZE; /* Adjust I2c device register offset. Not required if the access register addr pointing to FIFO */ -+ } -+ else -+ break; -+ } -+ msleep(1); -+ up(&dev->xfer_lock); -+ -+ return (rc); -+} -+ -+static int -+proc_debug_read(struct file *file, char __user *buffer, size_t count, loff_t *off) -+{ -+ unsigned int len = 0; -+ struct iproc_smb_drv_int_data *dev = (struct iproc_smb_drv_int_data *) PDE_DATA (file->f_inode); -+ -+ if (off > 0) -+ return 0; -+ -+ len += sprintf(buffer + len, "Debug print is %s\n", -+ dev->debug ? "enabled" : "disabled"); -+ -+ return len; -+} -+ -+/* Command interface for reading/writing to various I2C/SMBus devices */ -+#ifndef SMB_BLK_XFER_TEST -+static int -+proc_debug_write(struct file *file, const char __user *buffer, -+ unsigned long count, void *data) -+{ -+ struct iproc_smb_drv_int_data *dev = (struct iproc_smb_drv_int_data *)data; -+ int rc; -+ unsigned char kbuf[MAX_PROC_BUF_SIZE]; -+ union i2c_smbus_data i2cdata; -+ unsigned int val, i2cdev_addr, rd_wr_op; -+ int addr; -+ -+ if (count > MAX_PROC_BUF_SIZE) { -+ count = MAX_PROC_BUF_SIZE; -+ } -+ -+ rc = copy_from_user(kbuf, buffer, count); -+ if (rc) { -+ printk(KERN_ERR "%s: copy_from_user failed status=%d\n", __func__, rc); -+ return -EFAULT; -+ } -+ -+ rc = sscanf(kbuf, "%u %u %d %u", &rd_wr_op, &i2cdev_addr, &addr, &val); -+ if (rc != 4) { -+ printk(KERN_ERR "\necho args > %s", PROC_ENTRY_DEBUG); -+ printk(KERN_ERR "\nargs (all values should be in decimal)):"); -+ printk(KERN_ERR "\nrd_wr_op: 1 = read, 0 = write"); -+ printk(KERN_ERR "\ni2cdev_addr: I2C device address in decimal"); -+ printk(KERN_ERR "\noffset: offset of location within I2C device"); -+ printk(KERN_ERR "\naddr -1 if offset not applicable"); -+ printk(KERN_ERR "\nval: For write op: 8-bit value.\n" -+ " For read op: not used, may be 0\n\n"); -+ return count; -+ } -+ -+ printk("\nArg values :"); -+ printk("\nrd_wr_op = %u", rd_wr_op); -+ printk("\ni2cdev_addr = 0x%X", i2cdev_addr); -+ printk("\noffset = %d", addr); -+ printk("\nval = %u", val); -+ if (rd_wr_op > 1) { -+ printk(KERN_ERR "Error: Invalid rd_wr_op value %u\n", rd_wr_op); -+ return count; -+ } -+ -+ if (i2cdev_addr > 127) { -+ printk(KERN_ERR "Error: i2cdev_addr must be 7-bit value\n"); -+ return count; -+ } -+ -+ if (addr > 255) { -+ printk(KERN_ERR "Error: offset out of range for this device\n"); -+ return count; -+ } -+ -+ printk("Command can execute slow, please wait...\n"); -+ -+ if (rd_wr_op == 0) { /* Write operation */ -+ i2cdata.byte = val; -+ if (addr == -1) { -+ /* Device does not support, or require an offset to write to the -+ * location -+ */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, (unsigned char)0, -+ I2C_SMBUS_BYTE, &i2cdata); -+ } else { -+ /* Address required for write access */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, -+ &i2cdata); -+ } -+ -+ if (rc) { -+ printk(KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," -+ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); -+ /* return -EFAULT; */ -+ } else { -+ printk("Write OK.Wrote 0x%X at addr %u\n", val, addr); -+ } -+ -+ msleep(1); /* Delay required, since smb(i2c) interface is slow */ -+ } -+ -+ if (rd_wr_op == 1) { /* Read operation */ -+ if (addr == -1) { -+ /* Device does not support, or require an offset to read from the -+ * location -+ */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); -+ } else { -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); -+ } -+ -+ if (rc) { -+ printk(KERN_ERR "%s: iproc_smb_xfer failed status=%d\n", __func__, rc); -+ /* return -EFAULT; */ -+ } else { -+ printk("Read OK.Value read at %u = 0x%X\n", addr, i2cdata.byte); -+ } -+ msleep(1); /* Delay required, since smb(i2c) interface is slow */ -+ } -+ -+#ifdef IPROC_SMB_DBG -+ iproc_dump_smb_regs(dev); -+#endif /* IPROC_SMB_DBG */ -+ -+ printk("Last intr sts = 0x%08X\n", dev->smb_counters.last_int_sts); -+ printk("mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", -+ dev->smb_counters.mstr_start_busy_cnt, -+ dev->smb_counters.mstr_rx_evt_cnt, -+ dev->smb_counters.mstr_rx_fifo_full_cnt); -+ -+ return count; -+} -+#endif -+ -+#ifdef SMB_BLK_XFER_TEST -+static int -+proc_debug_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) -+{ -+ struct iproc_smb_drv_int_data *dev = (struct iproc_smb_drv_int_data *) PDE_DATA (file->f_inode); -+ int rc; -+ unsigned char kbuf[MAX_PROC_BUF_SIZE]; -+ union i2c_smbus_data i2cdata; -+ unsigned int val, i2cdev_addr, rd_wr_op; -+ int addr; -+ int i, j; -+ unsigned int burst_len, repated_cnt, total_cnt; -+ -+ if (count > MAX_PROC_BUF_SIZE) { -+ count = MAX_PROC_BUF_SIZE; -+ } -+ -+ rc = copy_from_user(kbuf, buffer, count); -+ -+ if (rc) { -+ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); -+ return -EFAULT; -+ -+ } -+ -+ rc = sscanf(kbuf, "%u %u %d %u %u %u", &rd_wr_op, &i2cdev_addr, &addr, &val, &burst_len, &repated_cnt); -+ if (rc != 6) { -+ burst_len = 1; -+ repated_cnt = 1; -+ -+ if (rc < 4 ) { -+ printk(KERN_ERR "\necho args > %s", PROC_ENTRY_DEBUG); -+ printk(KERN_ERR "\nargs (all values should be in decimal)):"); -+ printk(KERN_ERR "\nrd_wr_op: 1 = read, 0 = write"); -+ printk(KERN_ERR "\ni2cdev_addr: I2C device address in decimal"); -+ printk(KERN_ERR "\noffset: offset of location within I2C device"); -+ printk(KERN_ERR "\naddr -1 if offset not applicable"); -+ printk(KERN_ERR "\nval: For write op: 8-bit value.\n" -+ " For read op: not used, may be 0\n\n"); -+ printk(KERN_ERR "\burst_length: write block transfer byte length (<=8 for many EEPROM devices)"); -+ printk(KERN_ERR "\repated_cnt: number of repated write transfer of burst_len"); -+ return -EFAULT; -+ } -+ } -+ total_cnt = burst_len * repated_cnt; -+ -+ printk(KERN_DEBUG "\nArg values :"); -+ printk(KERN_DEBUG "\nrd_wr_op = %u", rd_wr_op); -+ printk(KERN_DEBUG "\ni2cdev_addr = 0x%X", i2cdev_addr); -+ printk(KERN_DEBUG "\noffset = %d", addr); -+ printk(KERN_DEBUG "\nval = %u", val); -+ -+ if (rd_wr_op > 1) { -+ printk(KERN_ERR "\nError: Invalid rd_wr_op value %u\n", rd_wr_op); -+ return count; -+ } -+ -+ if (i2cdev_addr > 127) { -+ printk(KERN_ERR "\nError: i2cdev_addr must be 7-bit value\n"); -+ return count; -+ } -+ -+ if (addr > 255) { -+ printk(KERN_ERR "\nError: offset out of range for this device\n"); -+ return count; -+ } -+ -+ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); -+ -+ if (rd_wr_op == 0) { /* Write operation */ -+ if (total_cnt == 1) { -+#if defined(CONFIG_MACH_SB2) -+ /* Testing EEPROM that requires 2-byte address */ -+ unsigned char *data = &i2cdata.word; -+ data[0] = addr; -+ data[1] = val; -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, (unsigned char)0, I2C_SMBUS_WORD_DATA, &i2cdata); -+#else -+ i2cdata.byte = val; -+ if (addr == -1) { -+ /* Device does not support, or require an offset to write to the -+ * location -+ */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, (unsigned char)0, -+ I2C_SMBUS_BYTE, &i2cdata); -+ } -+ else { -+ /* Address required for write access */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, &i2cdata); -+ } -+#endif -+ if (rc) { -+ printk (KERN_ERR "\n%s: iproc_smb_xfer:write failed status=%d," -+ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); -+ /* return -EFAULT; */ -+ } -+ else { -+ printk(KERN_ERR "Write OK. Wrote 0x%X at addr %u\n", val, addr); -+ } -+ msleep(1); /* Delay required, since smb(i2c) interface is slow */ -+ } -+ else { -+/* test of block xfer: echo "0 80 0 0 8 16" > /proc/iproc-i2c/iproc-i2c0/iproc-i2c-dbg */ -+/* write to EEPROM I2c device (slave addr 80=0x50), addr offset: 0, vlaue: starting from 0, block xfer size:8, repeat_cnt:16 (EEPROM doesn't accept block xfer length > 8) */ -+/* repeat_cnt times of write block transfer */ -+/* for single address cycle I2C device only */ -+ for(j=0;jadapter, i2cdev_addr, 0x0, I2C_SMBUS_WRITE, -+ addr+j*burst_len, I2C_SMBUS_BLOCK_DATA, &i2cdata); -+ if (rc) { -+ printk (KERN_ERR "\n%s: iproc_smb_xfer:write failed status=%d," -+ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); -+ return -EFAULT; -+ } -+ msleep(1); -+ } -+ } /* ! total_cnt == 1 */ -+ } -+ -+ if (rd_wr_op == 1) { /* Read operation */ -+ if (total_cnt == 1) { -+#if defined(CONFIG_MACH_SB2) -+ /* Testing EEPROM that requires 2-byte address: to support random read, -+ * issue dummy write and then current address read -+ */ -+ i2cdata.byte = addr; -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, -+ I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE_DATA, &i2cdata); -+ if (rc) { -+ printk (KERN_ERR "\n%s: iproc_smb_xfer dummy write failed status=%d\n", __func__, rc); -+ } -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); -+#else -+ if (addr == -1) { -+ /* Device does not support, or require an offset to read from the -+ * location -+ */ -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); -+ } -+ else { -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); -+ } -+#endif -+ if (rc) { -+ printk (KERN_ERR "\n%s: iproc_smb_xfer failed status=%d\n", __func__, rc); -+ -+ /* return -EFAULT; */ -+ } -+ else { -+ printk(KERN_ERR "\nRead OK.\n--------Value read at %u = 0x%X\n", addr, i2cdata.byte); -+ } -+ -+ msleep(1); /* Delay required, since smb(i2c) interface is slow */ -+ } -+ else { -+ for (i = 1; i <= total_cnt; i++) -+ i2cdata.block[i] = 0; -+ i2cdata.block[0] = total_cnt; -+ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, -+ addr, I2C_SMBUS_BLOCK_DATA, &i2cdata); -+ if (rc) { -+ printk (KERN_ERR "\n%s: iproc_smb_xfer:read failed status=%d," -+ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); -+ return -EFAULT; -+ } -+ msleep(1); -+ for (i = 1; i <= total_cnt; i++) -+ printk("%d ", i2cdata.block[i]); -+ } /* ! total_cnt == 1 */ -+ } -+ -+#ifdef IPROC_SMB_DBG -+ iproc_dump_smb_regs(dev); -+#endif -+ -+ printk(KERN_DEBUG "Last intr sts = 0x%08X\n", dev->smb_counters.last_int_sts); -+ -+ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n", -+ dev->smb_counters.mstr_start_busy_cnt, -+ dev->smb_counters.mstr_rx_evt_cnt, -+ dev->smb_counters.mstr_rx_fifo_full_cnt); -+ -+ return count; -+} -+#endif -+ -+ -+#ifdef CONFIG_USE_SVK_VERSION -+/* Written for SVK boards */ -+static int -+proc_debug_write_svk(struct file *file, const char __user *buffer, size_t count, loff_t *off) -+{ -+ struct iproc_smb_drv_int_data *dev = (struct iproc_smb_drv_int_data *) PDE_DATA (file->f_inode); -+ int rc; -+ unsigned int debug; -+ unsigned char kbuf[MAX_PROC_BUF_SIZE]; -+ union i2c_smbus_data i2cdata; -+ unsigned int val, addr; -+ -+ if (count > MAX_PROC_BUF_SIZE) { -+ count = MAX_PROC_BUF_SIZE; -+ } -+ -+ rc = copy_from_user(kbuf, buffer, count); -+ if (rc) { -+ printk(KERN_ERR "%s: copy_from_user failed status=%d\n", __func__, rc); -+ return -EFAULT; -+ } -+ -+ if (sscanf(kbuf, "%u", &debug) != 1) { -+ printk(KERN_ERR "%s: echo > %s\n", __func__, PROC_ENTRY_DEBUG); -+ return count; -+ } -+ -+ if (debug) { -+ dev->debug = 1; -+ } else { -+ dev->debug = 0; -+ } -+ -+ printk ("Command can execute slow, please wait...\n"); -+ if (!dev->debug) { -+ val = 0xFF; /* Initial value to write */ -+ for(addr = 0x0; addr < 256; val--, addr++) { -+ i2cdata.byte = val; -+ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, -+ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); -+ if (rc) { -+ printk(KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," -+ " addr=%u, val = 0x%X", __func__, rc, addr, val); -+ } else { -+ printk("Write OK. Wrote 0x%X at addr %u\n", val, addr); -+ } -+ msleep(1); /* Delay required, since smb(i2c) interface is slow */ -+ } -+ } else { -+ int i; -+ -+ /* Note about address expected by AT24C02: To write in correct order -+ * to AT24C02 using block write, refer bottom of page 9 (Write -+ * Operations) of the data sheet regarding internal incrementing of -+ * address. Based on that explanation, we program the addr value below. -+ * Select the 'highest' address in that page (7, 15, 23, and so on) to -+ * write to that page -+ */ -+ addr = debug - 1; -+ val = jiffies % 256; -+ printk("EEPROM page write. Page start addr = %u," -+ " write data: \n", debug - 8); -+ -+ for (i = 1; i <= 8; i++) { -+ i2cdata.block[i] = val % 256; /* Fill a sequence pattern */ -+ val++; -+ printk("byte%d = 0x%02X\n", i, i2cdata.block[i]); -+ } -+ -+ i2cdata.block[0] = 8; -+ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, -+ addr, I2C_SMBUS_BLOCK_DATA, &i2cdata); -+ if (rc) { -+ printk(KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," -+ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); -+ } else { -+ printk("Block Write OK.\n"); -+ } -+ } -+ -+#ifdef IPROC_SMB_DBG -+ iproc_dump_smb_regs(dev); -+#endif /* IPROC_SMB_DBG */ -+ -+ printk("Last intr sts = 0x%08X\n", -+ dev->smb_counters.last_int_sts); -+ printk("mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", -+ dev->smb_counters.mstr_start_busy_cnt, -+ dev->smb_counters.mstr_rx_evt_cnt, -+ dev->smb_counters.mstr_rx_fifo_full_cnt); -+ -+ return count; -+} -+ -+ -+/* Written for SVK boards */ -+static int -+proc_debug_read_svk(struct file *file, char __user *buffer, size_t count, loff_t *off) -+{ -+ unsigned int len = 0; -+ struct iproc_smb_drv_int_data *dev = (struct iproc_smb_drv_int_data *) PDE_DATA (file->f_inode); -+ int rc; -+ union i2c_smbus_data i2cdata; -+ unsigned int addr; -+ -+ if (off > 0) { -+ return 0; -+ } -+ -+ len += sprintf(buffer + len, "Read\n"); -+ -+ printk(KERN_ERR "\nCommand can execute slow, please wait...\n"); -+ -+ for(addr = 0x0; addr < 256; addr++) { -+ -+ /* Read operation */ -+ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_READ, addr, -+ I2C_SMBUS_BYTE_DATA, &i2cdata); -+ -+ if (rc) { -+ printk (KERN_ERR "%s: iproc_smb_xfer failed status=%d", __func__, rc); -+ } -+ else { -+ printk(KERN_DEBUG "Read OK.Value read at %u = 0x%X\n", addr, i2cdata.byte); -+ } -+ -+ msleep(1); -+ } -+ -+#ifdef IPROC_SMB_DBG -+ iproc_dump_smb_regs(dev); -+#endif /* IPROC_SMB_DBG */ -+ -+ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", dev->smb_counters.last_int_sts); -+ -+ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", -+ dev->smb_counters.mstr_start_busy_cnt, -+ dev->smb_counters.mstr_rx_evt_cnt, -+ dev->smb_counters.mstr_rx_fifo_full_cnt); -+ -+ return len; -+} -+#endif /* #ifdef CONFIG_USE_SVK_VERSION */ -+ -+static const struct file_operations proc_smb_file_fops= { -+#ifdef CONFIG_USE_SVK_VERSION -+ .read = proc_debug_read_svk, -+ .write = proc_debug_write_svk, -+#else -+ .read = proc_debug_read, -+ .write = proc_debug_write, -+#endif -+ -+}; -+ -+ -+ -+static int proc_init(struct platform_device *pdev) -+{ -+ int rc; -+ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); -+ struct procfs *proc = &dev->proc; -+ struct proc_dir_entry *proc_debug; -+ -+ -+ snprintf(proc->name, sizeof(proc->name), "%s%d", PROC_GLOBAL_PARENT_DIR, pdev->id); -+ -+ /* sub directory */ -+ proc->parent = proc_mkdir(proc->name, gProcParent); -+ -+ if (proc->parent == NULL) { -+ return -ENOMEM; -+ } -+ -+ proc_debug = proc_create_data(PROC_ENTRY_DEBUG, 0644, proc->parent, &proc_smb_file_fops, dev); -+ -+ if (proc_debug == NULL) { -+ rc = -ENOMEM; -+ goto err_del_parent; -+ } -+ -+ return 0; -+ -+err_del_parent: -+ remove_proc_entry(proc->name, gProcParent); -+ -+ return rc; -+} -+ -+static int proc_term(struct platform_device *pdev) -+{ -+ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); -+ struct procfs *proc = &dev->proc; -+ -+ remove_proc_entry(PROC_ENTRY_DEBUG, proc->parent); -+ remove_proc_entry(proc->name, gProcParent); -+ -+ return 0; -+} -+ -+/* -+ * This function set clock frequency for SMBus block. As per hardware -+ * engineering, the clock frequency can be changed dynamically. -+ */ -+static int iproc_smb_set_clk_freq(unsigned long base_addr, -+ smb_clk_freq_t freq) -+{ -+ unsigned int regval; -+ unsigned int val; -+ -+ switch (freq) { -+ -+ case I2C_SPEED_100KHz: -+ val = 0; -+ break; -+ -+ case I2C_SPEED_400KHz: -+ val = 1; -+ break; -+ -+ default: -+ return -EINVAL; -+ break; -+ -+ } -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); -+ -+ SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, -+ CCB_SMB_TIMGCFG_MODE400_SHIFT); -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_TIMGCFG_REG, regval); -+ -+ return(0); -+} -+ -+static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev) -+{ -+ -+ unsigned long base_addr = (unsigned long)dev->block_base_addr; -+ unsigned int regval; -+#ifdef CONFIG_OF -+ u32 i2c_clk_freq; -+ struct device_node *dn = dev->dev->of_node; -+#endif -+ -+ /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. -+ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts -+ */ -+ regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRFIFOCTL_REG, regval); -+ -+ /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero -+ * since there will be only one master -+ */ -+ regval = CCB_SMB_CFG_SMBEN_MASK; -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_CFG_REG, regval); -+ -+ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ -+ udelay(100); -+ -+ -+ /* Set default clock frequency */ -+#ifndef CONFIG_OF -+ iproc_smb_set_clk_freq(base_addr, I2C_SPEED_100KHz); -+#else -+ if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq)) { -+ i2c_clk_freq = I2C_SPEED_100KHz; /*no property available, use default: 100KHz*/ -+ } -+ iproc_smb_set_clk_freq(base_addr, i2c_clk_freq); -+#endif /* CONFIG_OF */ -+ /* Disable intrs */ -+ regval = 0x0; -+ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ /* Clear intrs (W1TC) */ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_EVTSTS_REG, regval); -+ -+ return(0); -+} -+ -+/* This function enables interrupts */ -+static int iproc_intr_enable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) -+{ -+ unsigned long base_addr = (unsigned long)dev->block_base_addr; -+ unsigned int regval; -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); -+ -+ regval |= bmap; -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ /* Store all interrupts enabled so far. Note bmap can have only 'incremental' -+ * set of events -+ */ -+ dev->evt_enable_bmap = regval; -+ -+ return(0); -+} -+ -+/* This function disables interrupts */ -+static int iproc_intr_disable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) -+{ -+ unsigned long base_addr = (unsigned long)dev->block_base_addr; -+ unsigned int regval; -+ -+ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); -+ -+ regval &= ~bmap; -+ -+ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ dev->evt_enable_bmap = regval; -+ -+ return(0); -+} -+ -+/* Verify this sequence with hw engg */ -+static int iproc_smbus_block_deinit(struct iproc_smb_drv_int_data *dev) -+{ -+ unsigned int regval; -+ int rc; -+ -+ /* Disable all interrupts */ -+ regval = 0x0; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); -+ -+ /* Check if a transaction is in progress */ -+ rc = iproc_smb_startbusy_wait(dev); -+ -+ if (rc < 0) { -+ -+ /* Do not exit the function, since we are most likely shutting down */ -+ printk(KERN_ERR "%s: A transaction is still in progress," -+ "but still continuing ", __func__); -+ -+ } -+ -+ /* Disable SMBus block */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); -+ -+ regval &= ~CCB_SMB_CFG_SMBEN_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); -+ -+ -+ /* Wait for some time */ -+ udelay(100); -+ -+ /* Put the block under reset. Note the RESET bit in reg 0x0 is -+ * self clearing -+ */ -+ regval = CCB_SMB_CFG_RST_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); -+ -+ return(0); -+} -+ -+static u32 iproc_smb_funcs(struct i2c_adapter *adapter) -+{ -+ /* I2C_FUNC_SMBUS_I2C_BLOCK */ -+ return (I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | -+ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA); -+} -+ -+static struct i2c_algorithm iproc_smb_algorithm = { -+ /* .name = "iproc-smb", */ -+ .smbus_xfer = iproc_smb_xfer, -+ .master_xfer = NULL, -+ .functionality = iproc_smb_funcs, -+}; -+ -+ -+static int iproc_smb_probe(struct platform_device *pdev) -+{ -+ int rc=0, irq; -+ struct iproc_smb_drv_int_data *dev; -+ struct i2c_adapter *adap; -+ struct resource *iomem; -+ struct resource *ioarea; -+#ifdef CONFIG_OF -+ struct device_node *dn = pdev->dev.of_node; -+ u32 smb_bus_id; -+#endif -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\n%s: Entering probe\n", __func__); -+#endif /* IPROC_SMB_DBG */ -+ -+#ifdef CONFIG_OF -+ /* first I2C init */ -+ if (gProcParent == NULL) { -+ gProcParent = proc_mkdir(PROC_GLOBAL_PARENT_DIR, NULL); -+ if (gProcParent == NULL) { -+ printk(KERN_ERR "%s: SMBus driver procfs failed\n", __func__); -+ return -ENOMEM; -+ } -+ iproc_smbus_list = NULL; -+ } -+#endif /* CONFIG_OF */ -+ -+ /* Get register memory resource */ -+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ if (!iomem) { -+ printk(KERN_ERR "%s: No mem resource\n", __func__); -+ return -ENODEV; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nGot iomem 0x%p\n", iomem); -+#endif /* IPROC_SMB_DBG */ -+ -+ /* Get the interrupt number */ -+ irq = platform_get_irq(pdev, 0); -+ -+ if (irq == -ENXIO) { -+ printk(KERN_ERR "%s: No irq resource\n", __func__); -+ return -ENODEV; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nGot irqnum %d\n", irq); -+#endif /* IPROC_SMB_DBG */ -+ -+ /* Mark the memory region as used */ -+ ioarea = request_mem_region(iomem->start, resource_size(iomem), -+ pdev->name); -+ if (!ioarea) { -+ printk(KERN_ERR "%s: SMBus region already claimed\n", __func__); -+ return -EBUSY; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nGot ioarea 0x%p\n", ioarea); -+#endif /* IPROC_SMB_DBG */ -+ -+ /* Allocate memory for driver's internal data structure */ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ -+ if (!dev) { -+ printk(KERN_ERR "%s: Couldn't allocate memory for driver's internaldb\n", __func__); -+ rc = -ENOMEM; -+ goto err_release_mem_region; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nGot dev 0x%p\n", dev); -+#endif /* IPROC_SMB_DBG */ -+ -+ dev->dev = &pdev->dev; -+ init_MUTEX(&dev->xfer_lock); -+ init_completion(&dev->ses_done); -+ dev->irq = irq; -+ -+ dev->block_base_addr = ioremap(iomem->start, resource_size(iomem)); -+ -+ if (!dev->block_base_addr) { -+ printk(KERN_ERR "%s: ioremap of register space failed\n", __func__); -+ rc = -ENOMEM; -+ goto err_free_dev_mem; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\n ==== Got block_base_addr=0x%08X\n", (unsigned int)dev->block_base_addr); -+ /* iproc_dump_smb_regs(dev); */ -+#endif /* IPROC_SMB_DBG */ -+ -+ dev->enable_evts = ENABLE_INTR; /* Default value, can be changed after -+ initial testing */ -+ -+ platform_set_drvdata(pdev, dev); -+ -+ /* Init internal regs, disable intrs (and then clear intrs), set fifo -+ * thresholds, etc. -+ */ -+ iproc_smbus_block_init(dev); -+ -+ /* Register ISR handler */ -+ rc = request_irq(dev->irq, iproc_smb_isr, IRQF_SHARED, pdev->name, dev); -+ -+ if (rc) { -+ printk(KERN_ERR "%s: failed to request irq %d, rc=%d\n", __func__, dev->irq, rc); -+ goto err_smb_deinit; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nrequest_irq succeeded\n"); -+#endif /* IPROC_SMB_DBG */ -+ -+ adap = &dev->adapter; -+ i2c_set_adapdata(adap, dev); /* Verify if this place is OK */ -+ adap->owner = THIS_MODULE; -+ adap->class = UINT_MAX; /* Can be used by any I2C device */ -+ adap->algo = &iproc_smb_algorithm; -+ adap->dev.parent = &pdev->dev; /* */ -+#ifndef CONFIG_OF -+ adap->nr = pdev->id; -+#else -+ if (of_property_read_u32(dn, "#bus-id", &smb_bus_id)) { -+ dev_warn(&pdev->dev, "missing #bus-id property (default to 0)\n"); -+ smb_bus_id = 0; -+ } -+ adap->nr = smb_bus_id; -+ pdev->id = smb_bus_id; -+ adap->dev.of_node = pdev->dev.of_node; /* needed for adding I2C child devices */ -+#endif /* CONFIG_OF */ -+ snprintf(adap->name, sizeof(adap->name), "iproc-smb%d", pdev->id); -+ -+ /* -+ * I2C device drivers may be active on return from -+ * i2c_add_numbered_adapter() -+ */ -+ rc = i2c_add_numbered_adapter(adap); -+ -+ if (rc) { -+ printk(KERN_ERR "%s: Failed to add I2C adapter, rc=%d\n", __func__, rc); -+ goto err_free_irq; -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\ni2c_add_numbered_adapter succeeded\n"); -+#endif /* IPROC_SMB_DBG */ -+ -+ /* Turn on default set of interrupts */ -+ /* For Rx, enable RX fifo full, threshold hit interrupts. Other rx -+ * interrupts will be set in the read/recv transactions, as required -+ * For Tx, enable fifo under run intr. Other intrs will be set in send -+ * write access functions -+ */ -+ iproc_intr_enable(dev, CCB_SMB_MSTRRXFIFOFULLEN_MASK); -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\niproc_intr_enable complete, intrs enabled\n"); -+#endif /* IPROC_SMB_DBG */ -+ -+ rc = proc_init(pdev); -+ -+ if (rc) { -+ printk(KERN_ERR "%s: Failed to install procfs entry, rc=%d\n", __func__, rc); -+ goto err_proc_term; -+ } -+ -+ dev->next = iproc_smbus_list; -+ iproc_smbus_list = dev; -+ -+#ifdef IPROC_SMB_DBG -+ iproc_dump_smb_regs(dev); -+ printk(KERN_DEBUG "%s: probe successful", __func__); -+#endif /* IPROC_SMB_DBG */ -+ -+ return 0; -+ -+err_proc_term: -+ proc_term(pdev); -+ -+err_free_irq: -+ free_irq(dev->irq, dev); -+ -+err_smb_deinit: -+ iproc_smbus_block_deinit(dev); -+ -+ iounmap(dev->block_base_addr); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+err_free_dev_mem: -+ kfree(dev); -+ -+err_release_mem_region: -+ release_mem_region(iomem->start, resource_size(iomem)); -+ -+ printk(KERN_ERR "%s: probe failed, error=%d", __func__, rc); -+ -+ return (rc); -+} -+ -+static int iproc_smb_remove(struct platform_device *pdev) -+{ -+ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); -+ struct resource *iomem; -+ unsigned int regval; -+ -+ /* Disable interrupts. */ -+ /* Verify: Should we wait for any in-progress xact to complete? */ -+ iproc_intr_disable(dev, ~0); -+ -+ /* Disable SMbus block */ -+ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); -+ -+ regval &= ~CCB_SMB_CFG_SMBEN_MASK; -+ -+ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); -+ -+ i2c_del_adapter(&dev->adapter); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ free_irq(dev->irq, dev); -+ -+ iproc_smbus_block_deinit(dev); -+ -+ iounmap(dev->block_base_addr); -+ -+ kfree(dev); -+ -+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ release_mem_region(iomem->start, resource_size(iomem)); -+ -+ return 0; -+} -+ -+#ifndef CONFIG_OF -+static int iproc_smb_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+/* struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); */ -+ -+ /* Add additional processing, if required */ -+ -+ return (0); -+} -+ -+static int iproc_smb_resume(struct platform_device *pdev) -+{ -+/* struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); */ -+ -+ /* Add additional processing, if required */ -+ -+ return (0); -+} -+ -+static struct platform_driver iproc_smb_driver = { -+ .driver = { -+ .name = "iproc-smb", -+ .owner = THIS_MODULE, -+ }, -+ .probe = iproc_smb_probe, -+ .remove = iproc_smb_remove, -+ .suspend = iproc_smb_suspend, -+ .resume = iproc_smb_resume, -+}; -+ -+static int __init iproc_smb_init(void) -+{ -+ int rc; -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "%s: Entering init", __func__); -+#endif /* IPROC_SMB_DBG */ -+ -+ gProcParent = proc_mkdir(PROC_GLOBAL_PARENT_DIR, NULL); -+ -+ if (gProcParent == NULL) { -+ -+ printk(KERN_ERR "%s: SMBus driver procfs failed\n", __func__); -+ -+ return -ENOMEM; -+ -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\nproc_mkdir succeeded, gProcParent=0x%08X\n", (unsigned int)gProcParent); -+#endif /* IPROC_SMB_DBG */ -+ -+ rc = platform_driver_register(&iproc_smb_driver); -+ -+ if (rc < 0) { -+ -+ printk(KERN_ERR "%s: SMBus driver init failed, error %d\n", __func__, rc); -+ -+ } -+ -+#ifdef IPROC_SMB_DBG -+ printk(KERN_DEBUG "\n%s: Called platform_driver_register, rc=%d\n", __func__, rc); -+#endif /* IPROC_SMB_DBG */ -+ -+ -+ iproc_smbus_list = NULL; -+ -+ /* Should we set RESET bit (reg 0x0) here?: Not necessary as per hw engg */ -+ -+ return rc; -+} -+ -+static void __exit iproc_smb_exit(void) -+{ -+ platform_driver_unregister(&iproc_smb_driver); -+ -+ remove_proc_entry(PROC_GLOBAL_PARENT_DIR, NULL); -+} -+ -+module_init(iproc_smb_init); -+module_exit(iproc_smb_exit); -+ -+#else /* CONFIG_OF */ -+ -+static const struct of_device_id bcm_iproc_i2c_of_match[] = { -+ { .compatible = "brcm,iproc-i2c" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_i2c_of_match); -+ -+static struct platform_driver bcm_iproc_i2c_driver = { -+ .driver = { -+ .name = "bcm-iproc-i2c", -+ .of_match_table = bcm_iproc_i2c_of_match, -+ }, -+ .probe = iproc_smb_probe, -+ .remove = iproc_smb_remove, -+}; -+module_platform_driver(bcm_iproc_i2c_driver); -+#endif /* !CONFIG_OF */ -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("IPROC I2C (SMBus) Bus Driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig ---- a/drivers/mmc/host/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mmc/host/Kconfig 2017-11-09 17:53:42.449278000 +0800 -@@ -786,3 +786,12 @@ config MMC_MTK - If you have a machine with a integrated SD/MMC card reader, say Y or M here. - This is needed if support for any SD/SDIO/MMC devices is required. - If unsure, say N. -+ -+config MMC_SDHCI_XGS_IPROC -+ tristate "Broadcom XGS iProc SD/MMC Card Interface support" -+ select MMC_SDHCI_IO_ACCESSORS -+ default n -+ help -+ This selects the platform Secure Digital Host Controller Interface. -+ If unsure, say N. -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile ---- a/drivers/mmc/host/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mmc/host/Makefile 2017-11-09 17:53:42.457283000 +0800 -@@ -75,6 +75,7 @@ obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhc - obj-$(CONFIG_MMC_SDHCI_IPROC) += sdhci-iproc.o - obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o - obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o -+obj-$(CONFIG_MMC_SDHCI_XGS_IPROC) += sdhci-bcm-hr3.o sdhci-xgs-iproc.o - - ifeq ($(CONFIG_CB710_DEBUG),y) - CFLAGS-cb710-mmc += -DDEBUG -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/sdhci-bcm-hr3.c b/drivers/mmc/host/sdhci-bcm-hr3.c ---- a/drivers/mmc/host/sdhci-bcm-hr3.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/mmc/host/sdhci-bcm-hr3.c 2017-11-09 17:53:42.528279000 +0800 -@@ -0,0 +1,611 @@ -+/* -+ * drivers/mmc/host/sdhci-bcm-hr3 - Broadcom HR3 SDHCI Platform driver -+ * -+ * Copyright (C) 2014-2016, Broadcom Corporation. All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 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. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sdhci.h" -+ -+struct sdhci_xgs_iproc_data { -+ struct sdhci_host *host; -+ struct clk *clk; -+ unsigned host_num; -+}; -+ -+struct xgs_iproc_sdhci_host { -+ struct sdhci_host host; -+ void __iomem *wrap_base; -+ void __iomem *idm_base; -+ void __iomem *cmicd_base; -+ u32 shadow_cmd; -+ u32 shadow_blk; -+}; -+ -+extern void __iomem *get_iproc_wrap_ctrl_base(void); -+static int iproc_top_sdio_config(void __iomem *cmicd_base); -+ -+static inline void -+iproc_sdhci_writel(struct sdhci_host *host, u32 val, int reg) -+{ -+ /* WAR for SDIO/GPIO setting might be reset by SDK for HR3. */ -+ if (reg == SDHCI_INT_STATUS) { -+ struct xgs_iproc_sdhci_host *iproc_host = (struct xgs_iproc_sdhci_host *)host; -+ iproc_top_sdio_config(iproc_host->cmicd_base); -+ } -+ -+ writel(val, host->ioaddr + reg); -+} -+ -+static inline u32 -+iproc_sdhci_readl(struct sdhci_host *host, int reg) -+{ -+ return readl(host->ioaddr + reg); -+} -+ -+static void -+iproc_sdhci_writew(struct sdhci_host *host, u16 val, int reg) -+{ -+ struct xgs_iproc_sdhci_host *iproc_host = (struct xgs_iproc_sdhci_host *)host; -+ u32 oldval, newval; -+ u32 word_num = (reg >> 1) & 1; -+ u32 word_shift = word_num * 16; -+ u32 mask = 0xffff << word_shift; -+ -+ if (reg == SDHCI_COMMAND) { -+ if (iproc_host->shadow_blk != 0) { -+ iproc_sdhci_writel(host, iproc_host->shadow_blk, SDHCI_BLOCK_SIZE); -+ iproc_host->shadow_blk = 0; -+ } -+ oldval = iproc_host->shadow_cmd; -+ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { -+ oldval = iproc_host->shadow_blk; -+ } else { -+ oldval = iproc_sdhci_readl(host, reg & ~3); -+ } -+ newval = (oldval & ~mask) | (val << word_shift); -+ -+ if (reg == SDHCI_TRANSFER_MODE) { -+ iproc_host->shadow_cmd = newval; -+ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { -+ iproc_host->shadow_blk = newval; -+ } else { -+ iproc_sdhci_writel(host, newval, reg & ~3); -+ } -+} -+ -+static u16 -+iproc_sdhci_readw(struct sdhci_host *host, int reg) -+{ -+ u32 val, word; -+ u32 word_num = (reg >> 1) & 1; -+ u32 word_shift = word_num * 16; -+ -+ val = iproc_sdhci_readl(host, (reg & ~3)); -+ word = (val >> word_shift) & 0xffff; -+ return word; -+} -+ -+static void -+iproc_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) -+{ -+ u32 oldval, newval; -+ u32 byte_num = reg & 3; -+ u32 byte_shift = byte_num * 8; -+ u32 mask = 0xff << byte_shift; -+ -+ oldval = iproc_sdhci_readl(host, reg & ~3); -+ newval = (oldval & ~mask) | (val << byte_shift); -+ -+ iproc_sdhci_writel(host, newval, reg & ~3); -+} -+ -+static u8 -+iproc_sdhci_readb(struct sdhci_host *host, int reg) -+{ -+ u32 val, byte; -+ u32 byte_num = reg & 3; -+ u32 byte_shift = byte_num * 8; -+ -+ val = iproc_sdhci_readl(host, (reg & ~3)); -+ byte = (val >> byte_shift) & 0xff; -+ return byte; -+} -+ -+static u32 -+iproc_sdhci_get_max_clock(struct sdhci_host *host) -+{ -+ unsigned long max_clock; -+ -+ max_clock = (host->caps & SDHCI_CLOCK_V3_BASE_MASK) -+ >> SDHCI_CLOCK_BASE_SHIFT; -+ max_clock *= 1000000; -+ -+ return max_clock; -+} -+ -+static u32 -+iproc_sdhci_get_min_clock(struct sdhci_host *host) -+{ -+ return (host->max_clk / SDHCI_MAX_DIV_SPEC_300); -+} -+ -+static int -+iproc_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) -+{ -+ /* -+ * Tuning is unnecessary for SDR50 and DDR50; moreover, the IPROC platform -+ * doesn't support SDR104, HS200 and Hs400 cards. So, we needn't do anything -+ * for tuning. -+ */ -+ return 0; -+} -+ -+static void -+iproc_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) -+{ -+ /* -+ * WAR that IPROC SD/MMC host need to set the driver strength -+ * to TYPE_A in 3.3v DS/HS mode even if the driver strength is -+ * meaningless for 3.3V signaling. -+ */ -+ if ((host->timing == MMC_TIMING_LEGACY) || -+ (host->timing == MMC_TIMING_MMC_HS) || -+ (host->timing == MMC_TIMING_SD_HS)) { -+ host->mmc->ios.drv_type = MMC_SET_DRIVER_TYPE_A; -+ } -+ -+ sdhci_set_clock(host, clock); -+} -+ -+static struct sdhci_ops sdhci_xgs_iproc_ops = { -+#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS -+ .write_l = iproc_sdhci_writel, -+ .write_w = iproc_sdhci_writew, -+ .write_b = iproc_sdhci_writeb, -+ .read_l = iproc_sdhci_readl, -+ .read_w = iproc_sdhci_readw, -+ .read_b = iproc_sdhci_readb, -+#else -+#error The iproc SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set -+#endif -+ .reset = sdhci_reset, -+ .set_bus_width = sdhci_set_bus_width, -+ .set_uhs_signaling = sdhci_set_uhs_signaling, -+ .set_clock = iproc_sdhci_set_clock, -+ .get_max_clock = iproc_sdhci_get_max_clock, -+ .get_min_clock = iproc_sdhci_get_min_clock, -+ .platform_execute_tuning = iproc_sdhci_execute_tuning, -+}; -+ -+#define IPROC_CMICD_COMPATIBLE "brcm,iproc-cmicd" -+ -+#define CMIC_SBUS_RING_MAP_0_7(base) (base + 0x10098) -+#define CMIC_SBUS_RING_MAP_8_15(base) (base + 0x1009C) -+#define CMIC_SBUS_RING_MAP_16_23(base) (base + 0x100A0) -+#define CMIC_SBUS_RING_MAP_24_31(base) (base + 0x100A4) -+#define CMIC_COMMON_SCHAN_CTRL(base) (base + 0x10000) -+#define CMIC_COMMON_SCHAN_MESSAGE0(base) (base + 0x1000C) -+#define CMIC_COMMON_SCHAN_MESSAGE1(base) (base + 0x10010) -+#define CMIC_COMMON_SCHAN_MESSAGE2(base) (base + 0x10014) -+ -+/* TOP registers */ -+#define TOP_SDIO_MISC_CONTROL 0x0207e500 -+#define TOP_SDIO_MISC_CONTROL__TOP_SDIO_8B_INF 4 -+#define TOP_SDIO_MISC_CONTROL__TOP_SDIO_GPIO_INF_SEL_R 0 -+ -+/* SDIO IDM registers */ -+#define SDIO_IDM0_IO_CONTROL_DIRECT(base) (base + 0x0) -+#define SDIO_IDM0_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE 22 -+#define SDIO_IDM0_IO_CONTROL_DIRECT__FEEDBACK_CLK_EN 21 -+#define SDIO_IDM0_IO_CONTROL_DIRECT__clk_enable 0 -+#define SDIO_IDM0_IDM_RESET_CONTROL(base) (base + 0x3F8) -+ -+/* IPROC WRAP registers */ -+#define IPROC_WRAP_SDIO_CONTROL(base) (base + 0xb0) -+#define IPROC_WRAP_SDIO_CONTROL1(base) (base + 0xb4) -+#define IPROC_WRAP_SDIO_CONTROL2(base) (base + 0xb8) -+#define IPROC_WRAP_SDIO_CONTROL3(base) (base + 0xbc) -+#define IPROC_WRAP_SDIO_CONTROL4(base) (base + 0xc0) -+#define IPROC_WRAP_SDIO_CONTROL5(base) (base + 0xc4) -+#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(base) (base + 0xc8) -+#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_VDDO_18V_FAIL_SOVW 1 -+#define IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_UHS1_18V_VREG_FAIL 0 -+ -+/* -+ * SDIO_CAPS_L -+ * -+ * Field Bit(s) -+ * =========================== -+ * DDR50 31 -+ * SDR104 30 -+ * SDR50 29 -+ * SLOTTYPE 28:27 -+ * ASYNCHIRQ 26 -+ * SYSBUS64 25 -+ * V18 24 -+ * V3 23 -+ * V33 22 -+ * SUPRSM 21 -+ * SDMA 20 -+ * HSPEED 19 -+ * ADMA2 18 -+ * EXTBUSMED 17 -+ * MAXBLK 16:15 -+ * BCLK 14:7 -+ * TOUT 6 -+ * TOUTFREQ 5:0 -+ */ -+#define SDIO_CAPS_L 0xA17f6470 -+ -+/* -+ * SDIO_CAPS_H -+ * -+ * Field Bit(s) -+ * =========================== -+ * reserved 31:20 -+ * SPIBLOCKMODE 19 -+ * SPIMODE_CAP 18 -+ * CLOCKMULT 17:10 -+ * RETUNE_MODE 9:8 -+ * USETUNE_SDR50 7 -+ * TMRCNT_RETUNE 6:3 -+ * DRVR_TYPED 2 -+ * DRVR_TYPEC 1 -+ * DRVR_TYPEA 0 -+ */ -+#define SDIO_CAPS_H 0x000C000f -+ -+/* -+ * Preset value -+ * -+ * Field Bit(s) -+ * =========================== -+ * Driver Strength 12:11 -+ * Clock Generator 10 -+ * SDCLK Frequeency 9:0 -+ */ -+ -+/* -+ * SDIO_PRESETVAL1 -+ * -+ * Field Bit(s) Description -+ * ============================================================ -+ * DDR50_PRESET 25:13 Preset Value for DDR50 -+ * DEFAULT_PRESET 12:0 Preset Value for Default Speed -+ */ -+#define SDIO_PRESETVAL1 0x01004004 -+ -+/* -+ * SDIO_PRESETVAL2 -+ * -+ * Field Bit(s) Description -+ * ============================================================ -+ * HIGH_SPEED_PRESET 25:13 Preset Value for High Speed -+ * INIT_PRESET 12:0 Preset Value for Initialization -+ */ -+#define SDIO_PRESETVAL2 0x01004100 -+ -+/* -+ * SDIO_PRESETVAL3 -+ * -+ * Field Bit(s) Description -+ * ============================================================ -+ * SDR104_PRESET 25:13 Preset Value for SDR104 -+ * SDR12_PRESET 12:0 Preset Value for SDR12 -+ */ -+#define SDIO_PRESETVAL3 0x00000004 -+ -+/* -+ * SDIO_PRESETVAL4 -+ * -+ * Field Bit(s) Description -+ * ============================================================ -+ * SDR25_PRESET 25:13 Preset Value for SDR25 -+ * SDR50_PRESET 12:0 Preset Value for SDR50 -+ */ -+#define SDIO_PRESETVAL4 0x01005001 -+ -+u32 -+cmicd_schan_read(void __iomem *base, u32 ctrl, u32 addr) { -+ u32 read = 0x0; -+ -+ writel(ctrl, CMIC_COMMON_SCHAN_MESSAGE0(base)); -+ writel(addr, CMIC_COMMON_SCHAN_MESSAGE1(base)); -+ -+ writel(0x1, CMIC_COMMON_SCHAN_CTRL(base)); -+ -+ while (read != 0x2) { -+ read = readl(CMIC_COMMON_SCHAN_CTRL(base)); -+ } -+ read = readl(CMIC_COMMON_SCHAN_MESSAGE1(base)); -+ return read; -+} -+ -+u32 -+cmicd_schan_write(void __iomem *base, u32 ctrl, u32 addr, u32 val) { -+ u32 read = 0x0; -+ -+ writel(ctrl, CMIC_COMMON_SCHAN_MESSAGE0(base)); -+ writel(addr, CMIC_COMMON_SCHAN_MESSAGE1(base)); -+ writel(val, CMIC_COMMON_SCHAN_MESSAGE2(base)); -+ -+ writel(0x1, CMIC_COMMON_SCHAN_CTRL(base)); -+ -+ while (read != 0x2) { -+ read = readl(CMIC_COMMON_SCHAN_CTRL(base)); -+ } -+ return read; -+} -+ -+static void -+cmicd_init_soc(void __iomem *base) { -+ /* Configure SBUS Ring Map for TOP, block id = 16, ring number = 4 */ -+ writel(0x11112200, CMIC_SBUS_RING_MAP_0_7(base)); -+ writel(0x00430001, CMIC_SBUS_RING_MAP_8_15(base)); -+ writel(0x00005064, CMIC_SBUS_RING_MAP_16_23(base)); -+ writel(0x00000000, CMIC_SBUS_RING_MAP_24_31(base)); -+} -+ -+static int -+iproc_top_sdio_config(void __iomem *cmicd_base) -+{ -+ u32 val; -+ -+ cmicd_init_soc(cmicd_base); -+ -+ /* Enable SDIO 8 bit mode */ -+ val = cmicd_schan_read(cmicd_base, 0x2c800200, TOP_SDIO_MISC_CONTROL); -+ if ((val & 0x1f) != 0x1f) { -+ val |= (0x1 << TOP_SDIO_MISC_CONTROL__TOP_SDIO_8B_INF); -+ val |= (0xf << TOP_SDIO_MISC_CONTROL__TOP_SDIO_GPIO_INF_SEL_R); -+ cmicd_schan_write(cmicd_base, 0x34800200, TOP_SDIO_MISC_CONTROL, val); -+ } -+ -+ return 0; -+} -+ -+static int -+iproc_sdio_init(struct xgs_iproc_sdhci_host *iproc_host) -+{ -+ int ret = 0; -+ u32 val; -+ -+ /* Enable SDIO for SDIO/GPIO selection */ -+ ret = iproc_top_sdio_config(iproc_host->cmicd_base); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ /* Release reset */ -+ writel(0x1, SDIO_IDM0_IDM_RESET_CONTROL(iproc_host->idm_base)); -+ udelay(1000); -+ writel(0x0, SDIO_IDM0_IDM_RESET_CONTROL(iproc_host->idm_base)); -+ -+ /* Enable the SDIO clock */ -+ val = readl(SDIO_IDM0_IO_CONTROL_DIRECT(iproc_host->idm_base)); -+ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE); -+ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__FEEDBACK_CLK_EN); -+ val |= (1 << SDIO_IDM0_IO_CONTROL_DIRECT__clk_enable); -+ writel(val, SDIO_IDM0_IO_CONTROL_DIRECT(iproc_host->idm_base)); -+ -+ /* Set the 1.8v fail control for HR3. -+ * This setting will not impact the uboot SD/MMC driver, since uboot doesn't -+ * support 1.8v. The 1.8v SDIO will be supportted in Kernel. -+ */ -+ val = readl(IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(iproc_host->wrap_base)); -+ val |= (1 << IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_VDDO_18V_FAIL_SOVW); -+ val &= ~(1 << IPROC_WRAP_SDIO_1P8_FAIL_CONTROL__SDIO_UHS1_18V_VREG_FAIL); -+ writel(val, IPROC_WRAP_SDIO_1P8_FAIL_CONTROL(iproc_host->wrap_base)); -+ -+ /* -+ * Configure SDIO host controller capabilities -+ * (common setting for all SDIO controllers) -+ */ -+ writel(SDIO_CAPS_H, IPROC_WRAP_SDIO_CONTROL(iproc_host->wrap_base)); -+ writel(SDIO_CAPS_L, IPROC_WRAP_SDIO_CONTROL1(iproc_host->wrap_base)); -+ -+ /* -+ * Configure SDIO host controller preset values -+ * (common setting for all SDIO controllers) -+ */ -+ writel(SDIO_PRESETVAL1, IPROC_WRAP_SDIO_CONTROL2(iproc_host->wrap_base)); -+ writel(SDIO_PRESETVAL2, IPROC_WRAP_SDIO_CONTROL3(iproc_host->wrap_base)); -+ writel(SDIO_PRESETVAL3, IPROC_WRAP_SDIO_CONTROL4(iproc_host->wrap_base)); -+ writel(SDIO_PRESETVAL4, IPROC_WRAP_SDIO_CONTROL5(iproc_host->wrap_base)); -+ -+ return 0; -+} -+ -+static int -+sdhci_xgs_iproc_probe(struct platform_device *pdev) -+{ -+ struct xgs_iproc_sdhci_host *iproc_host; -+ struct sdhci_host *host; -+ struct sdhci_xgs_iproc_data *data; -+ struct device_node *np = pdev->dev.of_node; -+ int ret = 0; -+ -+ /* allocate SDHCI host + platform data memory */ -+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_xgs_iproc_data)); -+ if (IS_ERR(host)) { -+ printk(KERN_ERR "SDIO%d: Unable to allocate SDHCI host\n", pdev->id); -+ return PTR_ERR(host); -+ } -+ -+ iproc_host = (struct xgs_iproc_sdhci_host *)host; -+ -+ /* set up data structure */ -+ data = sdhci_priv(host); -+ data->host = host; -+ data->host_num = pdev->id; -+ host->hw_name = "IPROC-SDIO"; -+ host->ops = &sdhci_xgs_iproc_ops; -+ host->mmc->caps = MMC_CAP_8_BIT_DATA; -+ host->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | -+ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; -+ host->irq = (unsigned int)irq_of_parse_and_map(np, 0); -+ host->ioaddr = (void *)of_iomap(np, 0); -+ if (!host->ioaddr) { -+ printk(KERN_ERR "SDIO%d: Unable to iomap SDIO registers\n", pdev->id); -+ ret = -ENXIO; -+ goto err_free_host; -+ } -+ -+ iproc_host->idm_base = of_iomap(np, 1); -+ if (!iproc_host->idm_base) { -+ printk(KERN_ERR "Unable to iomap SDIO IDM base address\n"); -+ ret = -ENXIO; -+ goto err_iounmap; -+ } -+ -+ np = of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE); -+ if (!np) { -+ printk(KERN_ERR "Failed to find IPROC_CMICD defined in DT\n"); -+ ret = -ENODEV; -+ goto err_iounmap; -+ } -+ -+ iproc_host->cmicd_base = of_iomap(np, 0); -+ if (!iproc_host->cmicd_base) { -+ printk(KERN_ERR "Unable to iomap IPROC CMICD base address\n"); -+ ret = -ENXIO; -+ goto err_iounmap; -+ } -+ -+ iproc_host->wrap_base = get_iproc_wrap_ctrl_base(); -+ if (!iproc_host->wrap_base) { -+ printk(KERN_ERR "Unable to get IPROC WRAP base address\n"); -+ ret = -ENXIO; -+ goto err_iounmap; -+ } -+ -+ ret = iproc_sdio_init(iproc_host); -+ if (ret < 0) { -+ printk(KERN_ERR "SDIO%d: SDIO initial failed\n", pdev->id); -+ ret = -ENXIO; -+ goto err_iounmap; -+ } -+ -+ platform_set_drvdata(pdev, data); -+ -+ ret = sdhci_add_host(host); -+ if (ret) { -+ printk(KERN_ERR "SDIO%d: Failed to add SDHCI host\n", pdev->id); -+ goto err_iounmap; -+ } -+ -+ return ret; -+ -+err_iounmap: -+ if (iproc_host->idm_base) -+ iounmap(iproc_host->idm_base); -+ if (iproc_host->cmicd_base) -+ iounmap(iproc_host->cmicd_base); -+ if (host->ioaddr) -+ iounmap(host->ioaddr); -+ -+err_free_host: -+ sdhci_free_host(host); -+ -+ return ret; -+} -+ -+static int __exit -+sdhci_xgs_iproc_remove(struct platform_device *pdev) -+{ -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ struct sdhci_host *host = data->host; -+ struct xgs_iproc_sdhci_host *iproc_host = (struct xgs_iproc_sdhci_host *)host; -+ -+ sdhci_remove_host(host, 0); -+ platform_set_drvdata(pdev, NULL); -+ -+ if (iproc_host->idm_base) -+ iounmap(iproc_host->idm_base); -+ if (iproc_host->cmicd_base) -+ iounmap(iproc_host->cmicd_base); -+ if (host->ioaddr) -+ iounmap(host->ioaddr); -+ -+ sdhci_free_host(host); -+ release_mem_region(pdev->resource[0].start, -+ pdev->resource[0].end - pdev->resource[0].start + 1); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int -+sdhci_xgs_iproc_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ int ret = 0; -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ -+ ret = sdhci_suspend_host(data->host); -+ if (ret < 0) { -+ printk("%s: %d\n", __FILE__, __LINE__); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+sdhci_xgs_iproc_resume(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ -+ ret = sdhci_resume_host(data->host); -+ if (ret < 0) { -+ printk("%s: %d\n", __FILE__, __LINE__); -+ return ret; -+ } -+ return 0; -+} -+#else /* CONFIG_PM */ -+ -+#define sdhci_xgs_iproc_suspend NULL -+#define sdhci_xgs_iproc_resume NULL -+ -+#endif /* CONFIG_PM */ -+ -+ -+static const struct of_device_id brcm_iproc_hr3_dt_ids[] = { -+ { .compatible = "brcm,iproc-hr3-sdio"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcm_iproc_dt_ids); -+ -+static struct platform_driver sdhci_xgs_iproc_driver = { -+ .probe = sdhci_xgs_iproc_probe, -+ .remove = __exit_p(sdhci_xgs_iproc_remove), -+ .suspend = sdhci_xgs_iproc_suspend, -+ .resume = sdhci_xgs_iproc_resume, -+ .driver = { -+ .name = "iproc-hr3-sdio", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcm_iproc_hr3_dt_ids), -+ }, -+}; -+ -+module_platform_driver(sdhci_xgs_iproc_driver); -+ -+MODULE_AUTHOR("Broadcom"); -+MODULE_DESCRIPTION("SDHCI XGS HR3 driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mmc/host/sdhci-xgs-iproc.c b/drivers/mmc/host/sdhci-xgs-iproc.c ---- a/drivers/mmc/host/sdhci-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/mmc/host/sdhci-xgs-iproc.c 2017-11-09 17:53:42.564288000 +0800 -@@ -0,0 +1,311 @@ -+/* -+ * drivers/mmc/host/sdhci-iproc.c - Broadcom IPROC SDHCI Platform driver -+ * -+ * Copyright (C) 2014-2016, Broadcom Corporation. All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 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. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sdhci.h" -+ -+struct sdhci_xgs_iproc_data { -+ struct sdhci_host *host; -+ struct clk *clk; -+ unsigned host_num; -+}; -+ -+struct xgs_iproc_sdhci_host { -+ struct sdhci_host host; -+ u32 shadow_cmd; -+ u32 shadow_blk; -+}; -+ -+static inline void -+iproc_sdhci_writel(struct sdhci_host *host, u32 val, int reg) -+{ -+ writel(val, host->ioaddr + reg); -+} -+ -+static inline u32 -+iproc_sdhci_readl(struct sdhci_host *host, int reg) -+{ -+ return readl(host->ioaddr + reg); -+} -+ -+static void -+iproc_sdhci_writew(struct sdhci_host *host, u16 val, int reg) -+{ -+ struct xgs_iproc_sdhci_host *iproc_host = (struct xgs_iproc_sdhci_host *)host; -+ u32 oldval, newval; -+ u32 word_num = (reg >> 1) & 1; -+ u32 word_shift = word_num * 16; -+ u32 mask = 0xffff << word_shift; -+ -+ if (reg == SDHCI_COMMAND) { -+ if (iproc_host->shadow_blk != 0) { -+ iproc_sdhci_writel(host, iproc_host->shadow_blk, SDHCI_BLOCK_SIZE); -+ iproc_host->shadow_blk = 0; -+ } -+ oldval = iproc_host->shadow_cmd; -+ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { -+ oldval = iproc_host->shadow_blk; -+ } else { -+ oldval = iproc_sdhci_readl(host, reg & ~3); -+ } -+ newval = (oldval & ~mask) | (val << word_shift); -+ -+ if (reg == SDHCI_TRANSFER_MODE) { -+ iproc_host->shadow_cmd = newval; -+ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { -+ iproc_host->shadow_blk = newval; -+ } else { -+ iproc_sdhci_writel(host, newval, reg & ~3); -+ } -+} -+ -+static u16 -+iproc_sdhci_readw(struct sdhci_host *host, int reg) -+{ -+ u32 val, word; -+ u32 word_num = (reg >> 1) & 1; -+ u32 word_shift = word_num * 16; -+ -+ val = iproc_sdhci_readl(host, (reg & ~3)); -+ word = (val >> word_shift) & 0xffff; -+ return word; -+} -+ -+ -+static void -+iproc_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) -+{ -+ u32 oldval, newval; -+ u32 byte_num = reg & 3; -+ u32 byte_shift = byte_num * 8; -+ u32 mask = 0xff << byte_shift; -+ -+ oldval = iproc_sdhci_readl(host, reg & ~3); -+ newval = (oldval & ~mask) | (val << byte_shift); -+ -+ iproc_sdhci_writel(host, newval, reg & ~3); -+} -+ -+static u8 -+iproc_sdhci_readb(struct sdhci_host *host, int reg) -+{ -+ u32 val, byte; -+ u32 byte_num = reg & 3; -+ u32 byte_shift = byte_num * 8; -+ -+ val = iproc_sdhci_readl(host, (reg & ~3)); -+ byte = (val >> byte_shift) & 0xff; -+ return byte; -+} -+ -+static u32 -+iproc_sdhci_get_max_clock(struct sdhci_host *host) -+{ -+ unsigned long max_clock; -+ -+ max_clock = (host->caps & SDHCI_CLOCK_V3_BASE_MASK) -+ >> SDHCI_CLOCK_BASE_SHIFT; -+ max_clock *= 1000000; -+ -+ return max_clock; -+} -+ -+static u32 -+iproc_sdhci_get_min_clock(struct sdhci_host *host) -+{ -+ return (host->max_clk / SDHCI_MAX_DIV_SPEC_300); -+} -+ -+static int -+iproc_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) -+{ -+ /* -+ * Tuning is unnecessary for SDR50 and DDR50; moreover, the IPROC platform -+ * doesn't support SDR104, HS200 and Hs400 cards. So, we needn't do anything -+ * for tuning. -+ */ -+ return 0; -+} -+ -+static void -+iproc_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) -+{ -+ /* -+ * WAR that IPROC SD/MMC host need to set the driver strength -+ * to TYPE_A in 3.3v DS/HS mode even if the driver strength is -+ * meaningless for 3.3V signaling. -+ */ -+ if ((host->timing == MMC_TIMING_LEGACY) || -+ (host->timing == MMC_TIMING_MMC_HS) || -+ (host->timing == MMC_TIMING_SD_HS)) { -+ host->mmc->ios.drv_type = MMC_SET_DRIVER_TYPE_A; -+ } -+ -+ sdhci_set_clock(host, clock); -+} -+ -+static struct sdhci_ops sdhci_xgs_iproc_ops = { -+#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS -+ .write_l = iproc_sdhci_writel, -+ .write_w = iproc_sdhci_writew, -+ .write_b = iproc_sdhci_writeb, -+ .read_l = iproc_sdhci_readl, -+ .read_w = iproc_sdhci_readw, -+ .read_b = iproc_sdhci_readb, -+#else -+#error The iproc SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set -+#endif -+ .reset = sdhci_reset, -+ .set_bus_width = sdhci_set_bus_width, -+ .set_uhs_signaling = sdhci_set_uhs_signaling, -+ .set_clock = iproc_sdhci_set_clock, -+ .get_max_clock = iproc_sdhci_get_max_clock, -+ .get_min_clock = iproc_sdhci_get_min_clock, -+ .platform_execute_tuning = iproc_sdhci_execute_tuning, -+}; -+ -+static int -+sdhci_xgs_iproc_probe(struct platform_device *pdev) -+{ -+ struct sdhci_host *host; -+ struct sdhci_xgs_iproc_data *data; -+ struct device_node *np = pdev->dev.of_node; -+ int ret = 0; -+ -+ /* allocate SDHCI host + platform data memory */ -+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_xgs_iproc_data)); -+ if (IS_ERR(host)) { -+ printk(KERN_ERR "SDIO%d: Unable to allocate SDHCI host\n", pdev->id); -+ return PTR_ERR(host); -+ } -+ -+ /* set up data structure */ -+ data = sdhci_priv(host); -+ data->host = host; -+ data->host_num = pdev->id; -+ host->hw_name = "IPROC-SDIO"; -+ host->ops = &sdhci_xgs_iproc_ops; -+ host->mmc->caps = MMC_CAP_8_BIT_DATA; -+ host->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | -+ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; -+ -+ host->irq = (unsigned int)irq_of_parse_and_map(np, 0); -+ host->ioaddr = (void *)of_iomap(np, 0); -+ if (!host->ioaddr) { -+ printk(KERN_ERR "SDIO%d: Unable to iomap SDIO registers\n", pdev->id); -+ ret = -ENXIO; -+ goto err_free_host; -+ } -+ -+ platform_set_drvdata(pdev, data); -+ -+ ret = sdhci_add_host(host); -+ if (ret) { -+ printk(KERN_ERR "SDIO%d: Failed to add SDHCI host\n", pdev->id); -+ goto err_iounmap; -+ } -+ -+ return ret; -+ -+err_iounmap: -+ iounmap(host->ioaddr); -+ -+err_free_host: -+ sdhci_free_host(host); -+ -+ return ret; -+} -+ -+static int __exit -+sdhci_xgs_iproc_remove(struct platform_device *pdev) -+{ -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ struct sdhci_host *host = data->host; -+ -+ sdhci_remove_host(host, 0); -+ platform_set_drvdata(pdev, NULL); -+ iounmap(host->ioaddr); -+ sdhci_free_host(host); -+ release_mem_region(pdev->resource[0].start, -+ pdev->resource[0].end - pdev->resource[0].start + 1); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int -+sdhci_xgs_iproc_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ int ret = 0; -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ -+ ret = sdhci_suspend_host(data->host); -+ if (ret < 0) { -+ printk("%s: %d\n", __FILE__, __LINE__); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+sdhci_xgs_iproc_resume(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct sdhci_xgs_iproc_data *data = platform_get_drvdata(pdev); -+ -+ ret = sdhci_resume_host(data->host); -+ if (ret < 0) { -+ printk("%s: %d\n", __FILE__, __LINE__); -+ return ret; -+ } -+ return 0; -+} -+#else /* CONFIG_PM */ -+ -+#define sdhci_xgs_iproc_suspend NULL -+#define sdhci_xgs_iproc_resume NULL -+ -+#endif /* CONFIG_PM */ -+ -+ -+static const struct of_device_id brcm_iproc_xgs_dt_ids[] = { -+ { .compatible = "brcm,iproc-xgs-sdio"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcm_iproc_dt_ids); -+ -+static struct platform_driver sdhci_xgs_iproc_driver = { -+ .probe = sdhci_xgs_iproc_probe, -+ .remove = __exit_p(sdhci_xgs_iproc_remove), -+ .suspend = sdhci_xgs_iproc_suspend, -+ .resume = sdhci_xgs_iproc_resume, -+ .driver = { -+ .name = "iproc-xgs-sdio", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcm_iproc_xgs_dt_ids), -+ }, -+}; -+ -+module_platform_driver(sdhci_xgs_iproc_driver); -+ -+MODULE_AUTHOR("Broadcom"); -+MODULE_DESCRIPTION("SDHCI XGS IPROC driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/Makefile b/drivers/mtd/Makefile ---- a/drivers/mtd/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/Makefile 2017-11-09 17:53:42.613320000 +0800 -@@ -33,4 +33,5 @@ inftl-objs := inftlcore.o inftlmount.o - obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ - - obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ -+obj-$(CONFIG_MTD_SPI_NOR_IPROC) += spi-nor/ - obj-$(CONFIG_MTD_UBI) += ubi/ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig ---- a/drivers/mtd/devices/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/devices/Kconfig 2017-11-09 17:53:42.646279000 +0800 -@@ -95,6 +95,12 @@ config MTD_M25P80 - if you want to specify device partitioning or to use a device which - doesn't support the JEDEC ID instruction. - -+config MTD_M25P80_IPROC -+ tristate "M25P80 modified for BRCM iProc" -+ depends on SPI_MASTER && MTD_SPI_NOR_IPROC -+ help -+ This enables access to most modern SPI flash chips for BRCM iProc QSPI controller -+ - config MTD_SPEAR_SMI - tristate "SPEAR MTD NOR Support through SMI controller" - depends on PLAT_SPEAR -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile ---- a/drivers/mtd/devices/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/devices/Makefile 2017-11-09 17:53:42.647286000 +0800 -@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_LART) += lart.o - obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o - obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o - obj-$(CONFIG_MTD_M25P80) += m25p80.o -+obj-$(CONFIG_MTD_M25P80_IPROC) += m25p80-iproc.o - obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o - obj-$(CONFIG_MTD_SST25L) += sst25l.o - obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/devices/m25p80-iproc.c b/drivers/mtd/devices/m25p80-iproc.c ---- a/drivers/mtd/devices/m25p80-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/mtd/devices/m25p80-iproc.c 2017-11-09 17:53:42.661287000 +0800 -@@ -0,0 +1,328 @@ -+/* -+ * MTD SPI driver for ST M25Pxx (and similar) serial flash chips based -+ * on m25p80.c with BRCM iProc patch -+ * -+ * This code 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define MAX_CMD_SIZE 6 -+struct m25p { -+ struct spi_device *spi; -+ struct spi_nor spi_nor; -+ u8 command[MAX_CMD_SIZE]; -+}; -+ -+static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) -+{ -+ struct m25p *flash = nor->priv; -+ struct spi_device *spi = flash->spi; -+ int ret; -+ -+ ret = spi_write_then_read(spi, &code, 1, val, len); -+ if (ret < 0) -+ dev_err(&spi->dev, "error %d reading %x\n", ret, code); -+ -+ return ret; -+} -+ -+static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, unsigned int len, u8 *cmd) -+{ -+ u16 addr_width = nor->addr_width; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Use 4-byte mode only if (address + len) is > 16MB */ -+ if (addr + len > 0x1000000) { -+ addr_width = 4; -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ /* opcode is in cmd[0] */ -+ cmd[1] = addr >> (addr_width * 8 - 8); -+ cmd[2] = addr >> (addr_width * 8 - 16); -+ cmd[3] = addr >> (addr_width * 8 - 24); -+ cmd[4] = addr >> (addr_width * 8 - 32); -+} -+ -+static int m25p_cmdsz(struct spi_nor *nor, unsigned int addr) -+{ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Use 4-byte mode only if the address is >= 16MB */ -+ if (addr >= 0x1000000) { -+ return 1 + 4; -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ return 1 + nor->addr_width; -+} -+ -+static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -+{ -+ struct m25p *flash = nor->priv; -+ struct spi_device *spi = flash->spi; -+ -+ flash->command[0] = opcode; -+ if (buf) -+ memcpy(&flash->command[1], buf, len); -+ -+ return spi_write(spi, flash->command, len + 1); -+} -+ -+static void m25p80_write(struct spi_nor *nor, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct m25p *flash = nor->priv; -+ struct spi_device *spi = flash->spi; -+ struct spi_transfer t[2] = {}; -+ struct spi_message m; -+ int cmd_sz = m25p_cmdsz(nor, to); -+ -+ spi_message_init(&m); -+ -+ if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) -+ cmd_sz = 1; -+ -+ flash->command[0] = nor->program_opcode; -+ m25p_addr2cmd(nor, to, 1, flash->command); -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = cmd_sz; -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].tx_buf = buf; -+ t[1].len = len; -+ spi_message_add_tail(&t[1], &m); -+ -+ spi_sync(spi, &m); -+ -+ *retlen += m.actual_length - cmd_sz; -+} -+ -+static inline unsigned int m25p80_rx_nbits(struct spi_nor *nor) -+{ -+ switch (nor->flash_read) { -+ case SPI_NOR_DUAL: -+ return 2; -+ case SPI_NOR_QUAD: -+ return 4; -+ default: -+ return 0; -+ } -+} -+ -+/* -+ * Read an address range from the nor chip. The address range -+ * may be any size provided it is within the physical boundaries. -+ */ -+static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct m25p *flash = nor->priv; -+ struct spi_device *spi = flash->spi; -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ unsigned int dummy = nor->read_dummy; -+ -+ /* convert the dummy cycles to the number of bytes */ -+ dummy /= 8; -+ -+ spi_message_init(&m); -+ memset(t, 0, (sizeof t)); -+ -+ flash->command[0] = nor->read_opcode; -+ m25p_addr2cmd(nor, from, len, flash->command); -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = m25p_cmdsz(nor, from + len - 1) + dummy; -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].rx_buf = buf; -+ t[1].rx_nbits = m25p80_rx_nbits(nor); -+ t[1].len = len; -+ spi_message_add_tail(&t[1], &m); -+ -+ spi_sync(spi, &m); -+ -+ *retlen = m.actual_length - m25p_cmdsz(nor, from + len - 1) - dummy; -+ return 0; -+} -+ -+static int m25p80_erase(struct spi_nor *nor, loff_t offset) -+{ -+ struct m25p *flash = nor->priv; -+ -+ dev_dbg(nor->dev, "%dKiB at 0x%08x\n", -+ flash->spi_nor.mtd.erasesize / 1024, (u32)offset); -+ -+ /* Set up command buffer. */ -+ flash->command[0] = nor->erase_opcode; -+ m25p_addr2cmd(nor, offset, 1, flash->command); -+ -+ spi_write(flash->spi, flash->command, m25p_cmdsz(nor, offset)); -+ -+ return 0; -+} -+ -+/* -+ * board specific setup should have ensured the SPI clock used here -+ * matches what the READ command supports, at least until this driver -+ * understands FAST_READ (for clocks over 25 MHz). -+ */ -+static int m25p_probe(struct spi_device *spi) -+{ -+ struct mtd_part_parser_data ppdata; -+ struct flash_platform_data *data; -+ struct m25p *flash; -+ struct spi_nor *nor; -+ enum read_mode mode = SPI_NOR_NORMAL; -+ char *flash_name = NULL; -+ int ret; -+ -+ data = dev_get_platdata(&spi->dev); -+ -+ flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); -+ if (!flash) -+ return -ENOMEM; -+ -+ nor = &flash->spi_nor; -+ -+ /* install the hooks */ -+ nor->read = m25p80_read; -+ nor->write = m25p80_write; -+ nor->erase = m25p80_erase; -+ nor->write_reg = m25p80_write_reg; -+ nor->read_reg = m25p80_read_reg; -+ -+ nor->dev = &spi->dev; -+ nor->flash_node = spi->dev.of_node; -+ nor->priv = flash; -+ -+ spi_set_drvdata(spi, flash); -+ flash->spi = spi; -+ -+ if (spi->mode & SPI_RX_QUAD) -+ mode = SPI_NOR_QUAD; -+ else if (spi->mode & SPI_RX_DUAL) -+ mode = SPI_NOR_DUAL; -+ -+ if (data && data->name) -+ nor->mtd.name = data->name; -+ -+ /* For some (historical?) reason many platforms provide two different -+ * names in flash_platform_data: "name" and "type". Quite often name is -+ * set to "m25p80" and then "type" provides a real chip name. -+ * If that's the case, respect "type" and ignore a "name". -+ */ -+ if (data && data->type) -+ flash_name = data->type; -+ else -+ flash_name = spi->modalias; -+ -+ ret = spi_nor_scan(nor, flash_name, mode); -+ if (ret) -+ return ret; -+ -+ ppdata.of_node = spi->dev.of_node; -+ -+ return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, -+ data ? data->parts : NULL, -+ data ? data->nr_parts : 0); -+} -+ -+ -+static int m25p_remove(struct spi_device *spi) -+{ -+ struct m25p *flash = spi_get_drvdata(spi); -+ -+ /* Clean up MTD stuff. */ -+ return mtd_device_unregister(&flash->spi_nor.mtd); -+} -+ -+/* -+ * Do NOT add to this array without reading the following: -+ * -+ * Historically, many flash devices are bound to this driver by their name. But -+ * since most of these flash are compatible to some extent, and their -+ * differences can often be differentiated by the JEDEC read-ID command, we -+ * encourage new users to add support to the spi-nor library, and simply bind -+ * against a generic string here (e.g., "jedec,spi-nor"). -+ * -+ * Many flash names are kept here in this list (as well as in spi-nor.c) to -+ * keep them available as module aliases for existing platforms. -+ */ -+static const struct spi_device_id m25p_ids[] = { -+ /* -+ * Entries not used in DTs that should be safe to drop after replacing -+ * them with "nor-jedec" in platform data. -+ */ -+ {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, -+ -+ /* -+ * Entries that were used in DTs without "nor-jedec" fallback and should -+ * be kept for backward compatibility. -+ */ -+ {"at25df321a"}, {"at25df641"}, {"at26df081a"}, -+ {"mr25h256"}, -+ {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, -+ {"mx25l25635e"},{"mx66l51235l"}, -+ {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, -+ {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, -+ {"s25fl064k"}, -+ {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, -+ {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, -+ {"m25p64"}, {"m25p128"}, -+ {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, -+ {"w25q80bl"}, {"w25q128"}, {"w25q256"}, -+ -+ /* Flashes that can't be detected using JEDEC */ -+ {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, -+ {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, -+ {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, -+ -+ { }, -+}; -+MODULE_DEVICE_TABLE(spi, m25p_ids); -+ -+static const struct of_device_id m25p_of_table[] = { -+ /* -+ * Generic compatibility for SPI NOR that can be identified by the -+ * JEDEC READ ID opcode (0x9F). Use this, if possible. -+ */ -+ { .compatible = "jedec,spi-nor" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, m25p_of_table); -+ -+static struct spi_driver m25p80_driver = { -+ .driver = { -+ .name = "m25p80", -+ .of_match_table = m25p_of_table, -+ }, -+ .id_table = m25p_ids, -+ .probe = m25p_probe, -+ .remove = m25p_remove, -+ -+ /* REVISIT: many of these chips have deep power-down modes, which -+ * should clearly be entered on suspend() to minimize power use. -+ * And also when they're otherwise idle... -+ */ -+}; -+ -+module_spi_driver(m25p80_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Mike Lavender"); -+MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig ---- a/drivers/mtd/maps/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/maps/Kconfig 2017-11-09 17:53:42.700292000 +0800 -@@ -97,6 +97,15 @@ config MSP_FLASH_MAP_LIMIT - default "0x02000000" - depends on MSP_FLASH_MAP_LIMIT_32M - -+config MTD_NOR_XGS_IPROC -+ bool "Broadcom XGS iProc CFI NOR support" -+ depends on (ARCH_XGS_IPROC || COMPILE_TEST) && MTD_CFI -+ default n -+ help -+ This selects a driver for the iProc NOR support. -+ -+ If unsure, say N. -+ - config MTD_SUN_UFLASH - tristate "Sun Microsystems userflash support" - depends on SPARC && MTD_CFI && PCI -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile ---- a/drivers/mtd/maps/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/maps/Makefile 2017-11-09 17:53:42.701291000 +0800 -@@ -43,3 +43,4 @@ obj-$(CONFIG_MTD_VMU) += vmu-flash.o - obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o - obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o - obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o -+obj-$(CONFIG_MTD_NOR_XGS_IPROC) += xgs-iproc-flash.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/maps/xgs-iproc-flash.c b/drivers/mtd/maps/xgs-iproc-flash.c ---- a/drivers/mtd/maps/xgs-iproc-flash.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/mtd/maps/xgs-iproc-flash.c 2017-11-09 17:53:42.757297000 +0800 -@@ -0,0 +1,229 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define IPROC_NOR_COMPATIBLE "brcm,iproc-nor" -+extern void __iomem *get_iproc_dmu_pcu_base(void); -+ -+/* HR2 */ -+#define PNOR_NAND_SEL_REG_OVERRIDE_HR2 2 -+#define PNOR_NAND_SEL_REG_PNOR_SEL_HR2 3 -+ -+/* GH/HR3 */ -+#define PNOR_NAND_SEL_REG_OVERRIDE_GH 0 -+#define PNOR_NAND_SEL_REG_PNOR_SEL_GH 1 -+#define PNOR_DIRECT_CMD_OFFSET 0x10 -+#define PNOR_SET_OPMODE_OFFSET 0X18 -+ -+ -+#define IPROC_STRAP_BOOT_DEV_NAND 1 -+#define IPROC_STRAP_BOOT_DEV_PNOR 4 -+#define ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R 0 -+#define PNOR_set_opmode__set_mw_R 0 -+#define PNOR_direct_cmd__cmd_type_R 21 -+#define IPROC_DMU_STRAPS_OFFSET 0x28 -+#define IPROC_BOOT_STRAP_MASK 0x7 -+#if defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_GH) -+#define IPROC_STRAP_BOOT_DEV_SHIFT 9 -+#elif defined(CONFIG_MACH_GH2) || defined(CONFIG_MACH_SB2) || \ -+ defined(CONFIG_MACH_HR3) -+#define IPROC_STRAP_BOOT_DEV_SHIFT 10 -+#endif -+ -+ -+static struct mtd_info *nor_mtd; -+ -+static struct map_info s29gl_map = { -+ .name = "S29GL", -+ .bankwidth = 4, -+}; -+ -+ -+/* -+ * Initialize FLASH support -+ */ -+static int __init s29gl_mtd_init(void) -+{ -+ struct device_node *np; -+ void __iomem *reg_addr; -+#ifdef CONFIG_MACH_IPROC_P7 -+ void __iomem *reg_strap; -+#endif -+ void __iomem *nor_enable=NULL; -+ struct platform_device *pdev; -+ struct resource *memres; -+ struct mtd_part_parser_data ppdata; -+ u32 straps, val; -+ -+ np = of_find_compatible_node(NULL, NULL, IPROC_NOR_COMPATIBLE); -+ if (!np) { -+ printk(KERN_INFO "No NOR flash controller enabled in DT\n"); -+ return -ENODEV; -+ } -+ -+ if (!of_device_is_available(np)) { -+ printk(KERN_INFO "NOR flash controller disabled in DT\n"); -+ return -ENODEV; -+ } -+ -+ reg_addr = of_iomap(np, 0); -+ if (!reg_addr) { -+ printk(KERN_ERR "NOR base addr ioremap eror\n"); -+ return -EIO; -+ } -+ -+ nor_enable = of_iomap(np, 2); -+ if (!nor_enable) { -+ printk(KERN_ERR "PNOR sel ioremap eror\n"); -+ return -EIO; -+ } -+ -+ /* Check boot device */ -+ straps = readl(get_iproc_dmu_pcu_base() + IPROC_DMU_STRAPS_OFFSET); -+ straps = (straps >> IPROC_STRAP_BOOT_DEV_SHIFT) & IPROC_BOOT_STRAP_MASK; -+ -+ if (straps == IPROC_STRAP_BOOT_DEV_NAND) { -+ /* If booting from NAND, PNOR cannot be used */ -+ return -ENODEV; -+ } else if (straps != IPROC_STRAP_BOOT_DEV_PNOR) { -+ /* Switching to PNOR only if not booting from PNOR */ -+ val = readl_relaxed(nor_enable); -+ if (of_find_compatible_node(NULL, NULL, "brcm,hurricane2")) { -+ val |= (1UL << PNOR_NAND_SEL_REG_OVERRIDE_HR2) | -+ (1UL << PNOR_NAND_SEL_REG_PNOR_SEL_HR2); -+ } else { -+ val |= (1UL << PNOR_NAND_SEL_REG_OVERRIDE_GH) | -+ (1UL << PNOR_NAND_SEL_REG_PNOR_SEL_GH); -+ } -+ writel_relaxed(val, nor_enable); -+ -+#ifdef CONFIG_MACH_IPROC_P7 -+ /* Configure controller memory width based on strap */ -+ reg_strap = of_iomap(np, 3); -+ if (!reg_strap) { -+ printk(KERN_ERR "NOR strap addr ioremap eror\n"); -+ return -EIO; -+ } -+ straps = readl_relaxed(reg_strap) & -+ (1 << ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R); -+ if (straps) { -+ /* 16-bit */ -+ val = readl_relaxed ((void * __iomem) -+ (reg_addr + PNOR_SET_OPMODE_OFFSET)); -+ val |= (1 << PNOR_set_opmode__set_mw_R); -+ writel_relaxed(val, (void * __iomem)( -+ reg_addr + PNOR_SET_OPMODE_OFFSET)); -+ } else { -+ /* 8-bit */ -+ val = readl_relaxed((void * __iomem) -+ (reg_addr + PNOR_SET_OPMODE_OFFSET)); -+ val &= ~(1 << PNOR_set_opmode__set_mw_R); -+ writel_relaxed(val, (void * __iomem) -+ (reg_addr + PNOR_SET_OPMODE_OFFSET)); -+ } -+ val = readl_relaxed((void * __iomem)(reg_addr + -+ PNOR_DIRECT_CMD_OFFSET)); -+ val |= (2 << PNOR_direct_cmd__cmd_type_R); -+ writel_relaxed(val, (void * __iomem)(reg_addr + -+ PNOR_DIRECT_CMD_OFFSET)); -+#endif -+ } -+ -+ printk(KERN_INFO "S29GL-MTD: NOR_INTERFACE Enabled\n"); -+ -+ udelay(1000); -+ -+ pdev = of_find_device_by_node(np); -+ memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ s29gl_map.phys = memres->start; -+ s29gl_map.size = resource_size(memres); -+ s29gl_map.virt = ioremap(s29gl_map.phys, s29gl_map.size); -+ -+ if (!s29gl_map.virt) { -+ printk(KERN_ERR "S29GL-MTD: ioremap failed\n"); -+ if (nor_enable) { -+ /* revert to NAND mode */ -+ val = readl_relaxed(nor_enable); -+ if (of_find_compatible_node(NULL, NULL, -+ "brcm,hurricane2")) -+ val &= ~(1UL << PNOR_NAND_SEL_REG_PNOR_SEL_HR2); -+ else -+ val &= ~(1UL << PNOR_NAND_SEL_REG_PNOR_SEL_GH); -+ writel_relaxed(val, nor_enable); -+ } -+ return -EIO; -+ } -+ -+ simple_map_init(&s29gl_map); -+ -+ // Probe for flash bankwidth 4 -+ printk (KERN_INFO "S29GL-MTD probing 32bit FLASH\n"); -+ nor_mtd = do_map_probe("cfi_probe", &s29gl_map); -+ if (!nor_mtd) { -+ printk (KERN_INFO "S29GL-MTD probing 16bit FLASH\n"); -+ // Probe for bankwidth 2 -+ s29gl_map.bankwidth = 2; -+ nor_mtd = do_map_probe("cfi_probe", &s29gl_map); -+ } -+ -+ if (nor_mtd) { -+ nor_mtd->owner = THIS_MODULE; -+ ppdata.of_node = np; -+ mtd_device_parse_register(nor_mtd, NULL, &ppdata, NULL, 0); -+ printk (KERN_INFO "S29GL-MTD MTD partitions parsed!\n"); -+ return 0; -+ } -+ -+ printk (KERN_INFO "S29GL-MTD NO FLASH found!\n"); -+ if (nor_enable) { -+ /* revert to NAND mode */ -+ val = readl_relaxed(nor_enable); -+ if (of_find_compatible_node(NULL, NULL, "brcm,hurricane2")) -+ val &= ~(1UL << PNOR_NAND_SEL_REG_PNOR_SEL_HR2); -+ else -+ val &= ~(1UL << PNOR_NAND_SEL_REG_PNOR_SEL_GH); -+ writel_relaxed(val, nor_enable); -+ } -+ iounmap((void *)s29gl_map.virt); -+ return -ENXIO; -+} -+ -+/* -+ * Cleanup -+ */ -+static void __exit s29gl_mtd_cleanup(void) -+{ -+ if (nor_mtd) { -+ mtd_device_unregister(nor_mtd); -+ map_destroy(nor_mtd); -+ } -+ -+ if (s29gl_map.virt) { -+ iounmap((void *)s29gl_map.virt); -+ s29gl_map.virt = 0; -+ } -+} -+ -+ -+module_init(s29gl_mtd_init); -+module_exit(s29gl_mtd_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("MTD map driver for Hurricane2 Deerhound evaluation boards"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig ---- a/drivers/mtd/nand/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/nand/Kconfig 2017-11-09 17:53:42.777285000 +0800 -@@ -399,6 +399,17 @@ config MTD_NAND_BRCMNAND - originally designed for Set-Top Box but is used on various BCM7xxx, - BCM3xxx, BCM63xxx, iProc/Cygnus and more. - -+if MTD_NAND_BRCMNAND -+config MTD_NAND_XGS_IPROC -+ bool "XGS iProc NAND controller" -+ depends on ARCH_XGS_IPROC -+ default n -+ help -+ Enable XGS iProc NAND controller. -+ -+ If unsure, say N. -+endif # MTD_NAND_BRCMNAND -+ - config MTD_NAND_BCM47XXNFLASH - tristate "Support for NAND flash on BCM4706 BCMA bus" - depends on BCMA_NFLASH -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c ---- a/drivers/mtd/nand/brcmnand/brcmnand.c 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/nand/brcmnand/brcmnand.c 2017-11-09 17:53:42.804318000 +0800 -@@ -14,7 +14,7 @@ - #include - #include - #include --#include -+/*#include */ - #include - #include - #include -@@ -26,7 +26,7 @@ - #include - #include - #include --#include -+/*#include */ - #include - #include - #include -@@ -1053,8 +1053,16 @@ static void brcmnand_send_cmd(struct brc - ctrl->cmd_pending = cmd; - - intfc = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS); -+ /* Currently one DTS file supports both NAND and PNOR flash, -+ * but not both controllers can be activated at the same time. -+ * The strap pin on board determines either NAND or PNOR flash -+ * controller is active. Need to comment out the following checking -+ * of NAND controller ready, otherwise it will fail as actually the -+ * NAND controller might be disabled. -+ */ -+#if !defined (CONFIG_MTD_NAND_XGS_IPROC) - BUG_ON(!(intfc & INTFC_CTLR_READY)); -- -+#endif - mb(); /* flush previous writes */ - brcmnand_write_reg(ctrl, BRCMNAND_CMD_START, - cmd << brcmnand_cmd_shift(ctrl)); -@@ -1282,9 +1290,20 @@ static uint8_t brcmnand_read_byte(struct - if (host->last_byte > 0 && offs == 0) - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1); - -+ /* For XGS iproc, no byte swap needed for little-endian mode */ -+#if defined (CONFIG_MTD_NAND_XGS_IPROC) -+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) -+ ret = ctrl->flash_cache[offs >> 2] >> -+ (24 - ((offs & 0x03) << 3)); -+ else -+ ret = ctrl->flash_cache[offs >> 2] >> -+ ((offs & 0x03) << 3); -+#else - ret = ctrl->flash_cache[offs >> 2] >> - (24 - ((offs & 0x03) << 3)); -+#endif - break; -+ - case NAND_CMD_GET_FEATURES: - if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) { - ret = 0; -@@ -1483,6 +1502,56 @@ static int brcmnand_read_by_pio(struct m - return ret; - } - -+/* -+ * Check a page to see if it is erased (w/ bitflips) after an uncorrectable ECC -+ * error -+ * -+ * Because the HW ECC signals an ECC error if an erase paged has even a single -+ * bitflip, we must check each ECC error to see if it is actually an erased -+ * page with bitflips, not a truly corrupted page. -+ * -+ * On a real error, return a negative error code (-EBADMSG for ECC error), and -+ * buf will contain raw data. -+ * Otherwise, buf gets filled with 0xffs and return the maximum number of -+ * bitflips-per-ECC-sector to the caller. -+ * -+ */ -+static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, -+ struct nand_chip *chip, void *buf, u64 addr) -+{ -+ int i, sas; -+ void *oob = chip->oob_poi; -+ int bitflips = 0; -+ int page = addr >> chip->page_shift; -+ int ret; -+ -+ if (!buf) { -+ buf = chip->buffers->databuf; -+ /* Invalidate page cache */ -+ chip->pagebuf = -1; -+ } -+ -+ sas = mtd->oobsize / chip->ecc.steps; -+ -+ /* read without ecc for verification */ -+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); -+ ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < chip->ecc.steps; i++, oob += sas) { -+ ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size, -+ oob, sas, NULL, 0, -+ chip->ecc.strength); -+ if (ret < 0) -+ return ret; -+ -+ bitflips = max(bitflips, ret); -+ } -+ -+ return bitflips; -+} -+ - static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, - u64 addr, unsigned int trans, u32 *buf, u8 *oob) - { -@@ -1513,6 +1582,18 @@ static int brcmnand_read(struct mtd_info - } - - if (mtd_is_eccerr(err)) { -+ /* -+ * Controller version 7.2 has hw encoder to detect erased page -+ * bitflips, apply sw verification for older controllers only -+ */ -+ if (ctrl->nand_version < 0x0702) { -+ err = brcmstb_nand_verify_erased_page(mtd, chip, buf, -+ addr); -+ /* erased page bitflips corrected */ -+ if (err >= 0) -+ return err; -+ } -+ - dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", - (unsigned long long)err_addr); - mtd->ecc_stats.failed++; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig ---- a/drivers/mtd/spi-nor/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/spi-nor/Kconfig 2017-11-09 17:53:42.932285000 +0800 -@@ -42,3 +42,38 @@ config SPI_NXP_SPIFI - controller and want to access the Flash as a mtd device. - - endif # MTD_SPI_NOR -+ -+ -+menuconfig MTD_SPI_NOR_IPROC -+ tristate "BRCM IPROC SPI-NOR device support" -+ depends on MTD -+ help -+ This is the framework for the SPI NOR which can be used by the SPI -+ device drivers and the SPI-NOR device driver. -+ -+if MTD_SPI_NOR_IPROC -+ -+config M25PXX_STAY_IN_3BYTE_MODE -+ bool "Stay in 3-byte address mode when idle" -+ default n -+ help -+ This option forces the flash to stay in 3-byte address mode when idle -+ (even for flashes that require 4-byte address). This is work around the -+ reset problem if the controller cannot issue 4-byte OPCODE when booting. -+ -+endif # MTD_SPI_NOR_IPROC -+ -+config MTD_SPI_NOR_USE_4K_SECTORS -+ bool "Use small 4096 B erase sectors" -+ default n -+ help -+ Many flash memories support erasing small (4096 B) sectors. Depending -+ on the usage this feature may provide performance gain in comparison -+ to erasing whole blocks (32/64 KiB). -+ Changing a small part of the flash's contents is usually faster with -+ small sectors. On the other hand erasing should be faster when using -+ 64 KiB block instead of 16 × 4 KiB sectors. -+ -+ Please note that some tools/drivers/filesystems may not work with -+ 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile ---- a/drivers/mtd/spi-nor/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/mtd/spi-nor/Makefile 2017-11-09 17:53:42.933281000 +0800 -@@ -1,3 +1,5 @@ - obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o -+obj-$(CONFIG_MTD_SPI_NOR_IPROC) += spi-nor-iproc.o - obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o - obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/mtd/spi-nor/spi-nor-iproc.c b/drivers/mtd/spi-nor/spi-nor-iproc.c ---- a/drivers/mtd/spi-nor/spi-nor-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/mtd/spi-nor/spi-nor-iproc.c 2017-11-09 17:53:42.936293000 +0800 -@@ -0,0 +1,1467 @@ -+/* -+ Based on spi-nor.c -+ -+ * This code 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+/* Define max times to check status register before we give up. */ -+ -+/* -+ * For everything but full-chip erase; probably could be much smaller, but kept -+ * around for safety for now -+ */ -+#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) -+ -+/* -+ * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up -+ * for larger flash -+ */ -+#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ) -+ -+#define SPI_NOR_MAX_ID_LEN 6 -+ -+struct flash_info { -+ char *name; -+ -+ /* -+ * This array stores the ID bytes. -+ * The first three bytes are the JEDIC ID. -+ * JEDEC ID zero means "no ID" (mostly older chips). -+ */ -+ u8 id[SPI_NOR_MAX_ID_LEN]; -+ u8 id_len; -+ -+ /* The size listed here is what works with SPINOR_OP_SE, which isn't -+ * necessarily called a "sector" by the vendor. -+ */ -+ unsigned sector_size; -+ u16 n_sectors; -+ -+ u16 page_size; -+ u16 addr_width; -+ -+ u16 flags; -+#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -+#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -+#define SST_WRITE 0x04 /* use SST byte programming */ -+#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -+#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -+#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -+#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -+#define USE_FSR 0x80 /* use flag status register */ -+}; -+ -+#define JEDEC_MFR(info) ((info)->id[0]) -+ -+static const struct flash_info *spi_nor_match_id(const char *name); -+ -+/* -+ * Read the status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_sr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading SR\n", (int) ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read the flag status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_fsr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading FSR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read configuration register, returning its value in the -+ * location. Return the configuration register value. -+ * Returns negative if error occured. -+ */ -+static int read_cr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading CR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Dummy Cycle calculation for different type of read. -+ * It can be used to support more commands with -+ * different dummy cycle requirements. -+ */ -+static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) -+{ -+ switch (nor->flash_read) { -+ case SPI_NOR_FAST: -+ case SPI_NOR_DUAL: -+ case SPI_NOR_QUAD: -+ return 8; -+ case SPI_NOR_NORMAL: -+ return 0; -+ } -+ return 0; -+} -+ -+/* -+ * Write status register 1 byte -+ * Returns negative if error occurred. -+ */ -+static inline int write_sr(struct spi_nor *nor, u8 val) -+{ -+ nor->cmd_buf[0] = val; -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); -+} -+ -+/* -+ * Set write enable latch with Write Enable command. -+ * Returns negative if error occurred. -+ */ -+static inline int write_enable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); -+} -+ -+/* -+ * Send write disble instruction to the chip. -+ */ -+static inline int write_disable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); -+} -+ -+static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) -+{ -+ return mtd->priv; -+} -+ -+/* Enable/disable 4-byte addressing mode. */ -+static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, -+ int enable) -+{ -+ int status; -+ bool need_wren = false; -+ u8 cmd; -+ -+ switch (JEDEC_MFR(info)) { -+ case SNOR_MFR_MICRON: -+ /* Some Micron need WREN command; all will accept it */ -+ need_wren = true; -+ case SNOR_MFR_MACRONIX: -+ case SNOR_MFR_WINBOND: -+ if (need_wren) -+ write_enable(nor); -+ -+ cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; -+ status = nor->write_reg(nor, cmd, NULL, 0); -+ if (need_wren) -+ write_disable(nor); -+ -+ return status; -+ default: -+ /* Spansion style */ -+ nor->cmd_buf[0] = enable << 7; -+ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); -+ } -+} -+static inline int spi_nor_sr_ready(struct spi_nor *nor) -+{ -+ int sr = read_sr(nor); -+ if (sr < 0) -+ return sr; -+ else -+ return !(sr & SR_WIP); -+} -+ -+static inline int spi_nor_fsr_ready(struct spi_nor *nor) -+{ -+ int fsr = read_fsr(nor); -+ if (fsr < 0) -+ return fsr; -+ else -+ return fsr & FSR_READY; -+} -+ -+static int spi_nor_ready(struct spi_nor *nor) -+{ -+ int sr, fsr; -+ sr = spi_nor_sr_ready(nor); -+ if (sr < 0) -+ return sr; -+ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; -+ if (fsr < 0) -+ return fsr; -+ return sr && fsr; -+} -+ -+/* -+ * Service routine to read status register until ready, or timeout occurs. -+ * Returns non-zero if error. -+ */ -+static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, -+ unsigned long timeout_jiffies) -+{ -+ unsigned long deadline; -+ int timeout = 0, ret; -+ -+ deadline = jiffies + timeout_jiffies; -+ -+ while (!timeout) { -+ if (time_after_eq(jiffies, deadline)) -+ timeout = 1; -+ -+ ret = spi_nor_ready(nor); -+ if (ret < 0) -+ return ret; -+ if (ret) -+ return 0; -+ -+ cond_resched(); -+ } -+ -+ dev_err(nor->dev, "flash operation timed out\n"); -+ -+ return -ETIMEDOUT; -+} -+ -+static int spi_nor_wait_till_ready(struct spi_nor *nor) -+{ -+ return spi_nor_wait_till_ready_with_timeout(nor, -+ DEFAULT_READY_WAIT_JIFFIES); -+} -+ -+/* -+ * Erase the whole flash memory -+ * -+ * Returns 0 if successful, non-zero otherwise. -+ */ -+static int erase_chip(struct spi_nor *nor) -+{ -+ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); -+ -+ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); -+} -+ -+static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ int ret = 0; -+ -+ mutex_lock(&nor->lock); -+ -+ if (nor->prepare) { -+ ret = nor->prepare(nor, ops); -+ if (ret) { -+ dev_err(nor->dev, "failed in the preparation.\n"); -+ mutex_unlock(&nor->lock); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ if (nor->unprepare) -+ nor->unprepare(nor, ops); -+ mutex_unlock(&nor->lock); -+} -+ -+/* -+ * Erase an address range on the nor chip. The address range may extend -+ * one or more erase sectors. Return an error is there is a problem erasing. -+ */ -+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 addr, len; -+ uint32_t rem; -+ int ret; -+ -+ dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, -+ (long long)instr->len); -+ -+ div_u64_rem(instr->len, mtd->erasesize, &rem); -+ if (rem) -+ return -EINVAL; -+ -+ addr = instr->addr; -+ len = instr->len; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE); -+ if (ret) -+ return ret; -+ -+ /* whole-chip erase? */ -+ if (len == mtd->size) { -+ unsigned long timeout; -+ -+ write_enable(nor); -+ -+ if (erase_chip(nor)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ /* -+ * Scale the timeout linearly with the size of the flash, with -+ * a minimum calibrated to an old 2MB flash. We could try to -+ * pull these from CFI/SFDP, but these values should be good -+ * enough for now. -+ */ -+ timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES, -+ CHIP_ERASE_2MB_READY_WAIT_JIFFIES * -+ (unsigned long)(mtd->size / SZ_2M)); -+ ret = spi_nor_wait_till_ready_with_timeout(nor, timeout); -+ if (ret) -+ goto erase_err; -+ -+ /* REVISIT in some cases we could speed up erasing large regions -+ * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up -+ * to use "small sector erase", but that's not always optimal. -+ */ -+ -+ /* "sector"-at-a-time erase */ -+ } else { -+ while (len) { -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Set to 4-byte mode if addr >= 16M */ -+ /* Note: set_4byte will call write_disable for Micron flash, so set_4byte should be called before the following write_enable(nor) */ -+ if ( addr >= 0x1000000 ) -+ set_4byte(nor, nor->priv1, 1); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_enable(nor); -+ -+ if (nor->erase(nor, addr)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ addr += mtd->erasesize; -+ len -= mtd->erasesize; -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto erase_err; -+ } -+ } -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Reset to 3-byte mode if it was set to 4-byte mode */ -+ if (addr >= 0x1000000) { -+ spi_nor_wait_till_ready(nor); -+ set_4byte(nor, nor->priv1, 0); -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_disable(nor); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ -+ instr->state = MTD_ERASE_DONE; -+ mtd_erase_callback(instr); -+ -+ return ret; -+ -+erase_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ instr->state = MTD_ERASE_FAILED; -+ return ret; -+} -+ -+static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, -+ uint64_t *len) -+{ -+ struct mtd_info *mtd = &nor->mtd; -+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -+ int shift = ffs(mask) - 1; -+ int pow; -+ -+ if (!(sr & mask)) { -+ /* No protection */ -+ *ofs = 0; -+ *len = 0; -+ } else { -+ pow = ((sr & mask) ^ mask) >> shift; -+ *len = mtd->size >> pow; -+ *ofs = mtd->size - *len; -+ } -+} -+ -+/* -+ * Return 1 if the entire region is locked, 0 otherwise -+ */ -+static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, -+ u8 sr) -+{ -+ loff_t lock_offs; -+ uint64_t lock_len; -+ -+ stm_get_locked_range(nor, sr, &lock_offs, &lock_len); -+ -+ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); -+} -+ -+/* -+ * Lock a region of the flash. Compatible with ST Micro and similar flash. -+ * Supports only the block protection bits BP{0,1,2} in the status register -+ * (SR). Does not support these features found in newer SR bitfields: -+ * - TB: top/bottom protect - only handle TB=0 (top protect) -+ * - SEC: sector/block protect - only handle SEC=0 (block protect) -+ * - CMP: complement protect - only support CMP=0 (range is not complemented) -+ * -+ * Sample table portion for 8MB flash (Winbond w25q64fw): -+ * -+ * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion -+ * -------------------------------------------------------------------------- -+ * X | X | 0 | 0 | 0 | NONE | NONE -+ * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 -+ * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 -+ * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 -+ * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 -+ * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 -+ * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 -+ * X | X | 1 | 1 | 1 | 8 MB | ALL -+ * -+ * Returns negative on errors, 0 on success. -+ */ -+static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) -+{ -+ struct mtd_info *mtd = &nor->mtd; -+ u8 status_old, status_new; -+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -+ u8 shift = ffs(mask) - 1, pow, val; -+ -+ status_old = read_sr(nor); -+ -+ /* SPI NOR always locks to the end */ -+ if (ofs + len != mtd->size) { -+ /* Does combined region extend to end? */ -+ if (!stm_is_locked_sr(nor, ofs + len, mtd->size - ofs - len, -+ status_old)) -+ return -EINVAL; -+ len = mtd->size - ofs; -+ } -+ -+ /* -+ * Need smallest pow such that: -+ * -+ * 1 / (2^pow) <= (len / size) -+ * -+ * so (assuming power-of-2 size) we do: -+ * -+ * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) -+ */ -+ pow = ilog2(mtd->size) - ilog2(len); -+ val = mask - (pow << shift); -+ if (val & ~mask) -+ return -EINVAL; -+ /* Don't "lock" with no region! */ -+ if (!(val & mask)) -+ return -EINVAL; -+ -+ status_new = (status_old & ~mask) | val; -+ -+ /* Only modify protection if it will not unlock other areas */ -+ if ((status_new & mask) <= (status_old & mask)) -+ return -EINVAL; -+ -+ write_enable(nor); -+ return write_sr(nor, status_new); -+} -+ -+/* -+ * Unlock a region of the flash. See stm_lock() for more info -+ * -+ * Returns negative on errors, 0 on success. -+ */ -+static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) -+{ -+ struct mtd_info *mtd = &nor->mtd; -+ uint8_t status_old, status_new; -+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -+ u8 shift = ffs(mask) - 1, pow, val; -+ -+ status_old = read_sr(nor); -+ -+ /* Cannot unlock; would unlock larger region than requested */ -+ if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, -+ status_old)) -+ return -EINVAL; -+ -+ /* -+ * Need largest pow such that: -+ * -+ * 1 / (2^pow) >= (len / size) -+ * -+ * so (assuming power-of-2 size) we do: -+ * -+ * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) -+ */ -+ pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); -+ if (ofs + len == mtd->size) { -+ val = 0; /* fully unlocked */ -+ } else { -+ val = mask - (pow << shift); -+ /* Some power-of-two sizes are not supported */ -+ if (val & ~mask) -+ return -EINVAL; -+ } -+ -+ status_new = (status_old & ~mask) | val; -+ -+ /* Only modify protection if it will not lock other areas */ -+ if ((status_new & mask) >= (status_old & mask)) -+ return -EINVAL; -+ -+ write_enable(nor); -+ return write_sr(nor, status_new); -+} -+ -+/* -+ * Check if a region of the flash is (completely) locked. See stm_lock() for -+ * more info. -+ * -+ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and -+ * negative on errors. -+ */ -+static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) -+{ -+ int status; -+ -+ status = read_sr(nor); -+ if (status < 0) -+ return status; -+ -+ return stm_is_locked_sr(nor, ofs, len, status); -+} -+ -+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); -+ if (ret) -+ return ret; -+ -+ ret = nor->flash_lock(nor, ofs, len); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); -+ return ret; -+} -+ -+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -+ if (ret) -+ return ret; -+ -+ ret = nor->flash_unlock(nor, ofs, len); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+ return ret; -+} -+ -+static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -+ if (ret) -+ return ret; -+ -+ ret = nor->flash_is_locked(nor, ofs, len); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+ return ret; -+} -+ -+/* Used when the "_ext_id" is two bytes at most */ -+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+ .id = { \ -+ ((_jedec_id) >> 16) & 0xff, \ -+ ((_jedec_id) >> 8) & 0xff, \ -+ (_jedec_id) & 0xff, \ -+ ((_ext_id) >> 8) & 0xff, \ -+ (_ext_id) & 0xff, \ -+ }, \ -+ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+ .flags = (_flags), -+ -+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+ .id = { \ -+ ((_jedec_id) >> 16) & 0xff, \ -+ ((_jedec_id) >> 8) & 0xff, \ -+ (_jedec_id) & 0xff, \ -+ ((_ext_id) >> 16) & 0xff, \ -+ ((_ext_id) >> 8) & 0xff, \ -+ (_ext_id) & 0xff, \ -+ }, \ -+ .id_len = 6, \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+ .flags = (_flags), -+ -+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = (_page_size), \ -+ .addr_width = (_addr_width), \ -+ .flags = (_flags), -+ -+/* NOTE: double check command sets and memory organization when you add -+ * more nor chips. This current list focusses on newer chips, which -+ * have been converging on command sets which including JEDEC ID. -+ * -+ * All newly added entries should describe *hardware* and should use SECT_4K -+ * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage -+ * scenarios excluding small sectors there is config option that can be -+ * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. -+ * For historical (and compatibility) reasons (before we got above config) some -+ * old entries may be missing 4K flag. -+ */ -+static const struct flash_info spi_nor_ids[] = { -+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */ -+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, -+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, -+ -+ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, -+ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, -+ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, -+ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, -+ -+ /* EON -- en25xxx */ -+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, -+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, -+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, -+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, -+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, -+ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* ESMT */ -+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Everspin */ -+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ -+ /* Fujitsu */ -+ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, -+ -+ /* GigaDevice */ -+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, -+ -+ /* Intel/Numonyx -- xxxs33b */ -+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -+ -+ /* ISSI */ -+ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, -+ -+ /* Macronix */ -+ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, -+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, -+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, -+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, -+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, -+ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, -+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, -+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, -+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, -+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) }, -+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -+ -+ /* Micron */ -+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, -+ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, -+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ -+ /* PMC */ -+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, -+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Spansion -- single (large) sector size only, at least -+ * for the chips listed here (without boot sectors). -+ */ -+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, -+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, -+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, -+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, -+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, -+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, -+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, -+ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) }, -+ -+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */ -+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, -+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, -+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, -+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, -+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, -+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, -+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, -+ { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, -+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) }, -+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, -+ { "sst26vf016", INFO(0xbf2601, 0, 64 * 1024, 32, SECT_4K) }, -+ { "sst26vf032", INFO(0xbf2602, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* ST Microelectronics -- newer production may have feature updates */ -+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, -+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, -+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, -+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, -+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, -+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, -+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, -+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, -+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, -+ -+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, -+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, -+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, -+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, -+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, -+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, -+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, -+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, -+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, -+ -+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, -+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, -+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, -+ -+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) }, -+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, -+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, -+ -+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) }, -+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, -+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, -+ -+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ -+ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, -+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, -+ { "w25m512", INFO(0xef7119, 0, 64 * 1024, 1024, SECT_4K) }, -+ -+ /* Catalyst / On Semiconductor -- non-JEDEC */ -+ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { }, -+}; -+ -+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -+{ -+ int tmp; -+ u8 id[SPI_NOR_MAX_ID_LEN]; -+ const struct flash_info *info; -+ -+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); -+ if (tmp < 0) { -+ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); -+ return ERR_PTR(tmp); -+ } -+ -+ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { -+ info = &spi_nor_ids[tmp]; -+ if (info->id_len) { -+ if (!memcmp(info->id, id, info->id_len)) -+ return &spi_nor_ids[tmp]; -+ } -+ } -+ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", -+ id[0], id[1], id[2]); -+ return ERR_PTR(-ENODEV); -+} -+ -+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ); -+ if (ret) -+ return ret; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* set to 4-byte mode */ -+ if (from + len > 0x1000000) -+ set_4byte(nor, nor->priv1, 1); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ ret = nor->read(nor, from, len, retlen, buf); -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* set to 3-byte mode */ -+ if (from + len > 0x1000000) -+ set_4byte(nor, nor->priv1, 0); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); -+ return ret; -+} -+ -+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ size_t actual; -+ int ret; -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ int addr_4byte = 0; -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* set to 4-byte mode */ -+ if (to >= 0x1000000) { -+ set_4byte(nor, nor->priv1, 1); -+ addr_4byte = 1; -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_enable(nor); -+ -+ nor->sst_write_second = false; -+ -+ actual = to % 2; -+ /* Start write from odd address. */ -+ if (actual) { -+ nor->program_opcode = SPINOR_OP_BP; -+ -+ /* write one byte. */ -+ nor->write(nor, to, 1, retlen, buf); -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ } -+ to += actual; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Use 4-byte mode only if the address is > 16MB */ -+ if (to >= 0x1000000 && !addr_4byte) { -+ set_4byte(nor, nor->priv1, 1); -+ addr_4byte = 1; -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ /* Write out most of the data here. */ -+ for (; actual < len - 1; actual += 2) { -+ nor->program_opcode = SPINOR_OP_AAI_WP; -+ -+ /* write two bytes. */ -+ nor->write(nor, to, 2, retlen, buf + actual); -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ to += 2; -+ nor->sst_write_second = true; -+ } -+ nor->sst_write_second = false; -+ -+ write_disable(nor); -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+ /* Write out trailing byte if it exists. */ -+ if (actual != len) { -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Use 4-byte mode only if the address is > 16MB */ -+ if (to >= 0x1000000 && !addr_4byte) { -+ set_4byte(nor, nor->priv1, 1); -+ addr_4byte = 1; -+ } -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_enable(nor); -+ -+ nor->program_opcode = SPINOR_OP_BP; -+ nor->write(nor, to, 1, retlen, buf + actual); -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ write_disable(nor); -+ } -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* Reset to 3-byte mode if the address is > 16MB */ -+ if (addr_4byte) -+ set_4byte(nor, nor->priv1, 0); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+time_out: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return ret; -+} -+ -+/* -+ * Write an address range to the nor chip. Data must be written in -+ * FLASH_PAGESIZE chunks. The address range may be any size provided -+ * it is within the physical boundaries. -+ */ -+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 page_offset, page_size, i; -+ int ret; -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* set to 4-byte mode */ -+ /* Note: set_4byte will call write_disable for Micron flash, so set_4byte should be called before the following write_enable(nor) */ -+ if (to >= 0x1000000) -+ set_4byte(nor, nor->priv1, 1); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_enable(nor); -+ -+ page_offset = to & (nor->page_size - 1); -+ -+ /* do all the bytes fit onto one page? */ -+ if (page_offset + len <= nor->page_size) { -+ nor->write(nor, to, len, retlen, buf); -+ } else { -+ /* the size of data remaining on the first page */ -+ page_size = nor->page_size - page_offset; -+ nor->write(nor, to, page_size, retlen, buf); -+ -+ /* write everything in nor->page_size chunks */ -+ for (i = page_size; i < len; i += page_size) { -+ page_size = len - i; -+ if (page_size > nor->page_size) -+ page_size = nor->page_size; -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto write_err; -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* set to 4-byte mode if this is the first time > 16MB*/ -+ if ( (to + i - page_size < 0x1000000) && (to + i >= 0x1000000) ) -+ set_4byte(nor, nor->priv1, 1); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+ write_enable(nor); -+ -+ nor->write(nor, to + i, page_size, retlen, buf + i); -+ } -+ } -+ -+ ret = spi_nor_wait_till_ready(nor); -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* reset to 3-byte mode*/ -+ if (to + len >= 0x1000000) -+ set_4byte(nor, nor->priv1, 0); -+#endif /* CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ -+write_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return ret; -+} -+ -+static int macronix_quad_enable(struct spi_nor *nor) -+{ -+ int ret, val; -+ -+ val = read_sr(nor); -+ write_enable(nor); -+ -+ write_sr(nor, val | SR_QUAD_EN_MX); -+ -+ if (spi_nor_wait_till_ready(nor)) -+ return 1; -+ -+ ret = read_sr(nor); -+ if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { -+ dev_err(nor->dev, "Macronix Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Write status Register and configuration register with 2 bytes -+ * The first byte will be written to the status register, while the -+ * second byte will be written to the configuration register. -+ * Return negative if error occured. -+ */ -+static int write_sr_cr(struct spi_nor *nor, u16 val) -+{ -+ nor->cmd_buf[0] = val & 0xff; -+ nor->cmd_buf[1] = (val >> 8); -+ -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2); -+} -+ -+static int spansion_quad_enable(struct spi_nor *nor) -+{ -+ int ret; -+ int quad_en = CR_QUAD_EN_SPAN << 8; -+ -+ write_enable(nor); -+ -+ ret = write_sr_cr(nor, quad_en); -+ if (ret < 0) { -+ dev_err(nor->dev, -+ "error while writing configuration register\n"); -+ return -EINVAL; -+ } -+ -+ /* read back and check it */ -+ ret = read_cr(nor); -+ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { -+ dev_err(nor->dev, "Spansion Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int micron_quad_enable(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading EVCR\n", ret); -+ return ret; -+ } -+ -+ write_enable(nor); -+ -+ /* set EVCR, enable quad I/O */ -+ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; -+ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error while writing EVCR register\n"); -+ return ret; -+ } -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* read EVCR and check it */ -+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading EVCR\n", ret); -+ return ret; -+ } -+ if (val & EVCR_QUAD_EN_MICRON) { -+ dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) -+{ -+ int status; -+ -+ switch (JEDEC_MFR(info)) { -+ case SNOR_MFR_MACRONIX: -+ status = macronix_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Macronix quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ case SNOR_MFR_MICRON: -+ status = micron_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Micron quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ default: -+ status = spansion_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Spansion quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ } -+} -+ -+static int spi_nor_check(struct spi_nor *nor) -+{ -+ if (!nor->dev || !nor->read || !nor->write || -+ !nor->read_reg || !nor->write_reg || !nor->erase) { -+ pr_err("spi-nor: please fill all the necessary fields!\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) -+{ -+ const struct flash_info *info = NULL; -+ struct device *dev = nor->dev; -+ struct mtd_info *mtd = &nor->mtd; -+ struct device_node *np = nor->flash_node; -+ int ret; -+ int i; -+ -+ ret = spi_nor_check(nor); -+ if (ret) -+ return ret; -+ -+ if (name) -+ info = spi_nor_match_id(name); -+ /* Try to auto-detect if chip name wasn't specified or not found */ -+ if (!info) -+ info = spi_nor_read_id(nor); -+ if (IS_ERR_OR_NULL(info)) -+ return -ENOENT; -+ -+ /* -+ * If caller has specified name of flash model that can normally be -+ * detected using JEDEC, let's verify it. -+ */ -+ if (name && info->id_len) { -+ const struct flash_info *jinfo; -+ -+ jinfo = spi_nor_read_id(nor); -+ if (IS_ERR(jinfo)) { -+ return PTR_ERR(jinfo); -+ } else if (jinfo != info) { -+ /* -+ * JEDEC knows better, so overwrite platform ID. We -+ * can't trust partitions any longer, but we'll let -+ * mtd apply them anyway, since some partitions may be -+ * marked read-only, and we don't want to lose that -+ * information, even if it's not 100% accurate. -+ */ -+ dev_warn(dev, "found %s, expected %s\n", -+ jinfo->name, info->name); -+ info = jinfo; -+ } -+ } -+ -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ /* keep the flash_info pointer for use with call to set_4byte() */ -+ nor->priv1 = info; -+#endif -+ -+ mutex_init(&nor->lock); -+ -+ /* -+ * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up -+ * with the software protection bits set -+ */ -+ -+ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || -+ JEDEC_MFR(info) == SNOR_MFR_INTEL || -+ JEDEC_MFR(info) == SNOR_MFR_SST) { -+ write_enable(nor); -+ write_sr(nor, 0); -+ } -+ -+ if (!mtd->name) -+ mtd->name = dev_name(dev); -+ mtd->priv = nor; -+ mtd->type = MTD_NORFLASH; -+ mtd->writesize = 1; -+ mtd->flags = MTD_CAP_NORFLASH; -+ mtd->size = info->sector_size * info->n_sectors; -+ mtd->_erase = spi_nor_erase; -+ mtd->_read = spi_nor_read; -+ -+ /* NOR protection support for STmicro/Micron chips and similar */ -+ if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { -+ nor->flash_lock = stm_lock; -+ nor->flash_unlock = stm_unlock; -+ nor->flash_is_locked = stm_is_locked; -+ } -+ -+ if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) { -+ mtd->_lock = spi_nor_lock; -+ mtd->_unlock = spi_nor_unlock; -+ mtd->_is_locked = spi_nor_is_locked; -+ } -+ -+ /* sst nor chips use AAI word program */ -+ if (info->flags & SST_WRITE) -+ mtd->_write = sst_write; -+ else -+ mtd->_write = spi_nor_write; -+ -+ if (info->flags & USE_FSR) -+ nor->flags |= SNOR_F_USE_FSR; -+ -+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS -+ /* prefer "small sector" erase if possible */ -+ if (info->flags & SECT_4K) { -+ nor->erase_opcode = SPINOR_OP_BE_4K; -+ mtd->erasesize = 4096; -+ } else if (info->flags & SECT_4K_PMC) { -+ nor->erase_opcode = SPINOR_OP_BE_4K_PMC; -+ mtd->erasesize = 4096; -+ } else -+#endif -+ { -+ nor->erase_opcode = SPINOR_OP_SE; -+ mtd->erasesize = info->sector_size; -+ } -+ -+ if (info->flags & SPI_NOR_NO_ERASE) -+ mtd->flags |= MTD_NO_ERASE; -+ -+ mtd->dev.parent = dev; -+ nor->page_size = info->page_size; -+ mtd->writebufsize = nor->page_size; -+ -+ if (np) { -+ /* If we were instantiated by DT, use it */ -+ if (of_property_read_bool(np, "m25p,fast-read")) -+ nor->flash_read = SPI_NOR_FAST; -+ else -+ nor->flash_read = SPI_NOR_NORMAL; -+ } else { -+ /* If we weren't instantiated by DT, default to fast-read */ -+ nor->flash_read = SPI_NOR_FAST; -+ } -+ -+ /* Some devices cannot do fast-read, no matter what DT tells us */ -+ if (info->flags & SPI_NOR_NO_FR) -+ nor->flash_read = SPI_NOR_NORMAL; -+ -+ /* Quad/Dual-read mode takes precedence over fast/normal */ -+ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -+ ret = set_quad_mode(nor, info); -+ if (ret) { -+ dev_err(dev, "quad mode not supported\n"); -+ return ret; -+ } -+ nor->flash_read = SPI_NOR_QUAD; -+ } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { -+ nor->flash_read = SPI_NOR_DUAL; -+ } -+ -+ /* Default commands */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ; -+ break; -+ default: -+ dev_err(dev, "No Read opcode defined\n"); -+ return -EINVAL; -+ } -+ -+ nor->program_opcode = SPINOR_OP_PP; -+ -+ if (info->addr_width) -+ nor->addr_width = info->addr_width; -+ else { -+#ifndef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ if (mtd->size > 0x1000000) { -+ /* enable 4-byte addressing if the device exceeds 16MiB */ -+ nor->addr_width = 4; -+ if (JEDEC_MFR(info) == CFI_MFR_AMD) { -+ /* Dedicated 4-byte command set */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ4_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ4; -+ break; -+ } -+ nor->program_opcode = SPINOR_OP_PP_4B; -+ /* No small sector erase for 4-byte command set */ -+ nor->erase_opcode = SPINOR_OP_SE_4B; -+ mtd->erasesize = info->sector_size; -+ } else -+ set_4byte(nor, info, 1); -+ } else -+#endif /* !CONFIG_M25PXX_STAY_IN_3BYTE_MODE */ -+ nor->addr_width = 3; -+ } -+ -+ nor->read_dummy = spi_nor_read_dummy_cycles(nor); -+ -+ dev_info(dev, "%s (%lld Kbytes)\n", info->name, -+ (long long)mtd->size >> 10); -+ -+ dev_dbg(dev, -+ "mtd .name = %s, .size = 0x%llx (%lldMiB), " -+ ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", -+ mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), -+ mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); -+ -+ if (mtd->numeraseregions) -+ for (i = 0; i < mtd->numeraseregions; i++) -+ dev_dbg(dev, -+ "mtd.eraseregions[%d] = { .offset = 0x%llx, " -+ ".erasesize = 0x%.8x (%uKiB), " -+ ".numblocks = %d }\n", -+ i, (long long)mtd->eraseregions[i].offset, -+ mtd->eraseregions[i].erasesize, -+ mtd->eraseregions[i].erasesize / 1024, -+ mtd->eraseregions[i].numblocks); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_nor_scan); -+ -+static const struct flash_info *spi_nor_match_id(const char *name) -+{ -+ const struct flash_info *id = spi_nor_ids; -+ -+ while (id->name) { -+ if (!strcmp(name, id->name)) -+ return id; -+ id++; -+ } -+ return NULL; -+} -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("framework for SPI NOR"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig ---- a/drivers/net/ethernet/broadcom/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/Kconfig 2017-11-09 17:53:43.698295000 +0800 -@@ -190,4 +190,8 @@ config BNXT_SRIOV - Virtualization support in the NetXtreme-C/E products. This - allows for virtual function acceleration in virtual environments. - -+source "drivers/net/ethernet/broadcom/gmac/et/Kconfig" -+source "drivers/net/ethernet/broadcom/gmac/hnd/Kconfig" -+source "drivers/net/ethernet/broadcom/mdio/Kconfig" -+ - endif # NET_VENDOR_BROADCOM -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile ---- a/drivers/net/ethernet/broadcom/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/Makefile 2017-11-09 17:53:43.699295000 +0800 -@@ -11,5 +11,8 @@ obj-$(CONFIG_BNX2X) += bnx2x/ - obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o - obj-$(CONFIG_TIGON3) += tg3.o - obj-$(CONFIG_BGMAC) += bgmac.o -+obj-$(CONFIG_MDIO_XGS_IPROC) += mdio/ -+obj-$(CONFIG_GMAC_XGS_IPROC) += gmac/et/ -+obj-$(CONFIG_GMAC_XGS_IPROC) += gmac/hnd/ - obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o - obj-$(CONFIG_BNXT) += bnxt/ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/et/Kconfig b/drivers/net/ethernet/broadcom/gmac/et/Kconfig ---- a/drivers/net/ethernet/broadcom/gmac/et/Kconfig 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/et/Kconfig 2017-11-09 17:53:43.878296000 +0800 -@@ -0,0 +1,26 @@ -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+config GMAC_XGS_IPROC -+ tristate "BRCM XGS iProc GMAC support " -+ select HND -+ select ET -+ select ET_ALL_PASSIVE_ON -+ depends on ARCH_XGS_IPROC -+ default n -+ help -+ Add GMAC support -+ -+ If unsure, say N. -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/et/Makefile b/drivers/net/ethernet/broadcom/gmac/et/Makefile ---- a/drivers/net/ethernet/broadcom/gmac/et/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/et/Makefile 2017-11-09 17:53:43.879292000 +0800 -@@ -0,0 +1,67 @@ -+# -+# Makefile for the Broadcom et driver -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+ETSRCDIR := ../src/et -+ -+et-objs := $(ETSRCDIR)/sys/et_linux.o $(ETSRCDIR)/sys/etc.o -+ -+## from linux dir ########## -+export SRCBASE_et := $(src)/$(ETSRCDIR)/sys/../../ -+KBUILD_CFLAGS += -I$(SRCBASE_et)/include -DBCMDRIVER -Dlinux -+KBUILD_AFLAGS += -I$(SRCBASE_et)/include -+################################# -+obj-$(CONFIG_ET) := et.o -+ -+et-objs += $(ETSRCDIR)/sys/etcgmac.o -+EXTRA_CFLAGS += -DDMA -Wno-error -+EXTRA_CFLAGS += -DGMAC_RATE_LIMITING -DBCMDMA32 -DBCMDBG_ERR -+ -+ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) -+EXTRA_CFLAGS += -DBCMDMASGLISTOSL -+endif -+ -+ifeq ($(CONFIG_ET_ALL_PASSIVE_ON),y) -+EXTRA_CFLAGS += -DGMAC_ALL_PASSIVE -+else -+ifeq ($(CONFIG_ET_ALL_PASSIVE_RUNTIME),y) -+EXTRA_CFLAGS += -DGMAC_ALL_PASSIVE -+endif -+endif -+ -+ifeq ($(CONFIG_ET_NAPI_POLL),y) -+EXTRA_CFLAGS += -DGMAC_NAPI_POLL -+else -+ifeq ($(CONFIG_ET_NAPI2_POLL),y) -+EXTRA_CFLAGS += -DGMAC_NAPI2_POLL -+endif -+endif -+ -+EXTRA_CFLAGS += -I$(src)/$(ETSRCDIR)/sys -+ -+ifneq ($(KERNELRELEASE),) -+# kbuild part of makefile -+else -+# Normal makefile -+KERNELDIR := ../../kernel/linux -+all: -+ $(MAKE) -C $(KERNELDIR) M=`pwd` -+ -+clean: -+ $(MAKE) -C $(KERNELDIR) M=`pwd` clean -+endif -+ -+clean-files += $(ETSRCDIR)/sys/*.o $(ETSRCDIR)/sys/.*.o.cmd -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/hnd/Kconfig b/drivers/net/ethernet/broadcom/gmac/hnd/Kconfig ---- a/drivers/net/ethernet/broadcom/gmac/hnd/Kconfig 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/hnd/Kconfig 2017-11-09 17:53:43.880305000 +0800 -@@ -0,0 +1,100 @@ -+# -+# Broadcom Home Networking Division (HND) driver configuration -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+ -+menu "Broadcom HND network devices" -+# Kenlo depends on PCI -+config HND -+ bool "Broadcom HND network device support" -+ depends on GMAC_XGS_IPROC -+config ET -+ tristate "10/100 Ethernet support" -+ depends on HND -+choice -+ prompt "ET ALL PASSIVE mode" -+ depends on ET -+ optional -+config ET_ALL_PASSIVE_ON -+ bool "ET ALL PASSIVE on" -+config ET_ALL_PASSIVE_RUNTIME -+ bool "ET ALL PASSIVE with runtime setting" -+endchoice -+config ET_NAPI2_POLL -+ bool "BCM GMAC NAPI2_POLL" -+ default n -+ depends on !ET_ALL_PASSIVE_ON && !ET_ALL_PASSIVE_RUNTIME -+config BCM_IPROC_GMAC_ACP -+ tristate "BCM GMAC_ACP support" -+ depends on HND -+ default n -+ help -+ Add GMAC_ACP support to improve performance without -+ cache flushing/invalidate. The uboot's bootargs must -+ include "mem=240M" to limit whole Kernel memory inside -+ ACP region which is 256MB from 0x80000000; since kernel -+ starts from 0x81000000, total mem is 240MB only -+ If unsure, say N. -+config BCM_IPROC_GMAC_PREFETCH -+ tristate "BCM GMAC prefetching support" -+ depends on HND -+ default n -+ help -+ If unsure, say N. -+config BCM_IPROC_GMAC_TXONCPU1 -+ tristate "BCM GMAC TX-ON-CPU1 support" -+ depends on HND && SMP && (ET_ALL_PASSIVE_ON || ET_ALL_PASSIVE_RUNTIME) -+ default n -+ help -+ Run "Passive Mode" Tx workthread on CPU1 for -+ multi-cores utilizing; -+ If unsure, say N. -+config BCM_IPROC_GMAC_LOCK_OPT -+ tristate "BCM GMAC LOCK OPTIMIZATION support" -+ depends on HND -+ default n -+ help -+ Minimize locks during Tx/Rx tasks; -+ it is tested under "Passive Mode" (workthread) only. -+ If unsure, say N. -+config BCM_IPROC_GMAC_RWREG_OPT -+ tristate "BCM GMAC R/W_REG OPTIMIZATION support" -+ depends on HND -+ default n -+ help -+ Remove unnecessary "DSB" intructions of R/W_REG Macro. -+ If unsure, say N. -+config BCM_IPROC_GMAC_SG -+ bool "BCM GMAC Scatter Gather support" -+ default n -+ depends on HND -+config IPROC_SDK_MGT_PORT_HANDOFF -+ bool "GMAC SDK Management port handoff" -+ default y -+ depends on HND -+config IPROC_2STAGE_RX -+ bool "GMAC 2 stage packet RX" -+ default n -+ depends on HND -+config SERDES_ASYMMETRIC_MODE -+ bool "GMAC SDK Serdes Asymmetric Mode" -+ default n -+ depends on HND && (MACH_KT2 || MACH_HX4) -+config JUMBO_FRAME -+ bool "GMAC Jumbo Frame Support" -+ default n -+ depends on HND -+endmenu -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/hnd/Makefile b/drivers/net/ethernet/broadcom/gmac/hnd/Makefile ---- a/drivers/net/ethernet/broadcom/gmac/hnd/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/hnd/Makefile 2017-11-09 17:53:43.881317000 +0800 -@@ -0,0 +1,121 @@ -+# -+# Makefile for Broadcom Home Networking Division (HND) shared driver code -+# -+# $Copyright Open Broadcom Corporation$ -+# -+# $Id: Makefile,v 1.5 2008-05-02 22:49:54 pmoutarl Exp $ -+# -+ -+SHARED := ../src/shared -+ -+## from linux dir ########## -+export SRCBASE_hnd := $(src)/$(SHARED)/../ -+KBUILD_CFLAGS += -I$(SRCBASE_hnd)/include -DBCMDRIVER -Dlinux -+KBUILD_AFLAGS += -I$(SRCBASE_hnd)/include -+################################# -+obj-$(CONFIG_HND) := hnd.o -+ -+EXTRA_CFLAGS += -DBCMDBG_ERR -DBCMDMA32 -+ -+ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) -+EXTRA_CFLAGS += -DBCMDMASGLISTOSL -+endif -+ -+HND_OBJS += $(src)/$(SHARED)/nvramstubs.o -+hnd-objs += $(SHARED)/nvramstubs.o -+ -+HND_OBJS += $(src)/$(SHARED)/hnddma.o -+hnd-objs += $(SHARED)/hnddma.o -+ -+HND_OBJS += $(src)/$(SHARED)/bcmutils.o -+hnd-objs += $(SHARED)/bcmutils.o -+ -+HND_OBJS += $(src)/$(SHARED)/linux_osl.o -+hnd-objs += $(SHARED)/linux_osl.o -+ -+HND_OBJS += $(src)/$(SHARED)/siutils.o -+hnd-objs += $(SHARED)/siutils.o -+ -+HND_OBJS += $(src)/$(SHARED)/aiutils.o -+hnd-objs += $(SHARED)/aiutils.o -+ -+ -+ifeq ($(CONFIG_MACH_HX4),y) -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o -+hnd-objs += $(SHARED)/bcmiproc_serdes.o -+ -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o -+hnd-objs += $(SHARED)/bcmiproc_phy5461s.o -+ -+HND_OBJS += $(src)/$(SHARED)/hx4_erom.o -+hnd-objs += $(SHARED)/hx4_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_SB2),y) -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o -+hnd-objs += $(SHARED)/bcmiproc_serdes.o -+ -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o -+hnd-objs += $(SHARED)/bcmiproc_phy5461s.o -+ -+HND_OBJS += $(src)/$(SHARED)/sb2_erom.o -+hnd-objs += $(SHARED)/sb2_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_KT2),y) -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o -+hnd-objs += $(SHARED)/bcmiproc_serdes.o -+ -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o -+hnd-objs += $(SHARED)/bcmiproc_phy5461s.o -+ -+HND_OBJS += $(src)/$(SHARED)/kt2_erom.o -+hnd-objs += $(SHARED)/kt2_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_HR2),y) -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5221.o -+hnd-objs += $(SHARED)/bcmiproc_phy5221.o -+ -+HND_OBJS += $(src)/$(SHARED)/hr2_erom.o -+hnd-objs += $(SHARED)/hr2_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_GH),y) -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5481.o -+hnd-objs += $(SHARED)/bcmiproc_phy5481.o -+ -+HND_OBJS += $(src)/$(SHARED)/gh_erom.o -+hnd-objs += $(SHARED)/gh_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_HR3),y) -+ifeq ($(CONFIG_MACH_WH2),y) -+HND_OBJS += $(src)/$(SHARED)/sgmiiplus2_serdes.o -+hnd-objs += $(SHARED)/sgmiiplus2_serdes.o -+ -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_egphy28.o -+hnd-objs += $(SHARED)/bcmiproc_egphy28.o -+else -+HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5481.o -+hnd-objs += $(SHARED)/bcmiproc_phy5481.o -+endif -+HND_OBJS += $(src)/$(SHARED)/hr3_erom.o -+hnd-objs += $(SHARED)/hr3_erom.o -+endif -+ -+ifeq ($(CONFIG_MACH_GH2),y) -+HND_OBJS += $(src)/$(SHARED)/sgmiiplus2_serdes.o -+hnd-objs += $(SHARED)/sgmiiplus2_serdes.o -+ -+HND_OBJS += $(src)/$(SHARED)/phy542xx.o -+hnd-objs += $(SHARED)/phy542xx.o -+ -+HND_OBJS += $(src)/$(SHARED)/gh2_erom.o -+hnd-objs += $(SHARED)/gh2_erom.o -+endif -+ -+#$(src)/shared_ksyms.c: $(src)/shared_ksyms.sh $(HND_OBJS) -+# sh -e $< $(HND_OBJS) > $@ -+ -+hnd-objs += shared_ksyms.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.c b/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.c ---- a/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.c 2017-11-09 17:53:43.882312000 +0800 -@@ -0,0 +1,43 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+#include -+#include -+#include -+#include -+EXPORT_SYMBOL(bcm_atoi); -+EXPORT_SYMBOL(bcm_binit); -+EXPORT_SYMBOL(bcm_bprintf); -+EXPORT_SYMBOL(bcm_ether_atoe); -+EXPORT_SYMBOL(bcm_ether_ntoa); -+EXPORT_SYMBOL(bcm_strtoul); -+EXPORT_SYMBOL(getgpiopin); -+EXPORT_SYMBOL(getintvar); -+EXPORT_SYMBOL(getvar); -+EXPORT_SYMBOL(nvram_env_gmac_name); -+EXPORT_SYMBOL(nvram_get); -+EXPORT_SYMBOL(osl_delay); -+EXPORT_SYMBOL(osl_detach); -+EXPORT_SYMBOL(osl_dma_map); -+EXPORT_SYMBOL(osl_malloc); -+EXPORT_SYMBOL(osl_malloced); -+EXPORT_SYMBOL(osl_mfree); -+EXPORT_SYMBOL(osl_pkt_frmnative); -+EXPORT_SYMBOL(osl_pkt_tonative); -+EXPORT_SYMBOL(osl_pktfree); -+EXPORT_SYMBOL(pktsetprio); -+EXPORT_SYMBOL(si_attach); -+EXPORT_SYMBOL(si_setcore); -+EXPORT_SYMBOL(si_core_cflags); -+EXPORT_SYMBOL(si_core_disable); -+EXPORT_SYMBOL(si_core_reset); -+EXPORT_SYMBOL(si_core_sflags); -+EXPORT_SYMBOL(si_coreid); -+EXPORT_SYMBOL(si_coreidx); -+EXPORT_SYMBOL(si_corerev); -+EXPORT_SYMBOL(si_coreunit); -+EXPORT_SYMBOL(si_detach); -+EXPORT_SYMBOL(si_gpioout); -+EXPORT_SYMBOL(si_gpioouten); -+EXPORT_SYMBOL(si_iscoreup); -+EXPORT_SYMBOL(si_setcoreidx); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.sh b/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.sh ---- a/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.sh 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/hnd/shared_ksyms.sh 2017-11-09 17:53:43.883313000 +0800 -@@ -0,0 +1,30 @@ -+#!/bin/sh -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+# $Id: shared_ksyms.sh,v 1.2 2008-12-05 20:10:41 $ -+# -+ -+cat < -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -+#include -+#endif -+EOF -+ -+for file in $* ; do -+ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [BDRT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' -+done -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_cfg.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_cfg.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_cfg.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_cfg.h 2017-11-09 17:53:43.886293000 +0800 -@@ -0,0 +1,12 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * BCM ET driver config options -+ * -+ * $Id: et_cfg.h,v 1.1.4.1 2010-08-05 19:17:00 jaredh Exp $ -+ */ -+ -+#if defined(__NetBSD__) || defined(__FreeBSD__) -+#include -+#include -+#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_dbg.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_dbg.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_dbg.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_dbg.h 2017-11-09 17:53:43.896296000 +0800 -@@ -0,0 +1,47 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Minimal debug/trace/assert driver definitions for -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Device Driver. -+ * -+ * $Id: et_dbg.h 286404 2011-09-27 19:29:08Z nisar $ -+ */ -+ -+#ifndef _et_dbg_ -+#define _et_dbg_ -+ -+#ifdef BCMDBG -+struct ether_header; -+extern void etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit); -+extern void etc_prhex(char *msg, uchar *buf, uint nbytes, int unit); -+/* -+ * et_msg_level is a bitvector: -+ * 0 errors -+ * 1 function-level tracing -+ * 2 one-line frame tx/rx summary -+ * 3 complex frame tx/rx in hex -+ */ -+#define ET_ERROR(args) if (!(et_msg_level & 1)) ; else printf args -+#define ET_TRACE(args) if (!(et_msg_level & 2)) ; else printf args -+#define ET_PRHDR(msg, eh, len, unit) if (!(et_msg_level & 4)) ; else etc_prhdr(msg, eh, len, unit) -+#define ET_PRPKT(msg, buf, len, unit) if (!(et_msg_level & 8)) ; else etc_prhex(msg, buf, len, unit) -+#else /* BCMDBG */ -+#define ET_ERROR(args) -+#define ET_TRACE(args) -+#define ET_PRHDR(msg, eh, len, unit) -+#define ET_PRPKT(msg, buf, len, unit) -+#endif /* BCMDBG */ -+ -+extern uint32 et_msg_level; -+ -+#define ET_LOG(fmt, a1, a2) -+ -+/* include port-specific tunables */ -+#if defined(linux) -+#include -+#else -+#error -+#endif -+ -+#endif /* _et_dbg_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_export.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_export.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_export.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_export.h 2017-11-09 17:53:43.897291000 +0800 -@@ -0,0 +1,28 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Required functions exported by the port-specific (os-dependent) driver -+ * to common (os-independent) driver code. -+ * -+ * $Id: et_export.h 322208 2012-03-20 01:53:23Z rnuti $ -+ */ -+ -+#ifndef _et_export_h_ -+#define _et_export_h_ -+ -+/* misc callbacks */ -+extern void et_init(void *et, uint options); -+extern void et_reset(void *et); -+extern void et_link_up(void *et); -+extern void et_link_down(void *et); -+extern bool et_is_link_up(void *et); -+extern int et_up(void *et); -+extern int et_down(void *et, int reset); -+extern void et_dump(void *et, struct bcmstrbuf *b); -+extern void et_intrson(void *et); -+ -+/* for BCM5222 dual-phy shared mdio contortion */ -+extern void *et_phyfind(void *et, uint coreunit); -+extern uint16 et_phyrd(void *et, uint phyaddr, uint reg); -+extern void et_phywr(void *et, uint reg, uint phyaddr, uint16 val); -+#endif /* _et_export_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.c b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.c ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.c 2017-11-09 17:53:43.899291000 +0800 -@@ -0,0 +1,2603 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Linux device driver for -+ * Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller -+ * -+ * $Id: et_linux.c 327582 2012-04-14 05:02:37Z kenlo $ -+ */ -+ -+#include -+#define __UNDEF_NO_VERSION__ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef SIOCETHTOOL -+#include -+#endif /* SIOCETHTOOL */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_OF -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* to be cleaned and fixed */ -+/* to be cleaned Makefile */ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+#include -+ -+#define SKB_PREFETCH_LEN (128) -+/* 30 rxhdr + 34 mac & ip */ -+#define SKB_DATA_PREFETCH_LEN (96) -+#endif /* CONFIG_BCM_IPROC_GMAC_PREFETCH */ -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) -+#error Linux version must be newer than 2.4.5 -+#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) */ -+ -+#define MIN_PACKET_SIZE 70 /* for gmac2 (&GMAC3?) */ -+/* if packet is less than 64 bytes, it will not tx */ -+/* if packet is less than 66 bytes, CRC is not generated) */ -+/* this length is after brm tag is stripped off */ -+ -+#define DATAHIWAT 1000 /* data msg txq hiwat mark */ -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) -+#define HAVE_NET_DEVICE_OPS 1 -+#define HAVE_NETDEV_PRIV 1 -+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) */ -+ -+#ifndef HAVE_NETDEV_PRIV -+#define HAVE_NETDEV_PRIV -+#define netdev_priv(dev) ((dev)->priv) -+#define ET_INFO(dev) (et_info_t *)((dev)->priv) -+#else -+#define ET_INFO(dev) netdev_priv(dev) -+#endif /* HAVE_NETDEV_PRIV */ -+ -+#ifdef GMAC_ALL_PASSIVE -+#define ET_LIMIT_TXQ -+#define ET_ALL_PASSIVE_ENAB(et) (!(et)->all_dispatch_mode) -+ -+/* passive mode: 1: enable, 0: disable */ -+static int passivemode = 0; -+module_param(passivemode, int, 0); -+#else /* GMAC_ALL_PASSIVE */ -+#define ET_ALL_PASSIVE_ENAB(et) 0 -+#endif /* GMAC_ALL_PASSIVE */ -+ -+#ifdef ET_LIMIT_TXQ -+#define ET_TXQ_THRESH 0 -+static int et_txq_thresh = ET_TXQ_THRESH; -+module_param(et_txq_thresh, int, 0); -+#endif /* ET_LIMIT_TXQ */ -+ -+ -+/* In 2.6.20 kernels work functions get passed a pointer to the -+ * struct work, so things will continue to work as long as the work -+ * structure is the first component of the task structure. -+ */ -+typedef struct et_task { -+ struct work_struct work; -+ void *context; -+} et_task_t; -+ -+typedef struct et_info { -+ etc_info_t *etc; /* pointer to common os-independent data */ -+ struct net_device *dev; /* backpoint to device */ -+ struct pci_dev *pdev; /* backpoint to pci_dev */ -+ void *osh; /* pointer to os handle */ -+ struct semaphore sem; /* use semaphore to allow sleep */ -+ spinlock_t lock; /* per-device perimeter lock */ -+ spinlock_t txq_lock; /* lock for txq protection */ -+ spinlock_t tx_lock; /* lock for tx protection */ -+ spinlock_t isr_lock; /* lock for irq reentrancy protection */ -+ struct sk_buff_head txq[NUMTXQ];/* send queue */ -+ void *regsva; /* opaque chip registers virtual address */ -+ struct timer_list timer; /* one second watchdog timer */ -+ bool set; /* indicate the timer is set or not */ -+ struct net_device_stats stats; /* stat counter reporting structure */ -+ int events; /* bit channel between isr and dpc */ -+ struct et_info *next; /* pointer to next et_info_t in chain */ -+#ifdef GMAC_NAPI2_POLL -+ struct napi_struct napi_poll; -+#endif /* GMAC_NAPI2_POLL */ -+#ifndef GMAC_NAPI_POLL -+ struct tasklet_struct tasklet;/* dpc tasklet */ -+#endif /* GMAC_NAPI_POLL */ -+#ifdef GMAC_ALL_PASSIVE -+ et_task_t dpc_task; /* work queue for rx dpc */ -+ et_task_t txq_task; /* work queue for tx frames */ -+ bool all_dispatch_mode; /* dispatch mode: tasklets or passive */ -+#endif /* GMAC_ALL_PASSIVE */ -+ bool resched; /* dpc was rescheduled */ -+#ifdef CONFIG_IPROC_2STAGE_RX -+ bool rxinisr; -+#endif /* CONFIG_IPROC_2STAGE_RX */ -+} et_info_t; -+ -+#define ET_LOCK(et) \ -+do { \ -+ if (ET_ALL_PASSIVE_ENAB(et)) \ -+ down(&(et)->sem); \ -+ else \ -+ spin_lock_bh(&(et)->lock); \ -+} while (0) -+ -+#define ET_UNLOCK(et) \ -+do { \ -+ if (ET_ALL_PASSIVE_ENAB(et)) \ -+ up(&(et)->sem); \ -+ else \ -+ spin_unlock_bh(&(et)->lock); \ -+} while (0) -+ -+#define ET_TXQ_LOCK(et) spin_lock_bh(&(et)->txq_lock) -+#define ET_TXQ_UNLOCK(et) spin_unlock_bh(&(et)->txq_lock) -+#define ET_TX_LOCK(et) spin_lock_bh(&(et)->tx_lock) -+#define ET_TX_UNLOCK(et) spin_unlock_bh(&(et)->tx_lock) -+#define INT_LOCK(et, flags) spin_lock_irqsave(&(et)->isr_lock, flags) -+#define INT_UNLOCK(et, flags) spin_unlock_irqrestore(&(et)->isr_lock, flags) -+ -+#ifdef GMAC_RATE_LIMITING -+static int et_rx_rate_limit = 0; -+extern void etc_check_rate_limiting(etc_info_t *etc, void *pch); -+#endif /* GMAC_RATE_LIMITING */ -+ -+#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+extern int gmac_has_mdio_access(void); -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ -+ -+static int et_found = 0; -+static et_info_t *et_list = NULL; -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) -+#define init_MUTEX(x) sema_init(x,1) -+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) */ -+ -+/* linux 2.4 doesn't have in_atomic */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -+#define in_atomic() 0 -+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) */ -+ -+/* Prototypes called by etc.c */ -+#ifdef CONFIG_BCM_GRO_ENABLE -+void et_flush(void *dev_id); -+#endif /* CONFIG_BCM_GRO_ENABLE */ -+void et_init(et_info_t *et, uint options); -+void et_reset(et_info_t *et); -+void et_up(et_info_t *et); -+void et_down(et_info_t *et, int reset); -+void et_intrson(et_info_t *et); -+void et_dump(et_info_t *et, struct bcmstrbuf *b); -+void et_link_up(et_info_t *et); -+void et_link_down(et_info_t *et); -+bool et_is_link_up(et_info_t *et); -+ -+/* Local prototypes */ -+static void et_free(et_info_t *et); -+static int et_open(struct net_device *dev); -+static int et_close(struct net_device *dev); -+static int et_start(struct sk_buff *skb, struct net_device *dev); -+static int et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -+static struct net_device_stats *et_get_stats(struct net_device *dev); -+static int et_set_mac_address(struct net_device *dev, void *addr); -+static void et_set_multicast_list(struct net_device *dev); -+ -+static void et_sendnext(et_info_t *et); -+static void _et_watchdog(struct net_device *data); -+static void et_watchdog(ulong data); -+#ifdef GMAC_ALL_PASSIVE -+static void et_watchdog_task(et_task_t *task); -+static void et_dpc_work(struct et_task *task); -+static int et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context); -+static void et_txq_work(struct et_task *task); -+#endif /* GMAC_ALL_PASSIVE */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -+static irqreturn_t et_isr(int irq, void *dev_id); -+#else -+static irqreturn_t et_isr(int irq, void *dev_id, struct pt_regs *ptregs); -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) */ -+static int et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota); -+#ifdef GMAC_NAPI2_POLL -+static int et_poll(struct napi_struct *napi, int budget); -+#elif defined(GMAC_NAPI_POLL) -+static int et_poll(struct net_device *dev, int *budget); -+#else /* ! GMAC_NAPI_POLL */ -+static void et_dpc(ulong data); -+#endif /* GMAC_NAPI_POLL */ -+static void et_error(et_info_t *et, struct sk_buff *skb, void *rxh); -+static void et_sendup(et_info_t *et, struct sk_buff *skb); -+static void et_dumpet(et_info_t *et, struct bcmstrbuf *b); -+static int et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd); -+static int et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd); -+static void et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info); -+ -+static int eth_mac_proc_create(struct net_device *dev); -+#ifndef CONFIG_OF -+static void eth_mac_proc_remove(void); -+#else -+static void eth_mac_proc_remove(struct net_device *dev); -+#endif -+static int iproc_gmac_drv_probe(struct platform_device*); -+static int __exit iproc_gmac_drv_remove(struct platform_device*); -+#ifdef CONFIG_PM -+static int iproc_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state); -+static int iproc_gmac_drv_resume(struct platform_device *pdev); -+#else /* CONFIG_PM */ -+#define iproc_gmac_drv_suspend NULL -+#define iproc_gmac_drv_resume NULL -+#endif /* CONFIG_PM */ -+ -+#define DISABLE_FA_BYPASS 0 -+#define ENABLE_FA_BYPASS 1 -+ -+#if 0 -+static unsigned int gBypass = DISABLE_FA_BYPASS; -+#endif -+ -+#ifdef BCMDBG -+static uint32 msglevel = 0xdeadbeef; -+module_param(msglevel, uint, 0644); -+#endif /* BCMDBG */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) -+static const struct ethtool_ops et_ethtool_ops = { -+ .get_settings = et_get_settings, -+ .set_settings = et_set_settings, -+ .get_drvinfo = et_get_driver_info, -+}; -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */ -+ -+#ifdef HAVE_NET_DEVICE_OPS -+static const struct net_device_ops et_netdev_ops = { -+ .ndo_open = et_open, -+ .ndo_stop = et_close, -+ .ndo_start_xmit = et_start, -+ .ndo_get_stats = et_get_stats, -+ .ndo_set_mac_address = et_set_mac_address, -+ .ndo_set_rx_mode = et_set_multicast_list, -+ .ndo_do_ioctl = et_ioctl, -+}; -+#endif /*HAVE_NET_DEVICE_OPS*/ -+ -+#ifndef CONFIG_OF -+static struct platform_driver gmac_pdrv[IPROC_MAX_GMAC_CORES] = { -+ { -+ .probe = iproc_gmac_drv_probe, -+ .remove = __exit_p(iproc_gmac_drv_remove), -+ .suspend = iproc_gmac_drv_suspend, -+ .resume = iproc_gmac_drv_resume, -+ .driver = { -+ .name = "bcm-gmac0", -+ }, -+ }, -+ { -+ .probe = iproc_gmac_drv_probe, -+ .remove = __exit_p(iproc_gmac_drv_remove), -+ .suspend = iproc_gmac_drv_suspend, -+ .resume = iproc_gmac_drv_resume, -+ .driver = { -+ .name = "bcm-gmac1", -+ }, -+ }, -+ { -+ .probe = iproc_gmac_drv_probe, -+ .remove = __exit_p(iproc_gmac_drv_remove), -+ .suspend = iproc_gmac_drv_suspend, -+ .resume = iproc_gmac_drv_resume, -+ .driver = { -+ .name = "bcm-gmac2", -+ }, -+ }, -+ { -+ .probe = iproc_gmac_drv_probe, -+ .remove = __exit_p(iproc_gmac_drv_remove), -+ .suspend = iproc_gmac_drv_suspend, -+ .resume = iproc_gmac_drv_resume, -+ .driver = { -+ .name = "bcm-gmac3", -+ }, -+ } -+}; -+#endif -+ -+/*int gmac_pdev_loaded[IPROC_NUM_GMACS];*/ -+ -+/***************************************************************************** -+*****************************************************************************/ -+static bool __maybe_unused -+et_ctf_pipeline_loopback(et_info_t *et) -+{ -+ if (et->etc->unit == 3) { -+ return true; -+ } else { -+ return false; -+ } -+} -+ -+#ifdef BCMDMASGLISTOSL -+static int -+et_bcmtag_len(et_info_t *et) -+{ -+ return (et_ctf_pipeline_loopback(et)) ? 8 : 0; -+} -+#endif /* BCMDMASGLISTOSL */ -+ -+static void -+et_free(et_info_t *et) -+{ -+ et_info_t **prev; -+ osl_t *osh; -+ -+ ET_TRACE(("et: et_free\n")); -+ -+ if (et == NULL) { -+ return; -+ } -+ -+ if (et->dev && et->dev->irq) { -+ free_irq(et->dev->irq, et); -+ } -+ -+#ifdef GMAC_NAPI2_POLL -+ napi_disable(&et->napi_poll); -+ netif_napi_del(&et->napi_poll); -+#endif /* GMAC_NAPI2_POLL */ -+ -+ if (et->dev) { -+ unregister_netdev(et->dev); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+ free_netdev(et->dev); -+#else -+ MFREE(et->osh, et->dev, sizeof(struct net_device)); -+#endif -+ et->dev = NULL; -+ } -+ -+ /* free common resources */ -+ if (et->etc) { -+ etc_detach(et->etc); -+ et->etc = NULL; -+ } -+ -+ /* unregister_netdev() calls get_stats() which may read chip registers -+ * so we cannot unmap the chip registers until after calling unregister_netdev() . -+ */ -+ if (et->regsva) { -+ iounmap((void *)et->regsva); -+ et->regsva = NULL; -+ } -+ -+ /* remove us from the global linked list */ -+ for (prev = &et_list; *prev; prev = &(*prev)->next) { -+ if (*prev == et) { -+ *prev = et->next; -+ break; -+ } -+ } -+ -+ osh = et->osh; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) -+ free_netdev(et->dev); -+ et->dev = NULL; -+#else -+ MFREE(et->osh, et, sizeof(et_info_t)); -+#endif -+ -+ if (MALLOCED(osh)) { -+ ET_ERROR(("Memory leak of bytes %d\n", MALLOCED(osh))); -+ } -+ ASSERT(MALLOCED(osh) == 0); -+ -+ osl_detach(osh); -+} -+ -+static int -+et_open(struct net_device *dev) -+{ -+ et_info_t *et = ET_INFO(dev); -+ -+ ET_TRACE(("et%d: et_open\n", et->etc->unit)); -+ -+ et->etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; -+ et->etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: et->etc->promisc; -+#ifdef GMAC_RATE_LIMITING -+ et->etc->rl_enabled = et_rx_rate_limit; -+#endif /* GMAC_RATE_LIMITING */ -+ -+ ET_LOCK(et); -+ et_up(et); -+ ET_UNLOCK(et); -+ -+ OLD_MOD_INC_USE_COUNT; -+ -+ return (0); -+} -+ -+static int -+et_close(struct net_device *dev) -+{ -+ et_info_t *et = ET_INFO(dev); -+ -+ ET_TRACE(("et%d: et_close\n", et->etc->unit)); -+ -+ et->etc->promisc = FALSE; -+ et->etc->allmulti = FALSE; -+ -+ ET_LOCK(et); -+ et_down(et, 1); -+ ET_UNLOCK(et); -+ -+ OLD_MOD_DEC_USE_COUNT; -+ -+ return (0); -+} -+ -+#if defined(BCMDMASGLISTOSL) -+/* -+ * Driver level checksum offload. This is being done so that we can advertise -+ * checksum offload support to Linux. -+ */ -+static void BCMFASTPATH_HOST -+et_cso(et_info_t *et, struct sk_buff *skb) -+{ -+ struct ethervlan_header *evh; -+ uint8 *th = skb_transport_header(skb); -+ uint16 thoff, eth_type, *check; -+ uint8 prot; -+ -+ ASSERT(!PKTISCTF(et->osh, skb)); -+ -+ evh = (struct ethervlan_header *)PKTDATA(et->osh, skb); -+ eth_type = ((evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) ? -+ evh->ether_type : evh->vlan_type); -+ -+ /* tcp/udp checksum calculation */ -+ thoff = (th - skb->data); -+ if (eth_type == HTON16(ETHER_TYPE_IP)) { -+ struct iphdr *ih = ip_hdr(skb); -+ prot = ih->protocol; -+ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); -+ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? -+ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); -+ *check = 0; -+ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); -+ *check = csum_tcpudp_magic(ih->saddr, ih->daddr, -+ skb->len - thoff, prot, skb->csum); -+ } else if (eth_type == HTON16(ETHER_TYPE_IPV6)) { -+ struct ipv6hdr *ih = ipv6_hdr(skb); -+ prot = IPV6_PROT(ih); -+ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); -+ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? -+ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); -+ *check = 0; -+ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); -+ *check = csum_ipv6_magic(&ih->saddr, &ih->daddr, -+ skb->len - thoff, prot, skb->csum); -+ } else { -+ return; -+ } -+ -+ if ((*check == 0) && (prot == IP_PROT_UDP)) { -+ *check = CSUM_MANGLED_0; -+ } -+} -+#endif /* defined(BCMDMASGLISTOSL) */ -+ -+/* -+ * Yeah, queueing the packets on a tx queue instead of throwing them -+ * directly into the descriptor ring in the case of dma is kinda lame, -+ * but this results in a unified transmit path for both dma and pio -+ * and localizes/simplifies the netif_*_queue semantics, too. -+ */ -+static int BCMFASTPATH -+et_start(struct sk_buff *skb, struct net_device *dev) -+{ -+ et_info_t *et = ET_INFO(dev); -+ uint32 q = 0; -+#ifdef BCMDMASGLISTOSL -+ bool sw_cksum = true; -+ struct iphdr *iph = NULL; -+#endif /* BCMDMASGLISTOSL */ -+#ifdef ET_LIMIT_TXQ -+ int qlen; -+#endif /* ET_LIMIT_TXQ */ -+ -+#ifdef BCMDMASGLISTOSL -+ if (!PKTSUMNEEDED(skb)) { -+ sw_cksum = false; -+ } -+ -+ /* can only update checksum once. */ -+ /* if checksum is updated later, don't do it here */ -+ iph = (struct iphdr *)skb->network_header; -+ if (((skb->len + et_bcmtag_len(et)) < MIN_PACKET_SIZE) && -+ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { -+ sw_cksum = false; -+ } -+ -+ if (sw_cksum) { -+ et_cso(et, skb); -+ } -+#endif /* BCMDMASGLISTOSL */ -+ -+ if (skb_is_nonlinear(skb)) { -+ et->etc->txsgpkt++; -+ } -+ -+ if (skb->len > et->etc->txmaxlen) { -+ et->etc->txmaxlen = skb->len; -+ } -+ -+ ET_TRACE(("et%d: et_start: len %d\n", et->etc->unit, skb->len)); -+ ET_LOG("et%d: et_start: len %d", et->etc->unit, skb->len); -+ -+ et->etc->txfrm++; -+#ifdef ET_LIMIT_TXQ -+#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_TXQ_LOCK(et); -+#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ qlen = skb_queue_len(&et->txq[q]); -+#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_TXQ_UNLOCK(et); -+#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ if (qlen > et->etc->txqlen) { -+ et->etc->txqlen = qlen; -+ } -+ -+ if (et_txq_thresh && (qlen >= et_txq_thresh)) { -+ //PKTCFREE(et->osh, skb, TRUE); -+ //return 0; -+ et->etc->txfrmdropped++; -+ /* schedule work */ -+#ifdef GMAC_ALL_PASSIVE -+ if (ET_ALL_PASSIVE_ENAB(et)) { -+#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 -+ schedule_work_on(1, &et->txq_task.work); -+#else -+ schedule_work(&et->txq_task.work); -+#endif -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+ return NETDEV_TX_BUSY; -+ } -+#endif /* ET_LIMIT_TXQ */ -+ -+ /* put it on the tx queue and call sendnext */ -+ ET_TXQ_LOCK(et); -+ __skb_queue_tail(&et->txq[q], skb); -+ et->etc->txq_state |= (1 << q); -+ ET_TXQ_UNLOCK(et); -+ -+ if (!ET_ALL_PASSIVE_ENAB(et)) { -+ ET_LOCK(et); -+ et_sendnext(et); -+ ET_UNLOCK(et); -+ } -+#ifdef GMAC_ALL_PASSIVE -+ else { -+#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 -+ schedule_work_on(1, &et->txq_task.work); -+#else -+ schedule_work(&et->txq_task.work); -+#endif /* CONFIG_BCM_IPROC_GMAC_TXONCPU1 */ -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+ -+ ET_LOG("et%d: et_start ret\n", et->etc->unit, 0); -+ -+ return (0); -+} -+ -+static void BCMFASTPATH -+et_sendnext(et_info_t *et) -+{ -+ etc_info_t *etc; -+ struct sk_buff *skb; -+ void *p, *n; -+ uint32 priq = TX_Q0; -+#ifdef DMA -+ uint32 txavail; -+#endif -+#ifdef DBG_PRINT_PKT -+ int tagoff, idx; -+#endif /* DBG_PRINT_PKT */ -+ -+ etc = et->etc; -+ -+ ET_TRACE(("et%d: et_sendnext\n", etc->unit)); -+ ET_LOG("et%d: et_sendnext", etc->unit, 0); -+ -+ /* dequeue packets from highest priority queue and send */ -+ while (1) { -+ ET_TXQ_LOCK(et); -+ -+ if (etc->txq_state == 0) -+ break; -+ -+ priq = etc_priq(etc->txq_state); -+ -+ ET_TRACE(("et%d: txq_state %x priq %d txavail %d\n", -+ etc->unit, etc->txq_state, priq, -+ *(uint *)etc->txavail[priq])); -+ -+ if ((skb = skb_peek(&et->txq[priq])) == NULL) { -+ etc->txq_state &= ~(1 << priq); -+ ET_TXQ_UNLOCK(et); -+ continue; -+ } -+ -+#ifdef DMA -+ /* current highest priority dma queue is full */ -+ txavail = *(uint *)(etc->txavail[priq]); -+ if ((PKTISCHAINED(skb) && (txavail < PKTCCNT(skb))) || (txavail == 0)) -+#else /* DMA */ -+ if (etc->pioactive != NULL) -+#endif /* DMA */ -+ { -+ etc->txdmafull++; -+ break; -+ } -+ -+ skb = __skb_dequeue(&et->txq[priq]); -+ -+ ET_TXQ_UNLOCK(et); -+ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); -+ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); -+ -+#ifdef DBG_PRINT_PKT -+ tagoff = 16; -+ printf("et%d: txpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, -+ skb->data[tagoff], skb->data[tagoff+1], skb->data[tagoff+2], skb->data[tagoff+3]); -+ -+ printk("et%d: %s len(0x%x) txpkt:", etc->unit, __FUNCTION__, skb->len); -+ for (idx = 0; idx < skb->len; idx++) { -+ if ((idx % 16) == 0) { -+ printk("\n"); -+ } -+ printk("%02x ", skb->data[idx]); -+ } -+ printk("\n"); -+#endif /* DBG_PRINT_PKT */ -+ -+ /* convert the packet. */ -+ p = PKTFRMNATIVE(etc->osh, skb); -+ ASSERT(p != NULL); -+ -+ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", -+ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); -+ -+ ET_TX_LOCK(et); -+ FOREACH_CHAINED_PKT(p, n) { -+ /* replicate vlan header contents from curr frame */ -+ if (n != NULL) { -+ uint8 *n_evh; -+ n_evh = PKTPUSH(et->osh, n, VLAN_TAG_LEN); -+ *(struct ethervlan_header *)n_evh = -+ *(struct ethervlan_header *)PKTDATA(et->osh, p); -+ } -+ (*etc->chops->tx)(etc->ch, p); -+#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_LOCK(et); -+#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ etc->txframe++; -+ etc->txbyte += PKTLEN(et->osh, p); -+#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_UNLOCK(et); -+#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ } -+ ET_TX_UNLOCK(et); -+ } -+ -+ /* no flow control when qos is enabled */ -+ if (!et->etc->qos) { -+ /* stop the queue whenever txq fills */ -+ if ((skb_queue_len(&et->txq[TX_Q0]) > DATAHIWAT) && !netif_queue_stopped(et->dev)) { -+ et->etc->txqstop++; -+ netif_stop_queue(et->dev); -+ } else if (netif_queue_stopped(et->dev) && -+ (skb_queue_len(&et->txq[TX_Q0]) < (DATAHIWAT/2))) { -+ netif_wake_queue(et->dev); -+ } -+ } else { -+ /* drop the frame if corresponding prec txq len exceeds hiwat -+ * when qos is enabled. -+ */ -+ if ((priq != TC_NONE) && (skb_queue_len(&et->txq[priq]) > DATAHIWAT)) { -+ skb = __skb_dequeue(&et->txq[priq]); -+ PKTCFREE(et->osh, skb, TRUE); -+ ET_ERROR(("et%d: %s: txqlen %d\n", et->etc->unit, -+ __FUNCTION__, skb_queue_len(&et->txq[priq]))); -+ } -+ } -+ -+ ET_TXQ_UNLOCK(et); -+} -+ -+#ifdef CONFIG_BCM_GRO_ENABLE -+#ifdef CONFIG_ET_MODULE -+extern int et_flushptr_ready; -+extern void (*et_flushptr)(void *dev_id); -+#endif /* CONFIG_ET_MODULE */ -+ -+void -+et_flush(void *dev_id) -+{ -+ et_info_t *et; -+ struct chops *chops; -+ void *ch; -+ osl_t *osh; -+ -+ et = (et_info_t *)dev_id; -+ chops = et->etc->chops; -+ ch = et->etc->ch; -+ osh = et->etc->osh; -+ -+ /* guard against shared interrupts */ -+ if (!et->etc->up) { -+ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); -+ return; -+ } -+ if (!et->napi_poll.gro_list) { -+ return; -+ } -+ -+ /* disable interrupts */ -+ (*chops->intrsoff)(ch); -+ -+ et->resched = TRUE; -+ -+ napi_gro_flush(&et->napi_poll); -+ -+ /* enable interrupts now */ -+ (*chops->intrson)(ch); -+} -+#endif /* CONFIG_BCM_GRO_ENABLE */ -+ -+void -+et_init(et_info_t *et, uint options) -+{ -+ ET_TRACE(("et%d: et_init\n", et->etc->unit)); -+ ET_LOG("et%d: et_init", et->etc->unit, 0); -+ -+ etc_init(et->etc, options); -+ -+#ifdef CONFIG_BCM_GRO_ENABLE -+#ifdef CONFIG_ET_MODULE -+ et_flushptr = &et_flush; -+ et_flushptr_ready = 1; -+#endif /* CONFIG_ET_MODULE */ -+#endif /* CONFIG_BCM_GRO_ENABLE */ -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) -+ netif_carrier_off(et->dev); -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) */ -+} -+ -+ -+void -+et_reset(et_info_t *et) -+{ -+ ET_TRACE(("et%d: et_reset\n", et->etc->unit)); -+ -+ etc_reset(et->etc); -+ -+ /* zap any pending dpc interrupt bits */ -+ et->events = 0; -+ -+ /* dpc will not be rescheduled */ -+ et->resched = 0; -+} -+ -+void -+et_up(et_info_t *et) -+{ -+ etc_info_t *etc; -+ -+ etc = et->etc; -+ -+ if (etc->up) { -+ return; -+ } -+ -+ ET_TRACE(("et%d: et_up\n", etc->unit)); -+ -+ etc_up(etc); -+ -+#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ if (et->set) { -+ /* This will happen if running watchdog to monitor mdio bus */ -+ /* and port not up */ -+ del_timer(&et->timer); -+ et->set = FALSE; -+ } -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ -+ -+ /* schedule one second watchdog timer */ -+ et->timer.expires = jiffies + HZ; -+ add_timer(&et->timer); -+ et->set=TRUE; -+ -+ netif_start_queue(et->dev); -+} -+ -+void -+et_down(et_info_t *et, int reset) -+{ -+ etc_info_t *etc; -+ struct sk_buff *skb; -+ int32 i; -+ bool stoptmr = TRUE; -+ -+ etc = et->etc; -+ -+ ET_TRACE(("et%d: et_down\n", etc->unit)); -+ -+ netif_down(et->dev); -+ netif_stop_queue(et->dev); -+ -+#ifdef CONFIG_IPROC_SDK_MGT_PORT_HANDOFF -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ if (gmac_has_mdio_access()) { -+ /* we have mdio bus don't stop timer so we can continue to monitor */ -+ stoptmr = FALSE; -+ } -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* CONFIG_IPROC_SDK_MGT_PORT_HANDOFF */ -+ -+ if ( stoptmr ) { -+ /* stop watchdog timer */ -+ del_timer(&et->timer); -+ et->set = FALSE; -+ } -+ -+#ifdef GMAC_RATE_LIMITING -+ /* stop ratelimiting timer */ -+ del_timer(&et->etc->rl_timer); -+ et->etc->rl_set = FALSE; -+#endif /* GMAC_RATE_LIMITING */ -+ -+ etc_down(etc, reset); -+ -+ /* flush the txq(s) */ -+ for (i = 0; i < NUMTXQ; i++) { -+ while ((skb = skb_dequeue(&et->txq[i]))) { -+ PKTFREE(etc->osh, skb, TRUE); -+ } -+ } -+ -+#if !defined(GMAC_NAPI_POLL) && !defined(GMAC_NAPI2_POLL) -+ /* kill dpc */ -+ ET_UNLOCK(et); -+ tasklet_kill(&et->tasklet); -+ ET_LOCK(et); -+#endif /* GMAC_NAPI_POLL */ -+} -+ -+/* -+ * These are interrupt on/off entry points. Disable interrupts -+ * during interrupt state transition. -+ */ -+void -+et_intrson(et_info_t *et) -+{ -+ unsigned long flags; -+ INT_LOCK(et, flags); -+ (*et->etc->chops->intrson)(et->etc->ch); -+ INT_UNLOCK(et, flags); -+} -+ -+static void -+_et_watchdog(struct net_device *dev) -+{ -+ et_info_t *et; -+ -+ et = ET_INFO(dev); -+ -+ ET_LOCK(et); -+ -+ etc_watchdog(et->etc); -+ -+ if (et->set) { -+ /* reschedule one second watchdog timer */ -+ et->timer.expires = jiffies + HZ; -+ add_timer(&et->timer); -+ } -+#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ /* this in case port when up then down before we released mdio */ -+ else if (gmac_has_mdio_access()) { -+ /* interface not up but we have mdio bus */ -+ /* reschedule one second watchdog timer */ -+ et->timer.expires = jiffies + HZ; -+ add_timer(&et->timer); -+ et->set = TRUE; -+ } -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ -+ -+ ET_UNLOCK(et); -+} -+ -+#ifdef GMAC_ALL_PASSIVE -+/* Schedule a completion handler to run at safe time */ -+static int -+et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context) -+{ -+ et_task_t *task; -+ -+ ET_TRACE(("et%d: et_schedule_task\n", et->etc->unit)); -+ -+ if (!(task = MALLOC(et->osh, sizeof(et_task_t)))) { -+ ET_ERROR(("et%d: et_schedule_task: out of memory, malloced %d bytes\n", -+ et->etc->unit, MALLOCED(et->osh))); -+ return -ENOMEM; -+ } -+ -+ MY_INIT_WORK(&task->work, (work_func_t)fn); -+ task->context = context; -+ -+ if (!schedule_work(&task->work)) { -+ ET_ERROR(("et%d: schedule_work() failed\n", et->etc->unit)); -+ MFREE(et->osh, task, sizeof(et_task_t)); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void BCMFASTPATH -+et_txq_work(struct et_task *task) -+{ -+ et_info_t *et = (et_info_t *)task->context; -+ -+#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_LOCK(et); -+#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ -+ et_sendnext(et); -+ -+#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT -+ ET_UNLOCK(et); -+#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ -+ return; -+} -+ -+static void -+et_watchdog_task(et_task_t *task) -+{ -+ et_info_t *et = ET_INFO((struct net_device *)task->context); -+ -+ _et_watchdog((struct net_device *)task->context); -+ MFREE(et->osh, task, sizeof(et_task_t)); -+} -+#endif /* GMAC_ALL_PASSIVE */ -+ -+static void -+et_watchdog(ulong data) -+{ -+ struct net_device *dev = (struct net_device *)data; -+ -+#ifdef GMAC_ALL_PASSIVE -+ et_info_t *et = ET_INFO(dev); -+#endif /* GMAC_ALL_PASSIVE */ -+ -+ if (!ET_ALL_PASSIVE_ENAB(et)) { -+ _et_watchdog(dev); -+ } -+#ifdef GMAC_ALL_PASSIVE -+ else { -+ et_schedule_task(et, et_watchdog_task, dev); -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+} -+ -+/* Rate limiting */ -+#ifdef GMAC_RATE_LIMITING -+static void et_release_congestion(ulong data) -+{ -+ struct net_device *dev = (struct net_device *)data; -+ et_info_t *et = ET_INFO(dev); -+ -+ if (!et) { -+ return; -+ } -+ -+ if (et->etc->rl_stopping_broadcasts) { -+ et->etc->rl_stopping_broadcasts = 0; -+ /* Clear the number of dropped broadcast packets */ -+ et->etc->rl_dropped_bc_packets = 0; -+ } -+ if (et->etc->rl_stopping_all_packets) { -+ et->etc->rl_stopping_all_packets = 0; -+ et->etc->rl_dropped_all_packets = 0; -+ } -+} -+#endif /* GMAC_RATE_LIMITING */ -+ -+ -+ -+static int -+et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -+{ -+ et_info_t *et = ET_INFO(dev); -+ -+ ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | -+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | -+ SUPPORTED_Autoneg | SUPPORTED_TP); -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ ecmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_Pause; -+#endif -+#if defined(CONFIG_MACH_HR2) -+ ecmd->supported |= SUPPORTED_Pause; -+#endif -+ -+ ecmd->advertising = ADVERTISED_TP; -+ ecmd->advertising |= (et->etc->advertise & ADV_10HALF) ? -+ ADVERTISED_10baseT_Half : 0; -+ ecmd->advertising |= (et->etc->advertise & ADV_10FULL) ? -+ ADVERTISED_10baseT_Full : 0; -+ ecmd->advertising |= (et->etc->advertise & ADV_100HALF) ? -+ ADVERTISED_100baseT_Half : 0; -+ ecmd->advertising |= (et->etc->advertise & ADV_100FULL) ? -+ ADVERTISED_100baseT_Full : 0; -+ ecmd->advertising |= (et->etc->advertise2 & ADV_1000FULL) ? -+ ADVERTISED_1000baseT_Full : 0; -+ ecmd->advertising |= (et->etc->advertise2 & ADV_1000HALF) ? -+ ADVERTISED_1000baseT_Half : 0; -+ ecmd->advertising |= (et->etc->forcespeed == ET_AUTO) ? -+ ADVERTISED_Autoneg : 0; -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HR2)) -+ ecmd->advertising |= ADVERTISED_Pause; -+#endif -+ if (et->etc->linkstate) { -+ ecmd->speed = (et->etc->speed == 1000) ? SPEED_1000 : -+ ((et->etc->speed == 100) ? SPEED_100 : SPEED_10); -+ ecmd->duplex = (et->etc->duplex == 1) ? DUPLEX_FULL : DUPLEX_HALF; -+ } else { -+ ecmd->speed = 0; -+ ecmd->duplex = 0; -+ } -+ ecmd->port = PORT_TP; -+ ecmd->phy_address = et->etc->phyaddr; -+ ecmd->transceiver = XCVR_INTERNAL; -+ ecmd->autoneg = (et->etc->forcespeed == ET_AUTO) ? AUTONEG_ENABLE : AUTONEG_DISABLE; -+ ecmd->maxtxpkt = 0; -+ ecmd->maxrxpkt = 0; -+ -+ return 0; -+} -+ -+static int -+et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -+{ -+ int speed[2]; -+ -+ et_info_t *et = ET_INFO(dev); -+ -+ if (!capable(CAP_NET_ADMIN)) -+ return (-EPERM); -+ -+ if (ecmd->autoneg == AUTONEG_ENABLE) { -+ speed[0] = ET_AUTO; -+ speed[1] = ecmd->advertising; -+ } else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) { -+ speed[0] = ET_10HALF; -+ } else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) { -+ speed[0] = ET_10FULL; -+ } else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) { -+ speed[0] = ET_100HALF; -+ } else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) { -+ speed[0] = ET_100FULL; -+ } else if (ecmd->speed == SPEED_1000 && ecmd->duplex == DUPLEX_FULL) { -+ speed[0] = ET_1000FULL; -+ } else { -+ return (-EINVAL); -+ } -+ -+ return etc_ioctl(et->etc, ETCSPEED, speed); -+} -+ -+static void -+et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info) -+{ -+ et_info_t *et = ET_INFO(dev); -+ bzero(info, sizeof(struct ethtool_drvinfo)); -+ info->cmd = ETHTOOL_GDRVINFO; -+ sprintf(info->driver, "et%d", et->etc->unit); -+ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version)); -+ info->version[(sizeof(info->version))-1] = '\0'; -+} -+ -+#ifdef SIOCETHTOOL -+static int -+et_ethtool(et_info_t *et, struct ethtool_cmd *ecmd) -+{ -+ int ret = 0; -+ -+ ET_LOCK(et); -+ -+ switch (ecmd->cmd) { -+ case ETHTOOL_GSET: -+ ret = et_get_settings(et->dev, ecmd); -+ break; -+ case ETHTOOL_SSET: -+ ret = et_set_settings(et->dev, ecmd); -+ break; -+ case ETHTOOL_GDRVINFO: -+ et_get_driver_info(et->dev, (struct ethtool_drvinfo *)ecmd); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ ET_UNLOCK(et); -+ -+ return (ret); -+} -+#endif /* SIOCETHTOOL */ -+ -+static int -+et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ et_info_t *et; -+ int error; -+ char *buf; -+ int size, ethtoolcmd; -+ bool get = 0, set; -+ et_var_t *var = NULL; -+ void *buffer = NULL; -+ -+ et = ET_INFO(dev); -+ -+ ET_TRACE(("et%d: et_ioctl: cmd 0x%x\n", et->etc->unit, cmd)); -+ -+ switch (cmd) { -+#ifdef SIOCETHTOOL -+ case SIOCETHTOOL: -+ if (copy_from_user(ðtoolcmd, ifr->ifr_data, sizeof(uint32))) -+ return (-EFAULT); -+ -+ if (ethtoolcmd == ETHTOOL_GDRVINFO) -+ size = sizeof(struct ethtool_drvinfo); -+ else -+ size = sizeof(struct ethtool_cmd); -+ get = TRUE; set = TRUE; -+ break; -+#endif /* SIOCETHTOOL */ -+ case SIOCGETCDUMP: -+ size = IOCBUFSZ; -+ get = TRUE; set = FALSE; -+ break; -+ case SIOCGETCPHYRD: -+ case SIOCGETCPHYRD2: -+ case SIOCGETCROBORD: -+ size = sizeof(int) * 2; -+ get = TRUE; set = TRUE; -+ break; -+ case SIOCSETCSPEED: -+ case SIOCSETCPHYWR: -+ case SIOCSETCPHYWR2: -+ case SIOCSETCROBOWR: -+ size = sizeof(int) * 2; -+ get = FALSE; set = TRUE; -+ break; -+ case SIOCSETGETVAR: -+ size = sizeof(et_var_t); -+ set = TRUE; -+ break; -+ default: -+ size = sizeof(int); -+ get = FALSE; set = TRUE; -+ break; -+ } -+ -+ if ((buf = MALLOC(et->osh, size)) == NULL) { -+ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", MALLOCED(et->osh))); -+ return (-ENOMEM); -+ } -+ -+ if (set && copy_from_user(buf, ifr->ifr_data, size)) { -+ MFREE(et->osh, buf, size); -+ return (-EFAULT); -+ } -+ -+ if (cmd == SIOCSETGETVAR) { -+ var = (et_var_t *)buf; -+ if (var->buf) { -+ if (!var->set) -+ get = TRUE; -+ -+ if (!(buffer = (void *) MALLOC(et->osh, var->len))) { -+ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", -+ MALLOCED(et->osh))); -+ MFREE(et->osh, buf, size); -+ return (-ENOMEM); -+ } -+ -+ if (copy_from_user(buffer, var->buf, var->len)) { -+ MFREE(et->osh, buffer, var->len); -+ MFREE(et->osh, buf, size); -+ return (-EFAULT); -+ } -+ } -+ } -+ -+ switch (cmd) { -+#ifdef SIOCETHTOOL -+ case SIOCETHTOOL: -+ error = et_ethtool(et, (struct ethtool_cmd *)buf); -+ break; -+#endif /* SIOCETHTOOL */ -+ case SIOCSETGETVAR: -+ ET_LOCK(et); -+ error = etc_iovar(et->etc, var->cmd, var->set, buffer); -+ ET_UNLOCK(et); -+ if (!error && get) { -+ error = copy_to_user(var->buf, buffer, var->len); -+ } -+ -+ if (buffer) { -+ MFREE(et->osh, buffer, var->len); -+ } -+ break; -+ default: -+ ET_LOCK(et); -+ error = etc_ioctl(et->etc, cmd - SIOCSETCUP, buf) ? -EINVAL : 0; -+ ET_UNLOCK(et); -+ break; -+ } -+ -+ if (!error && get) { -+ error = copy_to_user(ifr->ifr_data, buf, size); -+ } -+ -+ MFREE(et->osh, buf, size); -+ -+ return (error); -+} -+ -+static struct net_device_stats * -+et_get_stats(struct net_device *dev) -+{ -+ et_info_t *et; -+ etc_info_t *etc; -+ struct net_device_stats *stats; -+ int locked = 0; -+ -+ et = ET_INFO(dev); -+ -+ ET_TRACE(("et%d: et_get_stats\n", et->etc->unit)); -+ -+ if (!in_atomic()) { -+ locked = 1; -+ ET_LOCK(et); -+ } -+ -+ etc = et->etc; -+ stats = &et->stats; -+ bzero(stats, sizeof(struct net_device_stats)); -+ -+ /* refresh stats */ -+ if (et->etc->up) { -+ (*etc->chops->statsupd)(etc->ch); -+ } -+ -+ /* SWAG */ -+ stats->rx_packets = etc->rxframe; -+ stats->tx_packets = etc->txframe; -+ stats->rx_bytes = etc->rxbyte; -+ stats->tx_bytes = etc->txbyte; -+ stats->rx_errors = etc->rxerror; -+ stats->tx_errors = etc->txerror; -+ -+ if (ET_GMAC(etc)) { -+ gmacmib_t *mib; -+ -+ mib = etc->mib; -+ stats->collisions = mib->tx_total_cols; -+ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); -+ stats->rx_crc_errors = mib->rx_crc_errs; -+ stats->rx_frame_errors = mib->rx_align_errs; -+ stats->rx_missed_errors = mib->rx_missed_pkts; -+ } else { -+ bcmenetmib_t *mib; -+ -+ mib = etc->mib; -+ stats->collisions = mib->tx_total_cols; -+ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); -+ stats->rx_crc_errors = mib->rx_crc_errs; -+ stats->rx_frame_errors = mib->rx_align_errs; -+ stats->rx_missed_errors = mib->rx_missed_pkts; -+ -+ } -+ -+ stats->rx_fifo_errors = etc->rxoflo; -+ stats->rx_over_errors = etc->rxoflo; -+ stats->tx_fifo_errors = etc->txuflo; -+ -+ if (locked) { -+ ET_UNLOCK(et); -+ } -+ -+ return (stats); -+} -+ -+static int -+et_set_mac_address(struct net_device *dev, void *addr) -+{ -+ et_info_t *et; -+ struct sockaddr *sa = (struct sockaddr *) addr; -+ -+ et = ET_INFO(dev); -+ ET_TRACE(("et%d: et_set_mac_address\n", et->etc->unit)); -+ -+ if (et->etc->up) { -+ return -EBUSY; -+ } -+ -+ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN); -+ bcopy(dev->dev_addr, &et->etc->cur_etheraddr, ETHER_ADDR_LEN); -+ -+ return 0; -+} -+ -+static void -+et_set_multicast_list(struct net_device *dev) -+{ -+ et_info_t *et; -+ etc_info_t *etc; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -+ struct dev_mc_list *mclist; -+#else -+ struct netdev_hw_addr *ha ; -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) */ -+ int i; -+ int locked = 0; -+ -+ et = ET_INFO(dev); -+ etc = et->etc; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -+ mclist = NULL ; /* fend off warnings */ -+#else -+ ha = NULL ; -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) */ -+ -+ ET_TRACE(("et%d: et_set_multicast_list\n", etc->unit)); -+ -+ if (!in_atomic()) { -+ locked = 1; -+ ET_LOCK(et); -+ } -+ -+ if (etc->up) { -+ etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; -+ etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: etc->promisc; -+ -+ /* copy the list of multicasts into our private table */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -+ for (i = 0, mclist = dev->mc_list; mclist && (i < dev->mc_count); -+ i++, mclist = mclist->next) { -+ if (i >= MAXMULTILIST) { -+ etc->allmulti = TRUE; -+ i = 0; -+ break; -+ } -+ etc->multicast[i] = *((struct ether_addr *)mclist->dmi_addr); -+ } -+#else /* >= 2.6.36 */ -+ i = 0; -+ netdev_for_each_mc_addr(ha, dev) { -+ i ++; -+ if (i >= MAXMULTILIST) { -+ etc->allmulti = TRUE; -+ i = 0; -+ break; -+ } -+ etc->multicast[i] = *((struct ether_addr *)ha->addr); -+ } /* for each ha */ -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) */ -+ etc->nmulticast = i; -+ -+ /* LR: partial re-init, DMA is already initialized */ -+ et_init(et, ET_INIT_INTRON); -+ } -+ -+ if (locked) { -+ ET_UNLOCK(et); -+ } -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -+static irqreturn_t BCMFASTPATH -+et_isr(int irq, void *dev_id) -+#else -+static irqreturn_t BCMFASTPATH -+et_isr(int irq, void *dev_id, struct pt_regs *ptregs) -+#endif -+{ -+ et_info_t *et; -+ struct chops *chops; -+ void *ch; -+ uint events = 0; -+ osl_t *osh; -+ -+ et = (et_info_t *)dev_id; -+ chops = et->etc->chops; -+ ch = et->etc->ch; -+ osh = et->etc->osh; -+ -+ /* guard against shared interrupts */ -+ if (!et->etc->up) { -+ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); -+ goto done; -+ } -+ -+ /* get interrupt condition bits */ -+ events = (*chops->getintrevents)(ch, TRUE); -+ -+ /* not for us */ -+ if (!(events & INTR_NEW)) { -+ goto done; -+ } -+ -+ ET_TRACE(("et%d: et_isr: events 0x%x\n", et->etc->unit, events)); -+ ET_LOG("et%d: et_isr: events 0x%x", et->etc->unit, events); -+ -+#ifdef CONFIG_IPROC_2STAGE_RX -+ if (events & INTR_RX) { -+ et->rxinisr = true; -+ /* process a few RX interrupts */ -+ et_rxevent(osh, et, chops, ch, 1); -+ -+ et->rxinisr = false; -+ /* get interrupt condition bits */ -+ events = (*chops->getintrevents)(ch, TRUE); -+ et->resched = FALSE; -+ -+ /* not for us */ -+ if (!(events & INTR_NEW)) { -+ goto done; -+ } -+ } -+#endif /* CONFIG_IPROC_2STAGE_RX */ -+ -+ /* disable interrupts */ -+ (*chops->intrsoff)(ch); -+ -+ /* save intstatus bits */ -+ ASSERT(et->events == 0); -+ et->events = events; -+ -+ ASSERT(et->resched == FALSE); -+ -+#ifdef GMAC_NAPI2_POLL -+ napi_schedule(&et->napi_poll); -+#elif defined(GMAC_NAPI_POLL) -+ /* allow the device to be added to the cpu polling list if we are up */ -+ if (netif_rx_schedule_prep(et->dev)) { -+ /* tell the network core that we have packets to send up */ -+ __netif_rx_schedule(et->dev); -+ } else { -+ ET_ERROR(("et%d: et_isr: intr while in poll!\n", -+ et->etc->unit)); -+ (*chops->intrson)(ch); -+ } -+#else /* ! GMAC_NAPI_POLL && ! GMAC_NAPI2_POLL */ -+ /* schedule dpc */ -+#ifdef GMAC_ALL_PASSIVE -+ if (ET_ALL_PASSIVE_ENAB(et)) { -+ schedule_work(&et->dpc_task.work); -+ } else -+#endif /* GMAC_ALL_PASSIVE */ -+ { -+ tasklet_schedule(&et->tasklet); -+ } -+#endif /* GMAC_NAPI_POLL */ -+ -+done: -+ ET_LOG("et%d: et_isr ret", et->etc->unit, 0); -+ -+ return IRQ_RETVAL(events & INTR_NEW); -+} -+ -+static inline int -+et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota) -+{ -+ uint processed = 0; -+ void *p, *h = NULL, *t = NULL; -+ struct sk_buff *skb; -+ -+#ifdef GMAC_RATE_LIMITING -+ /* rate limiting */ -+ if (et->etc->rl_enabled) { -+ etc_check_rate_limiting(et->etc, ch); -+ } -+#endif /* GMAC_RATE_LIMITING */ -+ -+ /* read the buffers first */ -+ while ((p = (*chops->rx)(ch))) { -+ PKTSETLINK(p, NULL); -+ if (t == NULL) { -+ h = t = p; -+ } else { -+ PKTSETLINK(t, p); -+ t = p; -+ } -+ -+ /* we reached quota already */ -+ if (++processed >= quota) { -+ /* reschedule et_dpc()/et_poll() */ -+ et->resched = TRUE; -+ et->etc->rxquota++; -+ break; -+ } -+ } -+ -+ /* prefetch the headers */ -+ if (h != NULL) { -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); -+#else -+ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); -+#endif -+ } -+ -+ /* post more rx bufs */ -+ (*chops->rxfill)(ch); -+ -+ while ((p = h) != NULL) { -+ h = PKTLINK(h); -+ PKTSETLINK(p, NULL); -+ -+ /* prefetch the headers */ -+ if (h != NULL) { -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); -+#else -+ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); -+#endif -+ } -+ -+ skb = PKTTONATIVE(osh, p); -+ et->etc->unchained++; -+ et_sendup(et, skb); -+ } -+ -+ return (processed); -+} -+ -+#if defined(GMAC_NAPI2_POLL) -+static int BCMFASTPATH -+et_poll(struct napi_struct *napi, int budget) -+{ -+ int quota = budget; -+ struct net_device *dev = napi->dev; -+ et_info_t *et = ET_INFO(dev); -+ -+#elif defined(GMAC_NAPI_POLL) -+static int BCMFASTPATH -+et_poll(struct net_device *dev, int *budget) -+{ -+ int quota = min(RXBND, *budget); -+ et_info_t *et = ET_INFO(dev); -+#else /* GMAC_NAPI_POLL */ -+static void BCMFASTPATH -+et_dpc(ulong data) -+{ -+ et_info_t *et = (et_info_t *)data; -+ int quota = RXBND; -+#endif /* GMAC_NAPI_POLL */ -+ struct chops *chops; -+ void *ch; -+ osl_t *osh; -+ uint nrx = 0; -+ -+ chops = et->etc->chops; -+ ch = et->etc->ch; -+ osh = et->etc->osh; -+ -+ ET_TRACE(("et%d: et_dpc: events 0x%x\n", et->etc->unit, et->events)); -+ ET_LOG("et%d: et_dpc: events 0x%x", et->etc->unit, et->events); -+ -+#if !defined(GMAC_NAPI_POLL) && !defined(GMAC_NAPI2_POLL) -+ ET_LOCK(et); -+#endif /* ! NAPIx_POLL */ -+ -+ if (!et->etc->up) { -+ goto done; -+ } -+ -+ /* get interrupt condition bits again when dpc was rescheduled */ -+ if (et->resched) { -+ et->events = (*chops->getintrevents)(ch, FALSE); -+ et->resched = FALSE; -+ } -+ -+ if (et->events & INTR_RX) { -+ nrx = et_rxevent(osh, et, chops, ch, quota); -+ } -+ -+ if (et->events & INTR_TX) { -+ (*chops->txreclaim)(ch, FALSE); -+ } -+ -+ (*chops->rxfill)(ch); -+ -+ /* handle error conditions, if reset required leave interrupts off! */ -+ if (et->events & INTR_ERROR) { -+ if ((*chops->errors)(ch)) { -+ printk("%s error, calling et_init() for et%d\n", __FUNCTION__, et->etc->unit); -+ et_init(et, ET_INIT_INTROFF); -+ } else { -+ if (nrx < quota) { -+ nrx += et_rxevent(osh, et, chops, ch, quota); -+ } -+ } -+ } -+ -+ /* run the tx queue */ -+ if (et->etc->txq_state != 0) { -+ if (!ET_ALL_PASSIVE_ENAB(et)) { -+ et_sendnext(et); -+ } -+#ifdef GMAC_ALL_PASSIVE -+ else { -+#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 -+ schedule_work_on(1, &et->txq_task.work); -+#else -+ schedule_work(&et->txq_task.work); -+#endif -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+ } -+ -+ /* clear this before re-enabling interrupts */ -+ et->events = 0; -+ -+ /* something may bring the driver down */ -+ if (!et->etc->up) { -+ et->resched = FALSE; -+ goto done; -+ } -+ -+#if !defined(GMAC_NAPI_POLL) && !defined(GMAC_NAPI2_POLL) -+#ifdef GMAC_ALL_PASSIVE -+ if (et->resched) { -+ if (!ET_ALL_PASSIVE_ENAB(et)) { -+ tasklet_schedule(&et->tasklet); -+ } else { -+ schedule_work(&et->dpc_task.work); -+ } -+ } else { -+ (*chops->intrson)(ch); -+ } -+#else /* GMAC_ALL_PASSIVE */ -+ if (et->resched) { /* there may be frames left, reschedule et_dpc() */ -+ tasklet_schedule(&et->tasklet); -+ } else { /* re-enable interrupts */ -+ (*chops->intrson)(ch); -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+#endif /* ! NAPIx_POLL */ -+ -+done: -+#if defined(GMAC_NAPI_POLL) -+ /* update number of frames processed */ -+ *budget -= nrx; -+ dev->quota -= nrx; -+ -+ ET_TRACE(("et%d: et_poll: quota %d budget %d\n", -+ et->etc->unit, dev->quota, *budget)); -+ -+ /* we got packets but no quota */ -+ if (et->resched) { -+ return (1); -+ } -+ -+ netif_rx_complete(dev); -+ -+ /* enable interrupts now */ -+ (*chops->intrson)(ch); -+ -+ /* indicate that we are done */ -+ return (0); -+#elif defined(GMAC_NAPI2_POLL) -+ ET_TRACE(("et%d: et_poll: budget %d\n", -+ et->etc->unit, budget)); -+ -+ /* we got packets but no quota */ -+ if (et->resched) { -+ return (1); -+ } -+ -+ napi_complete(napi); -+ -+ /* enable interrupts now */ -+ (*chops->intrson)(ch); -+ -+ /* indicate that we are done */ -+ return (0); -+#else /* !defined(GMAC_NAPI_POLL) && !defined(GMAC_NAPI2_POLL) */ -+ ET_UNLOCK(et); -+ return; -+#endif -+} -+ -+#ifdef GMAC_ALL_PASSIVE -+static void BCMFASTPATH -+et_dpc_work(struct et_task *task) -+{ -+#if !defined(GMAC_NAPI_POLL) && !defined(GMAC_NAPI2_POLL) -+ et_info_t *et = (et_info_t *)task->context; -+ et_dpc((unsigned long)et); -+#else -+ BUG_ON(1); -+#endif -+ return; -+} -+#endif /* GMAC_ALL_PASSIVE */ -+ -+static void -+et_error(et_info_t *et, struct sk_buff *skb, void *rxh) -+{ -+ uchar eabuf[32]; -+ struct ether_header *eh; -+ -+ eh = (struct ether_header *)skb->data; -+ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, eabuf); -+ -+ if (RXH_OVERSIZE(et->etc, rxh)) { -+ ET_ERROR(("et%d: rx: over size packet from %s\n", et->etc->unit, eabuf)); -+ } -+ if (RXH_CRC(et->etc, rxh)) { -+ ET_ERROR(("et%d: rx: crc error from %s\n", et->etc->unit, eabuf)); -+ } -+ if (RXH_OVF(et->etc, rxh)) { -+ ET_ERROR(("et%d: rx: fifo overflow\n", et->etc->unit)); -+ } -+ if (RXH_NO(et->etc, rxh)) { -+ ET_ERROR(("et%d: rx: crc error (odd nibbles) from %s\n", -+ et->etc->unit, eabuf)); -+ } -+ if (RXH_RXER(et->etc, rxh)) { -+ ET_ERROR(("et%d: rx: symbol error from %s\n", et->etc->unit, eabuf)); -+ } -+} -+ -+static void BCMFASTPATH -+et_sendup(et_info_t *et, struct sk_buff *skb) -+{ -+ etc_info_t *etc; -+ void *rxh; -+ uint16 flags; -+#ifdef DBG_PRINT_PKT -+ int idx; -+#endif /* DBG_PRINT_PKT */ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ struct sk_buff *next; -+#endif /* CONFIG_BCM_IPROC_GMAC_PREFETCH */ -+ -+ etc = et->etc; -+ -+ /* packet buffer starts with rxhdr */ -+ rxh = skb->data; -+ -+ /* strip off rxhdr */ -+ __skb_pull(skb, HWRXOFF); -+ -+ ET_TRACE(("et%d: et_sendup: %d bytes\n", et->etc->unit, skb->len)); -+ ET_LOG("et%d: et_sendup: len %d", et->etc->unit, skb->len); -+ -+ etc->rxframe++; -+ etc->rxbyte += skb->len; -+ -+ /* eh should now be aligned 2-mod-4 */ -+ ASSERT(((ulong)skb->data & 3) == 2); -+ -+ /* strip off crc32 */ -+ __skb_trim(skb, skb->len - ETHER_CRC_LEN); -+ -+ ET_PRHDR("rx", (struct ether_header *)skb->data, skb->len, etc->unit); -+ ET_PRPKT("rxpkt", skb->data, skb->len, etc->unit); -+ -+#ifdef DBG_PRINT_PKT -+ printk("et%d: rxpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, -+ skb->data[12], skb->data[13], skb->data[14], skb->data[15]); -+ -+ printk("et%d: %s len(0x%x) rxpkt:", etc->unit, __FUNCTION__, skb->len); -+ for (idx = 0; idx < skb->len; idx++) { -+ if ((idx % 16) == 0) { -+ printk("\n"); -+ } -+ printk("%02x ", skb->data[idx]); -+ } -+ printk("\n"); -+#endif /* DBG_PRINT_PKT */ -+ -+ /* get the error flags */ -+ flags = RXH_FLAGS(etc, rxh); -+ -+ /* check for reported frame errors */ -+ if (flags) { -+ goto err; -+ } -+ -+ skb->dev = et->dev; -+ -+ ASSERT(!PKTISCHAINED(skb)); -+ -+ /* extract priority from payload and store it out-of-band -+ * in skb->priority -+ */ -+ if (et->etc->qos) { -+ pktsetprio(skb, TRUE); -+ } -+ -+ skb->protocol = eth_type_trans(skb, et->dev); -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ next = skb->next; -+ while (1) { -+ if (next != NULL) { -+ -+ prefetch_range(next, SKB_PREFETCH_LEN); -+ next = next->next; -+ } else { -+ break; -+ } -+ } -+#endif /* CONFIG_BCM_IPROC_GMAC_PREFETCH */ -+ -+ /* send it up */ -+#if defined(GMAC_NAPI_POLL) || defined(GMAC_NAPI2_POLL) -+#ifdef CONFIG_IPROC_2STAGE_RX -+ if (!et->rxinisr) { -+ netif_receive_skb(skb); -+ } else { -+ netif_rx(skb); -+ } -+#else /* CONFIG_IPROC_2STAGE_RX */ -+ if (et->dev->features & NETIF_F_GRO) { -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { -+ skb = vlan_untag(skb); -+ if (unlikely(!skb)) { -+ goto err; -+ } -+ } -+ napi_gro_receive(&et->napi_poll, skb); -+ } else { -+ netif_receive_skb(skb); -+ } -+#endif /* CONFIG_IPROC_2STAGE_RX */ -+#else -+ netif_rx(skb); -+#endif /* defined(GMAC_NAPI_POLL) || defined(GMAC_NAPI2_POLL) */ -+ -+ ET_LOG("et%d: et_sendup ret", et->etc->unit, 0); -+ -+ return; -+ -+err: -+ et_error(et, skb, rxh); -+ -+ PKTFRMNATIVE(etc->osh, skb); -+ PKTFREE(etc->osh, skb, FALSE); -+ -+ return; -+} -+ -+static void -+et_dumpet(et_info_t *et, struct bcmstrbuf *b) -+{ -+ bcm_bprintf(b, "et %p dev %p name %s tbusy %d txq[0].qlen %d malloced %d\n", -+ et, et->dev, et->dev->name, (uint)netif_queue_stopped(et->dev), et->txq[0].qlen, -+ MALLOCED(et->osh)); -+} -+ -+void -+et_dump(et_info_t *et, struct bcmstrbuf *b) -+{ -+/* bcm_bprintf(b, "et%d: %s %s version %s\n", et->etc->unit, -+ __DATE__, __TIME__, EPI_VERSION_STR); -+*/ -+ bcm_bprintf(b, "et%d: version %s\n", et->etc->unit, EPI_VERSION_STR); -+ -+ et_dumpet(et, b); -+ etc_dump(et->etc, b); -+ -+ bcm_bprintf(b, "txdfrm(%d); txdfrmropped(%d); txqlen(%d); txqstop(%d); txdmafull(%d) txmaxlen(%d) txsgpkt(%d)\n", -+ et->etc->txfrm, et->etc->txfrmdropped, et->etc->txqlen, et->etc->txqstop, et->etc->txdmafull, -+ et->etc->txmaxlen, et->etc->txsgpkt); -+ et->etc->txfrm=0; -+ et->etc->txfrmdropped=0; -+ et->etc->txqlen=0; -+ et->etc->txqstop=0; -+ et->etc->txdmafull=0; -+ et->etc->txmaxlen=0; -+ et->etc->txsgpkt=0; -+ -+ bcm_bprintf(b, "rxquota(%d); rxdmastopped(%d)\n", -+ et->etc->rxquota, et->etc->rxdmastopped); -+ et->etc->rxquota=0; -+ et->etc->rxdmastopped=0; -+#ifdef GMAC_RATE_LIMITING -+ bcm_bprintf(b, "rxd_dropped_packets(%d)\n", -+ et->etc->rl_dropped_packets); -+ et->etc->rl_dropped_packets=0; -+#endif /* GMAC_RATE_LIMITING */ -+ -+} -+ -+void -+et_link_up(et_info_t *et) -+{ -+ ET_ERROR(("et%d: link up (%d%s)\n", -+ et->etc->unit, et->etc->speed, (et->etc->duplex? "FD" : "HD"))); -+ printk(KERN_DEBUG "et%d Link Up: %d%s\n", et->etc->unit, et->etc->speed, et->etc->duplex?"FD":"HD"); -+ netif_carrier_on(et->dev); -+} -+ -+void -+et_link_down(et_info_t *et) -+{ -+ ET_ERROR(("et%d: link down\n", et->etc->unit)); -+ printk(KERN_DEBUG "et%d Link Down\n", et->etc->unit); -+ netif_carrier_off(et->dev); -+} -+ -+bool -+et_is_link_up(et_info_t *et) -+{ -+ return netif_carrier_ok(et->dev); -+} -+ -+/********************************************************************** -+ * iproc_gmac_drv_probe(device) -+ * -+ * The Platform Driver Probe function. -+ * -+ * Input parameters: -+ * device: The Device Context -+ * -+ * Return value: -+ * 0: Driver Probe is Succesful -+ * not 0: ERROR -+ **********************************************************************/ -+static int iproc_gmac_drv_probe(struct platform_device* pldev) -+{ -+ struct net_device *dev = NULL; -+ osl_t *osh = NULL; -+ et_info_t *et = NULL; -+ int unit = et_found; -+ int err = 0; -+ unsigned char devname[8] = {0}; -+ char name[128]; -+ int idx; -+ struct device_node *np = pldev->dev.of_node; -+ const void *macaddr; -+ -+ printk("%s enter :%s; id:0x%x; unit:%d\n", __FUNCTION__, pldev->name, pldev->id, unit); -+ -+ /* Validation of platform device structure */ -+ if (!pldev) { -+ ET_ERROR(("WRONG INPUT\nplatfrom_device pointer should not be NULL.\n")); -+ return -EINVAL; -+ } -+ -+ et_found++; -+ -+ macaddr = of_get_mac_address(np); -+ if (!macaddr) { -+ dev_err(&pldev->dev, "can't find MAC address\n"); -+ return -ENODEV; -+ } -+ -+ osh = osl_attach(pldev, PCI_BUS, FALSE); -+ ASSERT(osh); -+ -+ ET_TRACE(("%s call alloc_etherdev\n", __FUNCTION__)); -+ if ((dev = alloc_etherdev(sizeof( et_info_t ))) == NULL) { -+ ET_ERROR(("%s: alloc_etherdev() failed\n", __FUNCTION__)); -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ et = ET_INFO(dev); -+ bzero(et, sizeof(et_info_t)); /* Is this needed in 2.6.36 ? -LR */ -+ et->dev = dev; -+ et->osh = osh; -+ -+ dev->base_addr = (unsigned long)of_iomap(np, 0); -+ dev->irq = (unsigned int)irq_of_parse_and_map(np, 0); -+ -+ printk("et%d: base_addr (0x%x) irq (%d)\n", unit, (uint32)dev->base_addr, dev->irq); -+ -+ if ((et->regsva = ioremap_nocache(dev->base_addr, 0xc00)) == NULL) { -+ ET_ERROR(("et%d: ioremap() failed\n", unit)); -+ err = -ENOMEM; -+ goto exit; -+ } -+ ET_TRACE(("%s base_addr: 0x%x; regsva:0x%x\n", __FUNCTION__, (uint32)dev->base_addr, (uint32)et->regsva)); -+ -+ pldev->id = dev->base_addr; -+ dev_set_drvdata(&(pldev->dev), dev); -+ SET_NETDEV_DEV(dev, (&pldev->dev)); -+ -+ init_MUTEX(&et->sem); -+ spin_lock_init(&et->lock); -+ spin_lock_init(&et->txq_lock); -+ spin_lock_init(&et->tx_lock); -+ spin_lock_init(&et->isr_lock); -+ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ skb_queue_head_init(&et->txq[idx]); -+ } -+ -+ /* Common load-time initialization */ -+ et->etc = etc_attach((void *)et, VENDOR_BROADCOM, BCMIPROC_CHIP_ID, unit, osh, et->regsva); -+ if (et->etc == NULL) { -+ ET_ERROR(("et%d: etc_attach() failed\n", unit)); -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ ether_addr_copy(dev->dev_addr, macaddr); -+ bcopy(macaddr, (char *)&et->etc->cur_etheraddr, ETHER_ADDR_LEN); -+ -+ /* init 1 second watchdog timer */ -+ init_timer(&et->timer); -+ et->timer.data = (ulong)dev; -+ et->timer.function = et_watchdog; -+ -+#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ /* schedule one second watchdog timer */ -+ et->timer.expires = jiffies + HZ; -+ add_timer(&et->timer); -+ et->set = TRUE; -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ -+ -+#ifdef GMAC_RATE_LIMITING -+ /* Init 1 second watchdog timer */ -+ init_timer(&et->etc->rl_timer); -+ et->etc->rl_timer.data = (ulong)dev; -+ et->etc->rl_timer.function = et_release_congestion; -+#endif /* GMAC_RATE_LIMITING */ -+ -+#ifdef GMAC_ALL_PASSIVE -+ if (ET_ALL_PASSIVE_ENAB(et)) { -+ MY_INIT_WORK(&et->dpc_task.work, (work_func_t)et_dpc_work); -+ et->dpc_task.context = et; -+ MY_INIT_WORK(&et->txq_task.work, (work_func_t)et_txq_work); -+ et->txq_task.context = et; -+ } -+ if (et_ctf_pipeline_loopback(et)) { -+ et->all_dispatch_mode = FALSE; -+ } else { -+ et->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE; -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+ -+ ET_TRACE(("%s request irq\n", __FUNCTION__)); -+ /* register our interrupt handler */ -+ if (request_irq(dev->irq, et_isr, IRQF_SHARED, dev->name, et)) { -+ ET_ERROR(("%s: request_irq(%d) failed\n", __FUNCTION__, dev->irq)); -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ /* add us to the global linked list */ -+ et->next = et_list; -+ et_list = et; -+ -+#ifdef HAVE_NET_DEVICE_OPS -+ dev->netdev_ops = &et_netdev_ops ; -+#else /* HAVE_NET_DEVICE_OPS */ -+ dev->open = et_open; -+ dev->stop = et_close; -+ dev->hard_start_xmit = et_start; -+ dev->get_stats = et_get_stats; -+ dev->set_mac_address = et_set_mac_address; -+ dev->set_multicast_list = et_set_multicast_list; -+ dev->do_ioctl = et_ioctl; -+#endif /* HAVE_NET_DEVICE_OPS */ -+ -+#if defined(GMAC_NAPI_POLL) -+ dev->poll = et_poll; -+ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); -+#elif defined(GMAC_NAPI2_POLL) -+ netif_napi_add(dev, & et->napi_poll, et_poll, 64); -+ napi_enable(&et->napi_poll); -+#else /* !GMAC_NAPI_POLL && !GMAC_NAPI2_POLL */ -+ /* Setup the bottom half handler */ -+ tasklet_init(&et->tasklet, et_dpc, (ulong)et); -+#endif -+ -+#if defined(BCMDMASGLISTOSL) -+ dev->features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); -+ dev->vlan_features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); -+ -+#ifdef CONFIG_BCM_GRO_ENABLE -+ dev->features |= NETIF_F_GRO; -+ dev->vlan_features |= NETIF_F_GRO; -+ printk("et%d: Enable Checksum-SG-GRO\n", unit); -+#endif /* CONFIG_BCM_GRO_ENABLE */ -+#endif /* BCMDMASGLISTOSL */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) -+ dev->ethtool_ops = &et_ethtool_ops; -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */ -+ -+ /* Assign netdev name consistently, even if GMAC0 or 1 is disabled */ -+ snprintf(devname, 8, "eth%d", unit); -+ dev_alloc_name(dev, devname); -+ -+ ET_TRACE(("%s register netdev\n", __FUNCTION__)); -+ if (register_netdev(dev)) { -+ ET_ERROR(("%s register_netdev() failed\n", __FUNCTION__)); -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ /* Print hello string */ -+ (*et->etc->chops->longname)(et->etc->ch, name, sizeof(name)); -+ printk("%s: %s %s\n", dev->name, name, EPI_VERSION_STR); -+ -+ eth_mac_proc_create(dev); -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ -+ return 0; -+ -+exit: -+#ifndef CONFIG_OF -+ if (macbase) { -+ iounmap(macbase); -+ macbase=NULL; -+ } -+ if (memres) { -+ release_mem_region(memres->start, (memres->end - memres->start + 1)); -+ memres=NULL; -+ } -+#endif -+ if (dev) { -+ free_netdev(dev); -+ dev = NULL; -+ } -+ if (osh) { -+ osl_detach(osh); -+ osh=NULL; -+ } -+ if (et) { -+ etc_detach(et->etc); -+ et->dev = NULL; -+ et->osh = NULL; -+ et_free(et); -+ et=NULL; -+ } -+ return err; -+} -+ -+ -+/********************************************************************** -+ * iproc_gmac_drv_remove(device) -+ * -+ * The Removal of Platform Device, and un-initialize the previously -+ * added MAC, and it's MEM Regions and Resources. -+ * -+ * Input parameters: -+ * device: The Device Context -+ * -+ * Return value: -+ * 0: Driver Entry is Succesfull -+ **********************************************************************/ -+static int __exit iproc_gmac_drv_remove(struct platform_device *pldev) -+{ -+ struct net_device *dev = platform_get_drvdata(pldev); -+ int retVal = 0; -+ et_info_t *et = NULL; -+ struct resource *memres = NULL; -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ printk("%s: enter\n", __FUNCTION__); -+ -+#ifdef CONFIG_PM -+ iproc_gmac_drv_suspend(pldev, PMSG_SUSPEND); -+#endif -+ -+ et = ET_INFO(dev); -+ -+ iounmap(et->regsva); -+ unregister_netdev(dev); -+ -+ memres = platform_get_resource(pldev, IORESOURCE_MEM, 0); -+ if (memres) { -+ release_mem_region(memres->start, (memres->end - memres->start + 1)); -+ } else { -+ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register Memory Resource\n")); -+ retVal = -ENOMEM; -+ } -+ -+ free_netdev(dev); -+ -+#ifdef CONFIG_OF -+ eth_mac_proc_remove (dev); -+#endif -+ -+ et->dev = NULL; -+ et_free(et); -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ -+ return retVal; -+} -+ -+#ifdef CONFIG_PM -+static int iproc_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ int ret; -+ char *filename = "/usr/sbin/ifdown"; -+ char *argv[] = {filename, "eth0", NULL}; -+ char *envp[] = {"HOME=/", -+ "TERM=linux", -+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", -+ NULL}; -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ printk("%s: enter\n", __FUNCTION__); -+ -+/* ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp);*/ -+ ret = do_execve(getname_kernel(filename), (const char *const *)argv, (const char *const *)envp); -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ -+ return 0; -+} -+ -+static int iproc_gmac_drv_resume(struct platform_device *pdev) -+{ -+ int ret; -+ char *filename = "/usr/sbin/ifup"; -+ char *argv[] = {filename, "eth0", NULL}; -+ char *envp[] = {"HOME=/", -+ "TERM=linux", -+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", -+ NULL}; -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ printk("%s: enter\n", __FUNCTION__); -+ /*ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp);*/ -+ ret = do_execve(getname_kernel(filename), (const char *const *)argv, (const char *const *)envp); -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ -+ return 0; -+} -+#endif /* CONFIG_PM */ -+ -+ -+/********************************************************************** -+ * iproc_gmac_init_module(VOID) -+ * -+ * The Driver Entry Function -+ * -+ * Input parameters: -+ * None -+ * -+ * Return value: -+ * 0: Driver Entry is Succesful -+ * not 0: ERROR -+ **********************************************************************/ -+static int __init -+iproc_gmac_init_module(void) -+{ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ -+#ifdef BCMDBG -+ if (msglevel != 0xdeadbeef) { -+ et_msg_level = msglevel; -+ } else { -+ char *var = getvar(NULL, "et_msglevel"); -+ if (var) { -+ et_msg_level = bcm_strtoul(var, NULL, 0); -+ } -+ } -+ -+ printk("%s: msglevel set to 0x%x\n", __FUNCTION__, et_msg_level); -+#endif /* BCMDBG */ -+ -+#ifdef GMAC_ALL_PASSIVE -+ { -+ char *var = getvar(NULL, "et_dispatch_mode"); -+ if (var) -+ passivemode = bcm_strtoul(var, NULL, 0); -+ printk("%s: passivemode set to 0x%x\n", __FUNCTION__, passivemode); -+ } -+#endif /* GMAC_ALL_PASSIVE */ -+ -+#ifdef GMAC_NAPI_POLL -+ printk("%s: GMAC_NAPI_POLL mode\n", __FUNCTION__); -+#endif /* GMAC_NAPI_POLL */ -+ -+#ifdef GMAC_NAPI2_POLL -+ printk("%s: GMAC_NAPI2_POLL mode\n", __FUNCTION__); -+#endif /* GMAC_NAPI2_POLL */ -+ -+#ifdef ET_LIMIT_TXQ -+ { -+ char *var = getvar(NULL, "et_txq_thresh"); -+ if (var) { -+ et_txq_thresh = bcm_strtoul(var, NULL, 0); -+ } -+ printk("%s: et_txq_thresh set to 0x%x\n", __FUNCTION__, et_txq_thresh); -+ } -+#endif /* ET_LIMIT_TXQ */ -+ -+#ifdef GMAC_RATE_LIMITING -+ { -+ char *var = getvar(NULL, "et_rx_rate_limit"); -+ if (var) { -+ et_rx_rate_limit = bcm_strtoul(var, NULL, 0); -+ } -+ printk("%s: et_rx_rate_limit set to 0x%x\n", __FUNCTION__, et_rx_rate_limit); -+ } -+#endif /* GMAC_RATE_LIMITING */ -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ return 0; -+} -+ -+ -+#ifndef CONFIG_OF -+/********************************************************************** -+ * iproc_gmac_cleanup_module(VOID) -+ * -+ * The Driver Exit Function -+ * -+ * Input parameters: -+ * None -+ * -+ * Return value: -+ * Nothing -+ **********************************************************************/ -+static void __exit -+iproc_gmac_cleanup_module(void) -+{ -+ int idx; -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ -+ for (idx = 0; idx < IPROC_NUM_GMACS; idx++) { -+ if (gmac_pdev_loaded[idx]) { -+ /* Unregister GMAC driver */ -+ iproc_platform_driver_unregister(&gmac_pdrv[idx]); -+ } -+ } -+ -+ /* Clean up the proc directory */ -+ eth_mac_proc_remove(); -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ return; -+} -+#endif /*CONFIG_OF*/ -+ -+#if 0 -+static int get_fa_bypass(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ unsigned int len=0; -+ len += sprintf(page+len, "\n\n## Current FA Bypass setting = 0x%x, %s ##\n\n",gBypass, gBypass?"enabled":"disabled"); -+ *eof = 1; -+ return len; -+} -+ -+static int set_fa_bypass(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int len=1; -+ unsigned char debug_buffer[2]; -+ int bypass =0; -+ -+ if (count != 2) { -+ ET_ERROR(("Please pass (one:1) digit FA bypass value only, 0=disable FA bypass, 1 = enable FA bypass\n")); -+ return -EINVAL; -+ } -+ -+ /* Last buffer byte will be LF or CR only */ -+ if(copy_from_user(&debug_buffer[0], buffer, len)) { -+ ET_ERROR(("Problem in copying invalid user buffer\n")); -+ return -EFAULT; -+ } -+ -+ debug_buffer[len]='\0'; /* Only one byte value is available now */ -+ if ( sscanf(debug_buffer,"%d",&bypass) != 1) { -+ ET_ERROR(("\n##Invalid value :%s: is passed ##\n",debug_buffer)); -+ return -EINVAL; -+ } -+ if (!((bypass >=DISABLE_FA_BYPASS) && (bypass <= ENABLE_FA_BYPASS))) { -+ ET_ERROR(("\n##Passed value :%d: is not in valid range %d-%d \n",bypass,DISABLE_FA_BYPASS,ENABLE_FA_BYPASS)); -+ return -EINVAL; -+ } -+ ET_TRACE(("\n##set_fa_bypass(): Previous: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); -+ gBypass = bypass; -+ ET_TRACE(("\n##set_fa_bypass(): New: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); -+ return count; -+} -+#endif -+ -+static char* iproc_eth_proc_root="iproc_eth"; -+static struct proc_dir_entry *iproc_eth_root_dir=NULL; // BCM5892 eth proc root directory -+static int eth_mac_proc_create(struct net_device *dev ) -+{ -+/* struct proc_dir_entry *dent, *ent;*/ -+ struct proc_dir_entry *dent; -+ et_info_t *et = NULL; -+ etc_info_t *etc = NULL; -+ char fname[32]; -+ -+ et = ET_INFO(dev); -+ if (et != NULL) { -+ etc = et->etc; -+ } -+ -+ if ((et == NULL) || (etc == NULL)) { -+ printk("%s: error: Unit probably not initialized by probe function." -+ " et=0x%pm etc=0x%p\n", __FUNCTION__, et, etc); -+ return -1; -+ } -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ -+ snprintf(fname, 32, "%s%u", iproc_eth_proc_root, etc->unit); -+ -+ dent = proc_mkdir(fname,iproc_eth_root_dir); -+#if 0 -+ if (dent) { -+ /* unit 2 has FA connectivity, create bypass path only for unit 2 */ -+ if (etc->unit == 2) { -+ printk("\nCreating fa bypass proc entry\n"); -+ -+ ent = create_proc_entry("fa_bypass", S_IFREG|S_IRUGO, dent); -+ if (ent) { -+ ent->read_proc = get_fa_bypass; -+ ent->write_proc = set_fa_bypass; -+ } else { -+ printk("Error creating proc_entry, returning\n"); -+ return -1; -+ } -+ } -+ } -+#endif -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+ return 0; -+} -+ -+#ifndef CONFIG_OF -+static void eth_mac_proc_remove(void) -+{ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ printk("%s: enter\n", __FUNCTION__); -+ remove_proc_entry(iproc_eth_proc_root,NULL); -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+} -+#else -+static void eth_mac_proc_remove(struct net_device *dev) -+{ -+ et_info_t *et; -+ etc_info_t *etc; -+ char fname[32]; -+ -+ ET_TRACE(("%s: enter\n", __FUNCTION__)); -+ printk("%s: enter\n", __FUNCTION__); -+ -+ et = ET_INFO(dev); -+ if (et == NULL) { -+ printk("%s: error: Unit probably not initialized by probe function.\n", __FUNCTION__); -+ return; -+ } -+ -+ etc = et->etc; -+ if (etc == NULL) { -+ printk("%s: error: Unit probably not initialized by probe \ -+ function.\n", __FUNCTION__); -+ return; -+ } -+ -+ snprintf(fname, 32, "%s%u", iproc_eth_proc_root, etc->unit); -+ remove_proc_entry(fname,NULL); -+ -+ ET_TRACE(("%s: exit\n", __FUNCTION__)); -+} -+#endif /* CONFIG_OF */ -+ -+#ifdef CONFIG_OF -+static const struct of_device_id brcm_iproc_dt_ids[] = { -+ { .compatible = "brcm,iproc-gmac"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcm_iproc_dt_ids); -+ -+static struct platform_driver iproc_gmac_driver = -+{ -+ .probe = iproc_gmac_drv_probe, -+ .remove = __exit_p(iproc_gmac_drv_remove), -+ .suspend = iproc_gmac_drv_suspend, -+ .resume = iproc_gmac_drv_resume, -+ .driver = -+ { -+ .name = "bcmiproc-gmac", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcm_iproc_dt_ids), -+ }, -+}; -+module_init(iproc_gmac_init_module); -+module_platform_driver(iproc_gmac_driver); -+#else -+module_init(iproc_gmac_init_module); -+module_exit(iproc_gmac_cleanup_module); -+#endif /*CONFIG_OF*/ -+ -+MODULE_DESCRIPTION("Broadcom Northstar Ethernet Driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/et_linux.h 2017-11-09 17:53:43.900292000 +0800 -@@ -0,0 +1,50 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Linux device driver tunables for -+ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver -+ * -+ * $Id: et_linux.h 320789 2012-03-13 04:01:27Z rnuti $ -+ */ -+ -+#ifndef _et_linux_h_ -+#define _et_linux_h_ -+ -+/* tunables */ -+#define NTXD 512 /* # tx dma ring descriptors (must be ^2) */ -+#define NRXD 512 /* # rx dma ring descriptors (must be ^2) */ -+#if defined(CONFIG_RAM_SIZE) && (CONFIG_RAM_SIZE <= 16) -+#define NRXBUFPOST 256 /* try to keep this # rbufs posted to the chip */ -+#else -+#define NRXBUFPOST 420 /* try to keep this # rbufs posted to the chip */ -+#endif -+#ifdef CONFIG_JUMBO_FRAME -+#define BCM_ETHER_MAX_LEN 2500 -+#define RXBUFSZ (BCM_ETHER_MAX_LEN + HWRXOFF + BCMEXTRAHDROOM) /* receive buffer size */ -+#else -+#define BCM_ETHER_MAX_LEN 1518 //ETHER_MAX_LEN (1518) -+#define RXBUFSZ 1792 -+#endif /* CONFIG_JUMBO_FRAME */ -+ -+ -+#ifndef RXBND -+#define RXBND 64 //32 /* max # rx frames to process in dpc */ -+#endif -+ -+#if defined(ILSIM) || defined(__arch_um__) -+#undef NTXD -+#define NTXD 16 -+#undef NRXD -+#define NRXD 16 -+#undef NRXBUFPOST -+#define NRXBUFPOST 2 -+#endif -+ -+#define PKTCBND 48 -+ -+#define CTFPOOLSZ 768 -+ -+#define PREFSZ 96 -+#define ETPREFHDRS(h, sz) OSL_PREF_RANGE_ST((h), (sz)) -+ -+#endif /* _et_linux_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.c b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.c ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.c 2017-11-09 17:53:43.901298000 +0800 -@@ -0,0 +1,746 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Common [OS-independent] portion of -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Device Driver. -+ * -+ * $Id: etc.c 323634 2012-03-26 10:26:11Z groques $ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "etcgmac.h" -+ -+#ifdef BCMDBG -+uint32 et_msg_level = 1; -+#else -+uint32 et_msg_level = 0; -+#endif /* BCMDBG */ -+uint8 ethup = 0; -+uint8 ethupmask = 0; -+etc_info_t *ethupetcptr[IPROC_NUM_GMACS]; -+ -+/* local prototypes */ -+static void etc_loopback(etc_info_t *etc, int on); -+static void etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b); -+int etc_gmac_speed(int gmac); -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+extern void gmac_set_amac_mdio(int en); -+extern int gmac_has_mdio_access(void); -+#elif defined(CONFIG_MACH_WH2) -+extern void __iomem *get_iproc_wrap_ctrl_base(void); -+extern int egphy28_reg_read(uint32 phy_addr, int reg_addr, uint16 *data); -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+ -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+void gmac_serdes_asym_mode(etc_info_t *etcptrs[]); -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ -+/* 802.1d priority to traffic class mapping. queues correspond one-to-one -+ * with traffic classes. -+ */ -+uint32 up2tc[NUMPRIO] = { -+ TC_BE, /* 0 BE TC_BE Best Effort */ -+ TC_BK, /* 1 BK TC_BK Background */ -+ TC_BK, /* 2 -- TC_BK Background */ -+ TC_BE, /* 3 EE TC_BE Best Effort */ -+ TC_CL, /* 4 CL TC_CL Controlled Load */ -+ TC_CL, /* 5 VI TC_CL Controlled Load */ -+ TC_VO, /* 6 VO TC_VO Voice */ -+ TC_VO /* 7 NC TC_VO Voice */ -+}; -+ -+uint32 priq_selector[] = { -+ [0x0] = TC_NONE, [0x1] = TC_BK, [0x2] = TC_BE, [0x3] = TC_BE, -+ [0x4] = TC_CL, [0x5] = TC_CL, [0x6] = TC_CL, [0x7] = TC_CL, -+ [0x8] = TC_VO, [0x9] = TC_VO, [0xa] = TC_VO, [0xb] = TC_VO, -+ [0xc] = TC_VO, [0xd] = TC_VO, [0xe] = TC_VO, [0xf] = TC_VO -+}; -+ -+/* find the chip opsvec for this chip */ -+struct chops* -+etc_chipmatch(uint vendor, uint device) -+{ -+ extern struct chops bcmgmac_et_chops; -+ -+ if (bcmgmac_et_chops.id(vendor, device)) { -+ return (&bcmgmac_et_chops); -+ } -+ -+ return (NULL); -+} -+ -+void* -+etc_attach(void *et, uint vendor, uint device, uint unit, void *osh, void *regsva) -+{ -+ etc_info_t *etc; -+ char *var; -+ -+ ET_TRACE(("et%d: etc_attach: vendor 0x%x device 0x%x\n", unit, vendor, device)); -+ -+ /* some code depends on packed structures */ -+ ASSERT(sizeof(struct ether_addr) == ETHER_ADDR_LEN); -+ ASSERT(sizeof(struct ether_header) == ETHER_HDR_LEN); -+ -+ /* allocate etc_info_t state structure */ -+ if ((etc = (etc_info_t*) MALLOC(osh, sizeof(etc_info_t))) == NULL) { -+ ET_ERROR(("et%d: etc_attach: out of memory, malloced %d bytes\n", unit, -+ MALLOCED(osh))); -+ return (NULL); -+ } -+ bzero((char*)etc, sizeof(etc_info_t)); -+ -+ etc->et = et; -+ etc->unit = unit; -+ etc->osh = osh; -+ etc->vendorid = (uint16) vendor; -+ etc->deviceid = (uint16) device; -+ etc->forcespeed = etc_gmac_speed(unit); -+ etc->linkstate = FALSE; -+ etc->mdio_init_time = 5; /* number of seconds to wait before release mdio bus */ -+ var = getvar(NULL, "eth_init_time"); -+ if (var) { -+ etc->mdio_init_time = bcm_strtoul(var, NULL, 0); -+ } -+ printk("%s() mdio_init_time = %d\n", __FUNCTION__, etc->mdio_init_time); -+ ethupmask |= 1<unit; -+ ethupetcptr[unit] = etc; -+ -+ /* set chip opsvec */ -+ etc->chops = etc_chipmatch(vendor, device); -+ ASSERT(etc->chops); -+ -+ /* chip attach */ -+ if ((etc->ch = (*etc->chops->attach)(etc, osh, regsva)) == NULL) { -+ ET_ERROR(("et%d: chipattach error\n", unit)); -+ goto fail; -+ } -+ -+ return ((void*)etc); -+ -+fail: -+ etc_detach(etc); -+ return (NULL); -+} -+ -+void -+etc_detach(etc_info_t *etc) -+{ -+ if (etc == NULL) -+ return; -+ -+ /* free chip private state */ -+ if (etc->ch) { -+ (*etc->chops->detach)(etc->ch); -+ etc->chops = etc->ch = NULL; -+ } -+ -+ MFREE(etc->osh, etc, sizeof(etc_info_t)); -+} -+ -+void -+etc_reset(etc_info_t *etc) -+{ -+ ET_TRACE(("et%d: etc_reset\n", etc->unit)); -+ -+ etc->reset++; -+ -+ /* reset the chip */ -+ (*etc->chops->reset)(etc->ch); -+ -+ /* free any posted tx packets */ -+ (*etc->chops->txreclaim)(etc->ch, TRUE); -+ -+#ifdef DMA -+ /* free any posted rx packets */ -+ (*etc->chops->rxreclaim)(etc->ch); -+#endif /* DMA */ -+} -+ -+void -+etc_init(etc_info_t *etc, uint options) -+{ -+ ET_TRACE(("et%d: etc_init\n", etc->unit)); -+ -+ ASSERT(etc->pioactive == NULL); -+ ASSERT(!ETHER_ISNULLADDR(&etc->cur_etheraddr)); -+ ASSERT(!ETHER_ISMULTI(&etc->cur_etheraddr)); -+ -+ /* init the chip */ -+ (*etc->chops->init)(etc->ch, options); -+ /* init the PM change mode and linkstate */ -+ etc->pm_modechange = FALSE; -+ etc->linkstate = FALSE; -+} -+ -+/* mark interface up */ -+void -+etc_up(etc_info_t *etc) -+{ -+ etc->up = TRUE; -+ -+ /* enable the port phy */ -+ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 1); -+ -+ et_init(etc->et, ET_INIT_FULL | ET_INIT_INTRON); -+} -+ -+/* mark interface down */ -+uint -+etc_down(etc_info_t *etc, int reset) -+{ -+ uint callback; -+ -+ callback = 0; -+ -+ ET_FLAG_DOWN(etc); -+ -+ /* disable the port phy */ -+ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 0); -+ -+ if (reset) { -+ et_reset(etc->et); -+ } -+ -+ /* suppress link state changes during power management mode changes */ -+ if (etc->linkstate) { -+ etc->linkstate = FALSE; -+ if (!etc->pm_modechange) { -+ et_link_down(etc->et); -+ } -+ } -+ -+ return (callback); -+} -+ -+/* common iovar handler. return 0=ok, -1=error */ -+int -+etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg) -+{ -+ int error; -+ uint *vecarg; -+ -+ error = 0; -+ vecarg = (uint *)arg; -+ ET_TRACE(("et%d: etc_iovar: cmd 0x%x\n", etc->unit, cmd)); -+ -+ switch (cmd) { -+#ifdef BCMDBG -+ case IOV_ET_CLEAR_DUMP: -+ if (set) { -+ uint size = ((char *)(&etc->rxbadlen) - (char *)(&etc->txframe)); -+ -+ bzero((char *)&etc->txframe, size + sizeof(etc->rxbadlen)); -+ (*etc->chops->dumpmib)(etc->ch, NULL, TRUE); -+ error = 0; -+ } -+ break; -+#endif /* BCMDBG */ -+ case IOV_PKTC: -+ if (set) { -+ etc->pktc = *vecarg; -+ } else { -+ *vecarg = (uint)etc->pktc; -+ } -+ break; -+ -+ case IOV_PKTCBND: -+ if (set) { -+ etc->pktcbnd = MAX(*vecarg, 32); -+ } else { -+ *vecarg = etc->pktcbnd; -+ } -+ break; -+ -+ case IOV_COUNTERS: -+ { -+ struct bcmstrbuf b; -+ bcm_binit(&b, (char*)arg, IOCBUFSZ); -+ etc_dumpetc(etc, &b); -+ } -+ break; -+ -+ default: -+ error = -1; -+ } -+ -+ return (error); -+} -+ -+/* common ioctl handler. return: 0=ok, -1=error */ -+int -+etc_ioctl(etc_info_t *etc, int cmd, void *arg) -+{ -+ int error; -+ int val; -+ int *vec = (int*)arg; -+ -+ error = 0; -+ -+ val = arg ? *(int*)arg : 0; -+ -+ ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); -+ -+ switch (cmd) { -+ case ETCUP: -+ et_up(etc->et); -+ break; -+ -+ case ETCDOWN: -+ et_down(etc->et, TRUE); -+ break; -+ -+ case ETCLOOP: -+ etc_loopback(etc, val); -+ break; -+ -+ case ETCDUMP: -+ if (et_msg_level & 0x10000) { -+ bcmdumplog((char *)arg, IOCBUFSZ); -+ } else { -+ struct bcmstrbuf b; -+ bcm_binit(&b, (char*)arg, IOCBUFSZ); -+ et_dump(etc->et, &b); -+ } -+ break; -+ -+ case ETCSETMSGLEVEL: -+ et_msg_level = val; -+ break; -+ -+ case ETCPROMISC: -+ etc_promisc(etc, val); -+ break; -+ -+ case ETCQOS: -+ etc_qos(etc, val); -+ break; -+ -+ case ETCSPEED: -+ if (vec) { -+ if (vec[0] < ET_AUTO || vec[0] > ET_1000FULL) { -+ goto err; -+ } -+ -+ etc->forcespeed = vec[0]; -+ -+ /* explicitly reset the phy */ -+ (*etc->chops->phyreset)(etc->ch); -+ -+ /* request restart autonegotiation if we're reverting to adv mode */ -+ etc->advertise = etc->advertise2 = 0; -+ if (etc->forcespeed == ET_AUTO) { -+ if (vec[1] & ADVERTISED_10baseT_Half) { -+ etc->advertise |= ADV_10HALF; -+ } -+ if (vec[1] & ADVERTISED_10baseT_Full) { -+ etc->advertise |= ADV_10FULL; -+ } -+ if (vec[1] & ADVERTISED_100baseT_Half) { -+ etc->advertise |= ADV_100HALF; -+ } -+ if (vec[1] & ADVERTISED_100baseT_Full) { -+ etc->advertise |= ADV_100FULL; -+ } -+ if (vec[1] & ADVERTISED_1000baseT_Full) { -+ etc->advertise2 |= ADV_1000FULL; -+ } -+ etc->needautoneg = TRUE; -+ } else { -+ etc->needautoneg = FALSE; -+ } -+ et_init(etc->et, ET_INIT_INTRON); -+ } -+ break; -+ -+ case ETCPHYRD: -+ if (vec) { -+ vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); -+ ET_TRACE(("etc_ioctl: ETCPHYRD of reg 0x%x => 0x%x\n", vec[0], vec[1])); -+ } -+ break; -+ -+ case ETCPHYRD2: -+ if (vec) { -+ uint phyaddr, reg; -+ phyaddr = vec[0] >> 16; -+ reg = vec[0] & 0xffff; -+ vec[1] = (*etc->chops->phyrd)(etc->ch, phyaddr, reg); -+ ET_TRACE(("etc_ioctl: ETCPHYRD2 of phy 0x%x, reg 0x%x => 0x%x\n", -+ phyaddr, reg, vec[1])); -+ } -+ break; -+ -+ case ETCPHYWR: -+ if (vec) { -+ ET_TRACE(("etc_ioctl: ETCPHYWR to reg 0x%x <= 0x%x\n", vec[0], vec[1])); -+ (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16)vec[1]); -+ } -+ break; -+ -+ case ETCPHYWR2: -+ if (vec) { -+ uint phyaddr, reg; -+ phyaddr = vec[0] >> 16; -+ reg = vec[0] & 0xffff; -+ (*etc->chops->phywr)(etc->ch, phyaddr, reg, (uint16)vec[1]); -+ ET_TRACE(("etc_ioctl: ETCPHYWR2 to phy 0x%x, reg 0x%x <= 0x%x\n", -+ phyaddr, reg, vec[1])); -+ } -+ break; -+ -+ default: -+err: -+ error = -1; -+ } -+ -+ return (error); -+} -+ -+/* called once per second */ -+void -+etc_watchdog(etc_info_t *etc) -+{ -+ uint16 status; -+ uint16 lpa; -+ -+#if defined(CONFIG_MACH_WH2) -+ uint32 select = (ioread32(get_iproc_wrap_ctrl_base() + 0xa8)); /* IPROC_WRAP_TOP_STRAP_STATUS_1 */ -+ if (select & 0x04) /* select SGMII path */ -+ { -+ etc->speed = 1000; -+ etc->duplex = 1; -+ etc->linkstate = true; -+ (*etc->chops->duplexupd)(etc->ch); -+ return; -+ } -+#endif -+ etc->now++; -+ -+ /* no local phy registers */ -+ if (etc->phyaddr == EPHY_NOREG) -+ { -+ etc->linkstate = TRUE; -+ etc->duplex = 1; -+ /* keep emac txcontrol duplex bit consistent with current phy duplex */ -+ (*etc->chops->duplexupd)(etc->ch); -+ return; -+ } -+ -+ if (etc->up && etc->linkstate) { -+ if (!(ethup & 1<unit)) { -+ printk(KERN_DEBUG "et%d Interface up\n", etc->unit); -+ } -+ ethup |= 1<unit; -+ } -+ -+#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ if ( !gmac_has_mdio_access()) { -+ /* we can't monitor link so force link up */ -+ /* if GMAC does not have access to MDIO then exit */ -+ if (!etc->linkstate) { -+ etc->linkstate = TRUE; -+ etc->duplex = 1; -+ etc->speed = 1000; -+ } -+ /* keep emac txcontrol duplex bit consistent with current phy duplex */ -+ (*etc->chops->duplexupd)(etc->ch); -+ if (!et_is_link_up(etc->et)) { -+ printk(KERN_DEBUG "%s rcan't access PHY, forcing link up\n", __FUNCTION__); -+ et_link_up(etc->et); -+ } -+ return; -+ } -+ -+ /* check if need to release mdio access */ -+ if ((ethup==ethupmask) || (etc->now > etc->mdio_init_time)) { -+ /* either both links up or (5) "eth_init_time" seconds elapsed */ -+ /* keep mdio access if ethtool is set */ -+ char *s = getvar(NULL, "ethtool"); -+ if (!s) { -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+ gmac_serdes_asym_mode(ethupetcptr); -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ printk(KERN_DEBUG "%s releasing MDIO access; ethup(0x%x)\n", __FUNCTION__, ethup); -+ gmac_set_amac_mdio(0); -+ return; -+ } -+ } -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ -+ -+ status = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 1); -+ /* check for bad mdio read */ -+ if (status == 0xffff) { -+ ET_ERROR(("et%d: etc_watchdog: bad mdio read: phyaddr %d mdcport %d\n", -+ etc->unit, etc->phyaddr, etc->mdcport)); -+ return; -+ } -+ -+ if (etc->forcespeed == ET_AUTO) { -+ uint16 adv, adv2 = 0, status2 = 0, estatus; -+ -+ adv = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 4); -+ lpa = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 5); -+ -+ /* read extended status register. if we are 1000BASE-T -+ * capable then get our advertised capabilities and the -+ * link partner capabilities from 1000BASE-T control and -+ * status registers. -+ */ -+ estatus = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 15); -+ if ((estatus != 0xffff) && (estatus & EST_1000TFULL)) { -+ /* read 1000BASE-T control and status registers */ -+ adv2 = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 9); -+ status2 = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, 10); -+ } -+ -+ /* update current speed and duplex */ -+ if ((adv2 & ADV_1000FULL) && (status2 & LPA_1000FULL)) { -+ etc->speed = 1000; -+ etc->duplex = 1; -+ } else if ((adv2 & ADV_1000HALF) && (status2 & LPA_1000HALF)) { -+ etc->speed = 1000; -+ etc->duplex = 0; -+ } else if ((adv & ADV_100FULL) && (lpa & LPA_100FULL)) { -+ etc->speed = 100; -+ etc->duplex = 1; -+ } else if ((adv & ADV_100HALF) && (lpa & LPA_100HALF)) { -+ etc->speed = 100; -+ etc->duplex = 0; -+ } else if ((adv & ADV_10FULL) && (lpa & LPA_10FULL)) { -+ etc->speed = 10; -+ etc->duplex = 1; -+ } else { -+ etc->speed = 10; -+ etc->duplex = 0; -+ } -+ } -+ -+ /* monitor link state */ -+ if (!etc->linkstate && (status & STAT_LINK)) { -+ etc->linkstate = TRUE; -+ if (etc->pm_modechange) { -+ etc->pm_modechange = FALSE; -+ } else { -+ et_link_up(etc->et); -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+ (*etc->chops->forcespddpx)(etc->ch); -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ } -+ } else if (etc->linkstate && !(status & STAT_LINK)) { -+ etc->linkstate = FALSE; -+ if (!etc->pm_modechange) { -+ et_link_down(etc->et); -+ } -+ } -+ -+ /* keep emac txcontrol duplex bit consistent with current phy duplex */ -+ (*etc->chops->duplexupd)(etc->ch); -+ -+ /* check for remote fault error */ -+ if (status & STAT_REMFAULT) { -+ ET_ERROR(("et%d: remote fault\n", etc->unit)); -+ } -+ -+ /* check for jabber error */ -+ if (status & STAT_JAB) { -+ ET_ERROR(("et%d: jabber\n", etc->unit)); -+ } -+ -+ /* -+ * Read chip mib counters occationally before the 16bit ones can wrap. -+ * We don't use the high-rate mib counters. -+ */ -+ if ((etc->now % 30) == 0) { -+ (*etc->chops->statsupd)(etc->ch); -+ } -+} -+ -+static void -+etc_loopback(etc_info_t *etc, int on) -+{ -+ ET_TRACE(("et%d: etc_loopback: %d\n", etc->unit, on)); -+ -+ etc->loopbk = (bool) on; -+ et_init(etc->et, ET_INIT_INTRON); -+} -+ -+void -+etc_promisc(etc_info_t *etc, uint on) -+{ -+ ET_TRACE(("et%d: etc_promisc: %d\n", etc->unit, on)); -+ -+ etc->promisc = (bool) on; -+ et_init(etc->et, ET_INIT_INTRON); -+} -+ -+void -+etc_qos(etc_info_t *etc, uint on) -+{ -+ ET_TRACE(("et%d: etc_qos: %d\n", etc->unit, on)); -+ -+ etc->qos = (bool) on; -+ et_init(etc->et, ET_INIT_INTRON); -+} -+ -+void -+etc_dump(etc_info_t *etc, struct bcmstrbuf *b) -+{ -+ etc_dumpetc(etc, b); -+ (*etc->chops->dump)(etc->ch, b); -+} -+ -+static void -+etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b) -+{ -+ char perm[32], cur[32]; -+ uint i; -+ -+ bcm_bprintf(b, "etc 0x%x et 0x%x unit %d msglevel %d speed/duplex %d%s\n", -+ (ulong)etc, (ulong)etc->et, etc->unit, et_msg_level, -+ etc->speed, (etc->duplex ? "full": "half")); -+ bcm_bprintf(b, "up %d promisc %d loopbk %d forcespeed %d advertise 0x%x " -+ "advertise2 0x%x needautoneg %d\n", -+ etc->up, etc->promisc, etc->loopbk, etc->forcespeed, -+ etc->advertise, etc->advertise2, etc->needautoneg); -+ bcm_bprintf(b, "piomode %d pioactive 0x%x nmulticast %d allmulti %d qos %d\n", -+ etc->piomode, (ulong)etc->pioactive, etc->nmulticast, etc->allmulti, etc->qos); -+ bcm_bprintf(b, "vendor 0x%x device 0x%x rev %d coreunit %d phyaddr %d mdcport %d\n", -+ etc->vendorid, etc->deviceid, etc->chiprev, -+ etc->coreunit, etc->phyaddr, etc->mdcport); -+ -+ bcm_bprintf(b, "perm_etheraddr %s cur_etheraddr %s\n", -+ bcm_ether_ntoa(&etc->perm_etheraddr, perm), -+ bcm_ether_ntoa(&etc->cur_etheraddr, cur)); -+ -+ if (etc->nmulticast) { -+ bcm_bprintf(b, "multicast: "); -+ for (i = 0; i < etc->nmulticast; i++) { -+ bcm_bprintf(b, "%s ", bcm_ether_ntoa(&etc->multicast[i], cur)); -+ } -+ bcm_bprintf(b, "\n"); -+ } -+ -+ bcm_bprintf(b, "linkstate %d\n", etc->linkstate); -+ bcm_bprintf(b, "\n"); -+ -+ /* refresh stat counters */ -+ (*etc->chops->statsupd)(etc->ch); -+ -+ /* summary stat counter line */ -+ /* use sw frame and byte counters -- hw mib counters wrap too quickly */ -+ bcm_bprintf(b, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %d\n", -+ etc->txframe, etc->txbyte, etc->txerror, -+ etc->rxframe, etc->rxbyte, etc->rxerror); -+ -+ /* transmit & receive stat counters */ -+ /* hardware mib pkt and octet counters wrap too quickly to be useful */ -+ (*etc->chops->dumpmib)(etc->ch, b, FALSE); -+ -+ bcm_bprintf(b, "txnobuf %d reset %d dmade %d dmada %d dmape %d\n", -+ etc->txnobuf, etc->reset, etc->dmade, etc->dmada, etc->dmape); -+ -+ /* hardware mib pkt and octet counters wrap too quickly to be useful */ -+ bcm_bprintf(b, "rxnobuf %d rxdmauflo %d rxoflo %d rxbadlen %d " -+ "rxgiants %d rxoflodiscards %d\n", -+ etc->rxnobuf, etc->rxdmauflo, etc->rxoflo, etc->rxbadlen, -+ etc->rxgiants, etc->rxoflodiscards); -+ -+ bcm_bprintf(b, "chained %d chainedsz1 %d unchained %d maxchainsz %d currchainsz %d\n", -+ etc->chained, etc->chainedsz1, etc->unchained, etc->maxchainsz, -+ etc->currchainsz); -+ -+ bcm_bprintf(b, "\n"); -+} -+ -+uint -+etc_totlen(etc_info_t *etc, void *p) -+{ -+ uint total; -+ -+ total = 0; -+ for (; p; p = PKTNEXT(etc->osh, p)) { -+ total += PKTLEN(etc->osh, p); -+ } -+ return (total); -+} -+ -+#ifdef BCMDBG -+void -+etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit) -+{ -+ char da[32], sa[32]; -+ -+ if (msg && (msg[0] != '\0')) { -+ printf("et%d: %s: ", unit, msg); -+ } else { -+ printf("et%d: ", unit); -+ } -+ -+ printf("dst %s src %s type 0x%04X len %d\n", -+ bcm_ether_ntoa((struct ether_addr *)eh->ether_dhost, da), -+ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, sa), -+ ntoh16(eh->ether_type), -+ len); -+} -+void -+etc_prhex(char *msg, uchar *buf, uint nbytes, int unit) -+{ -+ if (msg && (msg[0] != '\0')) { -+ printf("et%d: %s:\n", unit, msg); -+ } else { -+ printf("et%d:\n", unit); -+ } -+ -+ prhex(NULL, buf, nbytes); -+} -+#endif /* BCMDBG */ -+ -+int -+etc_gmac_speed(int gmac) -+{ -+ char name[16], *speed; -+ sprintf(name, "et%dspeed", gmac); -+ -+ speed = nvram_get(name); -+ if (speed == NULL) { -+ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); -+ return ET_AUTO; -+ } -+ -+ if (!strcmp(speed, "2500")) { -+ printf("%s specifing GMAC%d speed: 2500\n", __FUNCTION__, gmac); -+ return ET_2500FULL; -+ } else if (!strcmp(speed, "1000")) { -+ printf("%s specifing GMAC%d speed: 1000\n", __FUNCTION__, gmac); -+ return ET_1000FULL; -+ } else if (!strcmp(speed, "100")) { -+ printf("%s specifing GMAC%d speed: 100\n", __FUNCTION__, gmac); -+ return ET_100FULL; -+ } else if (!strcmp(speed, "10")) { -+ printf("%s specifing GMAC%d speed: 10\n", __FUNCTION__, gmac); -+ return ET_10FULL; -+ } -+ -+ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); -+ return ET_AUTO; -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etc.h 2017-11-09 17:53:43.902294000 +0800 -@@ -0,0 +1,295 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Common [OS-independent] header file for -+ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver -+ * -+ * $Id: etc.h 327582 2012-04-14 05:02:37Z kenlo $ -+ */ -+ -+#ifndef _ETC_H_ -+#define _ETC_H_ -+ -+#include -+ -+#define MAXMULTILIST 32 -+ -+#ifndef ch_t -+#define ch_t void -+#endif -+ -+#define NUMTXQ 1 -+ -+ -+#define TXREC_THR 8 -+ -+#if defined(__ECOS) -+#define IOCBUFSZ 4096 -+#elif defined(__linux__) -+#define IOCBUFSZ 16384 -+#else -+#define IOCBUFSZ 4096 -+#endif -+ -+struct etc_info; /* forward declaration */ -+struct bcmstrbuf; /* forward declaration */ -+ -+/* each chip type supports a set of chip-type-specific ops */ -+struct chops { -+ bool (*id)(uint vendor, uint device); /* return true if match */ -+ void *(*attach)(struct etc_info *etc, void *dev, void *regs); -+ void (*detach)(ch_t *ch); /* free chip private state */ -+ void (*reset)(ch_t *ch); /* chip reset */ -+ void (*init)(ch_t *ch, uint options); /* chip init */ -+ bool (*tx)(ch_t *ch, void *p); /* transmit frame */ -+ void *(*rx)(ch_t *ch); /* receive frame */ -+ void (*rxfill)(ch_t *ch); /* post dma rx buffers */ -+ int (*getintrevents)(ch_t *ch, bool in_isr); /* return intr events */ -+ bool (*errors)(ch_t *ch); /* handle chip errors */ -+ void (*intrson)(ch_t *ch); /* enable chip interrupts */ -+ void (*intrsoff)(ch_t *ch); /* disable chip interrupts */ -+ void (*txreclaim)(ch_t *ch, bool all); /* reclaim transmit resources */ -+ void (*rxreclaim)(ch_t *ch); /* reclaim receive resources */ -+ void (*statsupd)(ch_t *ch); /* update sw stat counters */ -+ void (*dumpmib)(ch_t *ch, struct bcmstrbuf *, bool clear); /* get sw mib counters */ -+ void (*enablepme)(ch_t *ch); /* enable PME */ -+ void (*disablepme)(ch_t *ch); /* disable PME */ -+ void (*phyreset)(ch_t *ch); /* reset phy */ -+ uint16 (*phyrd)(ch_t *ch, uint phyaddr, uint reg); /* read phy register */ -+ void (*phywr)(ch_t *ch, uint phyaddr, uint reg, uint16 val); /* write phy register */ -+ void (*dump)(ch_t *ch, struct bcmstrbuf *b); /* debugging output */ -+ void (*longname)(ch_t *ch, char *buf, uint bufsize); /* return descriptive name */ -+ void (*duplexupd)(ch_t *ch); /* keep mac duplex consistent */ -+#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) -+ void (*forcespddpx)(ch_t *ch); /* force the speed and duplex */ -+#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ -+ void (*phyenable)(ch_t *ch, uint eth_num, uint phyaddr, int enable); /* enable phy */ -+}; -+ -+/* -+ * "Common" os-independent software state structure. -+ */ -+typedef struct etc_info { -+ void *et; /* pointer to os-specific private state */ -+ uint unit; /* device instance number */ -+ void *osh; /* pointer to os handler */ -+ bool pktc; /* packet chaining enabled or not */ -+ int pktcbnd; /* max # of packets to chain */ -+ void *mib; /* pointer to s/w maintained mib counters */ -+ bool up; /* interface up and running */ -+ bool promisc; /* promiscuous destination address */ -+ bool qos; /* QoS priority determination on rx */ -+ bool loopbk; /* loopback override mode */ -+ -+ int forcespeed; /* disable autonegotiation and force speed/duplex */ -+ uint advertise; /* control speed/duplex advertised caps */ -+ uint advertise2; /* control gige speed/duplex advertised caps */ -+ bool needautoneg; /* request restart autonegotiation */ -+ int speed; /* current speed: 10, 100 */ -+ int duplex; /* current duplex: 0=half, 1=full */ -+ -+ bool piomode; /* enable programmed io (!dma) */ -+ void *pioactive; /* points to pio packet being transmitted */ -+ volatile uint *txavail[NUMTXQ]; /* dma: # tx descriptors available */ -+ -+ uint16 vendorid; /* pci function vendor id */ -+ uint16 deviceid; /* pci function device id */ -+ uint chip; /* chip number */ -+ uint chiprev; /* chip revision */ -+ uint coreid; /* core id */ -+ uint corerev; /* core revision */ -+ -+ bool nicmode; /* is this core using its own pci i/f */ -+ -+ struct chops *chops; /* pointer to chip-specific opsvec */ -+ void *ch; /* pointer to chip-specific state */ -+ void *robo; /* optional robo private data */ -+ -+ uint txq_state; /* tx queues state bits */ -+ uint coreunit; /* sb chips: chip enet instance # */ -+ uint phyaddr; /* mdio 5-bit phy address for external phy */ -+ uint int_phyaddr; /* mdio 5-bit phy address for internal serdes*/ -+ uint mdcport; /* sb chips: which mii to use (enet core #) to access phy */ -+ -+ struct ether_addr cur_etheraddr; /* our local ethernet address */ -+ struct ether_addr perm_etheraddr; /* original sprom local ethernet address */ -+ -+ struct ether_addr multicast[MAXMULTILIST]; -+ uint nmulticast; -+ bool allmulti; /* enable all multicasts */ -+ -+ bool linkstate; /* link integrity state */ -+ bool pm_modechange; /* true if mode change is to due pm */ -+ -+ uint32 now; /* elapsed seconds */ -+ -+ uint32 boardflags; /* board flags */ -+ uint32 txrec_thresh; /* # of tx frames after which reclaim is done */ -+ uint32 switch_mode; /* switch mode */ -+ -+ uint32 mdio_init_time; /* # of seconds to wait before release mdio bus */ -+ -+#ifdef GMAC_RATE_LIMITING -+ /* rate limiting */ -+ bool rl_enabled; /* enable rate limiting logic */ -+ struct timer_list rl_timer; /* one second ratelimiting timer */ -+ bool rl_set; /* indicate the timer is set or not */ -+ uint32 rl_stopping_all_packets; -+ uint32 rl_stopping_broadcasts; -+ uint32 rl_dropped_all_packets; -+ uint32 rl_dropped_bc_packets; -+ uint32 rl_dropped_packets; -+ uint32 rl_prior_jiffies; -+ uint32 rx_bc_frame_cnt; -+#endif /* GMAC_RATE_LIMITING */ -+ -+ /* sw-maintained stat counters */ -+ uint32 txframes[NUMTXQ]; /* transmitted frames on each tx fifo */ -+ uint32 txframe; /* transmitted frames */ -+ uint32 txbyte; /* transmitted bytes */ -+ uint32 rxframe; /* received frames */ -+ uint32 rxbyte; /* received bytes */ -+ uint32 txerror; /* total tx errors */ -+ uint32 txnobuf; /* tx out-of-buffer errors */ -+ uint32 rxerror; /* total rx errors */ -+ uint32 rxgiants; /* total rx giant frames */ -+ uint32 rxnobuf; /* rx out-of-buffer errors */ -+ uint32 reset; /* reset count */ -+ uint32 dmade; /* pci descriptor errors */ -+ uint32 dmada; /* pci data errors */ -+ uint32 dmape; /* descriptor protocol error */ -+ uint32 rxdmauflo; /* receive descriptor underflow */ -+ uint32 rxoflo; /* receive fifo overflow */ -+ uint32 txuflo; /* transmit fifo underflow */ -+ uint32 rxoflodiscards; /* frames discarded during rx fifo overflow */ -+ uint32 rxbadlen; /* 802.3 len field != read length */ -+ uint32 chained; /* number of frames chained */ -+ uint32 chainedsz1; /* number of chain size 1 frames */ -+ uint32 unchained; /* number of frames not chained */ -+ uint32 maxchainsz; /* max chain size so far */ -+ uint32 currchainsz; /* current chain size */ -+ /* my counters */ -+ uint32 txfrm; /* tx frames */ -+ uint32 txfrmdropped; /* tx dropped frames */ -+ uint32 txqlen; -+ uint32 txqstop; -+ uint32 txdmafull; -+ uint32 txmaxlen; -+ uint32 txsgpkt; -+ uint32 rxquota; -+ uint32 rxdmastopped; -+} etc_info_t; -+ -+/* interrupt event bitvec */ -+#define INTR_TX 0x1 -+#define INTR_RX 0x2 -+#define INTR_ERROR 0x4 -+#define INTR_TO 0x8 -+#define INTR_NEW 0x10 -+ -+/* forcespeed values */ -+#define ET_AUTO -1 -+#define ET_10HALF 0 -+#define ET_10FULL 1 -+#define ET_100HALF 2 -+#define ET_100FULL 3 -+#define ET_1000HALF 4 -+#define ET_1000FULL 5 -+#define ET_2500FULL 6 /* 2.5Gigabit */ -+ -+/* init options */ -+#define ET_INIT_FULL 0x1 -+#define ET_INIT_INTRON 0x2 -+ -+/* Specific init options for et_init */ -+#define ET_INIT_DEF_OPTIONS (ET_INIT_FULL | ET_INIT_INTRON) -+#define ET_INIT_INTROFF (ET_INIT_FULL) -+#define ET_INIT_PARTIAL (0) -+ -+/* macro to safely clear the UP flag */ -+#define ET_FLAG_DOWN(x) (*(x)->chops->intrsoff)((x)->ch); \ -+ (x)->up = FALSE; -+ -+/* -+ * Least-common denominator rxbuf start-of-data offset: -+ * Must be >= size of largest rxhdr -+ * Must be 2-mod-4 aligned so IP is 0-mod-4 -+ */ -+#define HWRXOFF 30 -+ -+#define TC_BK 0 /* background traffic class */ -+#define TC_BE 1 /* best effort traffic class */ -+#define TC_CL 2 /* controlled load traffic class */ -+#define TC_VO 3 /* voice traffic class */ -+#define TC_NONE -1 /* traffic class none */ -+ -+#define RX_Q0 0 /* receive DMA queue */ -+#define NUMRXQ 1 /* gmac has one rx queue */ -+ -+#define TX_Q0 TC_BK /* DMA txq 0 */ -+#define TX_Q1 TC_BE /* DMA txq 1 */ -+#define TX_Q2 TC_CL /* DMA txq 2 */ -+#define TX_Q3 TC_VO /* DMA txq 3 */ -+ -+static inline uint32 -+etc_up2tc(uint32 up) -+{ -+ extern uint32 up2tc[]; -+ return (up2tc[up]); -+} -+ -+static inline uint32 -+etc_priq(uint32 txq_state) -+{ -+ extern uint32 priq_selector[]; -+ return (priq_selector[txq_state]); -+} -+ -+/* rx header flags bits */ -+#define RXH_FLAGS(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ ((((bcmgmacrxh_t *)(rxh))->flags) & htol16(GRXF_CRC | GRXF_OVF | GRXF_OVERSIZE)) : \ -+ ((((bcmenetrxh_t *)(rxh))->flags) & htol16(RXF_NO | RXF_RXER | RXF_CRC | RXF_OV))) -+ -+#define RXH_OVERSIZE(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVERSIZE) : FALSE) -+ -+#define RXH_PT(etc, rxh) (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_PT_MASK) -+ -+#define RXH_CRC(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_CRC) : \ -+ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_CRC)) -+ -+#define RXH_OVF(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVF) : \ -+ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_OV)) -+ -+#define RXH_RXER(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_RXER)) -+ -+#define RXH_NO(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_NO)) -+ -+/* Used for fa+ error determination */ -+#define RXH_CTFERROR(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ -+ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & (GRXF_CTFERR | GRXF_CRC | GRXF_OVF)) : FALSE) -+ -+#define ET_GMAC(etc) ((etc)->coreid == GMAC_CORE_ID) -+ -+/* exported prototypes */ -+extern struct chops *etc_chipmatch(uint vendor, uint device); -+extern void *etc_attach(void *et, uint vendor, uint device, uint unit, void *dev, void *regsva); -+extern void etc_detach(etc_info_t *etc); -+extern void etc_reset(etc_info_t *etc); -+extern void etc_init(etc_info_t *etc, uint options); -+extern void etc_up(etc_info_t *etc); -+extern uint etc_down(etc_info_t *etc, int reset); -+extern int etc_ioctl(etc_info_t *etc, int cmd, void *arg); -+extern int etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg); -+extern void etc_promisc(etc_info_t *etc, uint on); -+extern void etc_qos(etc_info_t *etc, uint on); -+extern void etc_dump(etc_info_t *etc, struct bcmstrbuf *b); -+extern void etc_watchdog(etc_info_t *etc); -+extern uint etc_totlen(etc_info_t *etc, void *p); -+extern void etc_robomib(etc_info_t *etc); -+ -+#endif /* _ETC_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.c b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.c ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.c 2017-11-09 17:53:43.904292000 +0800 -@@ -0,0 +1,2593 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Broadcom Gigabit Ethernet MAC (Unimac) core. -+ * This file implements the chip-specific routines for the GMAC core. -+ * -+ * $Id: etcgmac.c 327582 2012-04-14 05:02:37Z kenlo $ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for et_phyxx() routines */ -+#include -+#include -+#include -+#include "bcmiproc_phy.h" -+ -+#define ENABLE_MIB_REG_DUMP -+ -+/* MDIO address definitation */ -+#if defined(CONFIG_MACH_HR3) -+#if defined(CONFIG_MACH_WH2) -+#define GMAC_EXT_PHY_ADDR 0x18 -+#define GMAC_INT_PHY_ADDR 0x14 -+#else -+#define GMAC_EXT_PHY_ADDR 0x18 -+#define GMAC_INT_PHY_ADDR 0xFF -+#endif -+#elif defined(CONFIG_MACH_GH) -+#define GMAC_EXT_PHY_ADDR 0x18 -+#define GMAC_INT_PHY_ADDR 0xFF -+#elif defined(CONFIG_MACH_GH2) -+#define GMAC_EXT_PHY_ADDR 0x10 -+#define GMAC_INT_PHY_ADDR 0x19 -+#else -+#define GMAC_EXT_PHY_ADDR 0x01 -+#define GMAC_INT_PHY_ADDR 0x01 -+#endif -+ -+ -+extern void __iomem *get_iproc_wrap_ctrl_base(void); -+extern void __iomem *get_iproc_idm_base(int index); -+#if defined (CONFIG_MACH_KT2) -+#define IPROC_WRAP_MISC_CONTROL_OFFSET 0x24 -+#elif (defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_HR2)) -+#define IPROC_WRAP_MISC_CONTROL_OFFSET 0x3C -+#else -+#define IPROC_WRAP_MISC_CONTROL_OFFSET 0x40 -+#endif -+ -+static const u32 idm_ioctl_offset[] = { -+ 0x10408, -+#if defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_KT2) -+ 0x11408, -+#elif defined (CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) -+ 0x1f408, -+#endif -+}; -+#define AMAC_IDM_IO_CONTROL_DIRECT__CLK_250_SEL 6 -+#define AMAC_IDM_IO_CONTROL_DIRECT__DIRECT_GMII_MODE 5 -+#define AMAC_IDM_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN 3 -+ -+#if defined(CONFIG_MACH_HX4) -+#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL 3 -+#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL 2 -+#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 4 -+#endif /* defined(CONFIG_MACH_HX4) */ -+ -+#if defined(CONFIG_MACH_KT2) -+#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL 1 -+#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL 2 -+#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 3 -+#endif /* defined(CONFIG_MACH_KT2) */ -+ -+#if defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_WH2) -+#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 1 -+#endif /* defined(CONFIG_MACH_SB2) */ -+ -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+#include "bcmiproc_serdes.h" -+#include "bcmiproc_phy5461s.h" -+#elif defined(CONFIG_MACH_GH2) -+#include "sgmiiplus2_serdes.h" -+#include "phy542xx.h" -+#elif defined(CONFIG_MACH_HR3) -+#if defined(CONFIG_MACH_WH2) -+#include "../../../mdio/iproc_mdio.h" -+#include "sgmiiplus2_serdes.h" -+#include "bcmiproc_egphy28.h" -+#include -+#define IPROC_CMICD_COMPATIBLE "brcm,iproc-cmicd" -+#define CMIC_SBUS_RING_MAP_0_7(base) (base + 0x10098) -+#define CMIC_SBUS_RING_MAP_8_15(base) (base + 0x1009C) -+#define CMIC_SBUS_RING_MAP_16_23(base) (base + 0x100A0) -+#define CMIC_SBUS_RING_MAP_24_31(base) (base + 0x100A4) -+extern u32 cmicd_schan_read(void __iomem *base, u32 ctrl, u32 addr); -+extern u32 cmicd_schan_write(void __iomem *base, u32 ctrl, u32 addr, u32 val); -+extern int egphy28_init(void __iomem *base, u32 phy_addr); -+#else -+#include "bcmiproc_phy5481.h" -+#endif -+#elif defined(CONFIG_MACH_HR2) -+#include "bcmiproc_phy5221.h" -+#elif defined(CONFIG_MACH_GH) -+#include "bcmiproc_phy5481.h" -+#endif -+ -+ -+#if !defined(CONFIG_MACH_HR2) -+/* BCM5221 on HR2 board does not support this feature */ -+#define CONFIG_FORCED_MODE_AUTO_MDIX 1 -+#endif -+ -+struct bcmgmac; /* forward declaration */ -+#define ch_t struct bcmgmac -+#include -+ -+extern int nvram_env_gmac_name(int gmac, char *name); -+ -+/* private chip state */ -+struct bcmgmac { -+ void *et; /* pointer to et private state */ -+ etc_info_t *etc; /* pointer to etc public state */ -+ -+ gmac_commonregs_t *regscomm; /* pointer to GMAC COMMON registers */ -+ gmacregs_t *regs; /* pointer to chip registers */ -+ osl_t *osh; /* os handle */ -+ -+ void *etphy; /* pointer to et for shared mdc/mdio contortion */ -+ -+ uint32 intstatus; /* saved interrupt condition bits */ -+ uint32 intmask; /* current software interrupt mask */ -+ uint32 def_intmask;/* default interrupt mask */ -+ -+ hnddma_t *di[NUMTXQ];/* dma engine software state */ -+ -+ bool mibgood; /* true once mib registers have been cleared */ -+ gmacmib_t mib; /* mib statistic counters */ -+ si_t *sih; /* si utils handle */ -+ -+ char *vars; /* sprom name=value */ -+ uint vars_size; -+ -+ void *adm; /* optional admtek private data */ -+ mcfilter_t mf; /* multicast filter */ -+}; -+ -+/* local prototypes */ -+static bool chipid(uint vendor, uint device); -+static void *chipattach(etc_info_t *etc, void *osh, void *regsva); -+static void chipdetach(ch_t *ch); -+static void chipreset(ch_t *ch); -+static void chipinit(ch_t *ch, uint options); -+static bool chiptx(ch_t *ch, void *p); -+static void *chiprx(ch_t *ch); -+static void chiprxfill(ch_t *ch); -+static int chipgetintrevents(ch_t *ch, bool in_isr); -+static bool chiperrors(ch_t *ch); -+static void chipintrson(ch_t *ch); -+static void chipintrsoff(ch_t *ch); -+static void chiptxreclaim(ch_t *ch, bool all); -+static void chiprxreclaim(ch_t *ch); -+static void chipstatsupd(ch_t *ch); -+static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear); -+static void chipenablepme(ch_t *ch); -+static void chipdisablepme(ch_t *ch); -+static void chipphyreset(ch_t *ch); -+static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg); -+static void chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 val); -+static void chipdump(ch_t *ch, struct bcmstrbuf *b); -+static void chiplongname(ch_t *ch, char *buf, uint bufsize); -+static void chipduplexupd(ch_t *ch); -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+static void chipforcespddpx(ch_t *ch); -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ -+static void chipphyinit(ch_t *ch); -+static void chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v); -+static void chipphyforce(ch_t *ch, uint phyaddr); -+static void chipphyadvertise(ch_t *ch, uint phyaddr); -+static void chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable); -+static void chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b); -+static void gmac_mf_cleanup(ch_t *ch); -+static int gmac_speed(ch_t *ch, uint32 speed); -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) || defined(CONFIG_MACH_WH2) -+static void gmac_serdes_init(ch_t *ch); -+#endif -+static void gmac_miiconfig(ch_t *ch); -+ -+struct chops bcmgmac_et_chops = { -+ chipid, -+ chipattach, -+ chipdetach, -+ chipreset, -+ chipinit, -+ chiptx, -+ chiprx, -+ chiprxfill, -+ chipgetintrevents, -+ chiperrors, -+ chipintrson, -+ chipintrsoff, -+ chiptxreclaim, -+ chiprxreclaim, -+ chipstatsupd, -+ chipdumpmib, -+ chipenablepme, -+ chipdisablepme, -+ chipphyreset, -+ chipphyrd, -+ chipphywr, -+ chipdump, -+ chiplongname, -+ chipduplexupd, -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+ chipforcespddpx, -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ chipphyenable -+}; -+ -+static uint devices[] = { -+ BCM56150_CHIP_ID, -+ BCM56340_CHIP_ID, -+ BCM56450_CHIP_ID, -+ BCM53400_CHIP_ID, -+ BCM56260_CHIP_ID, -+ BCM56160_CHIP_ID, -+ BCM56170_CHIP_ID, -+ BCM53540_CHIP_ID, -+ 0x0000 -+}; -+ -+ -+#if defined(CONFIG_MACH_WH2) -+static uint32 select = 0x06; -+ -+static void -+cmid_schan_modify(void __iomem *base, u32 ctrl, u32 addr, u32 val, u32 mask) -+{ -+ u32 ori_val; -+ -+ ori_val = cmicd_schan_read(base, ctrl, addr); -+ ori_val &= ~mask; -+ ori_val |= (val & mask); -+ cmicd_schan_write(base, ctrl + 0x08000000, addr, ori_val); -+} -+ -+static void power_on_serdesphy(ch_t *ch) -+{ -+ void __iomem *base; -+ uint32 val; -+ int i; -+ -+ select = (ioread32(get_iproc_wrap_ctrl_base() + 0xa8)); /* IPROC_WRAP_TOP_STRAP_STATUS_1 */ -+ base = of_iomap(of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE), 0); -+ //* Configure SBUS Ring Map for TOP, block id = 16, ring number = 4 */ -+ writel(0x00000000, CMIC_SBUS_RING_MAP_0_7(base)); -+ writel(0x00430000, CMIC_SBUS_RING_MAP_8_15(base)); -+ writel(0x00005064, CMIC_SBUS_RING_MAP_16_23(base)); -+ writel(0x00000000, CMIC_SBUS_RING_MAP_24_31(base)); -+ -+ if (select & 0x04) /* select Serdes (SGMII Plus2) path */ -+ { -+ printf("AMAC selects SGMII path... \n"); -+ -+ /* Reset TOP_SGMII_CTRL_REG through S-Channel */ -+ /* bit 2 (RSTB_HW) & 3 (IDDQ) & 4 (PWRDWN) = 0 */ -+ cmid_schan_modify(base, 0x2c800200, 0x0207e800, 0x0, 0x0000001c); -+ /* bit 2 (RSTB_HW) & 1 (RSTB_MDIOREGS) & 0 (RSTB_PLL) = 1 */ -+ cmid_schan_modify(base, 0x2c800200, 0x0207e800, 0x00000007, 0x00000007); -+ -+ /* Hardware reset 4th lane. PHY addr = 0x17, Reg addr = 0x0000, bit 15 = 1 */ -+ val = chipphyrd(ch, GMAC_INT_PHY_ADDR, 0x0000); -+ val |= (1 << 15); -+ chipphywr(ch, GMAC_INT_PHY_ADDR, 0x0000, val); -+ -+ /* Power down other 3 lanes. PHY addr = (0x14, 0x15, 0x16) */ -+ for (i = 0; i < 3; ++i) -+ { -+ val = chipphyrd(ch, GMAC_INT_PHY_ADDR + i, 0x0); -+ val |= (1 << 11); -+ chipphywr(ch, GMAC_INT_PHY_ADDR + i, 0x0, val); -+ } -+ } else /* select EGPHY28 path */ -+ { -+ printf("AMAC selects EGPHY path... \n"); -+ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[23:20] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x00F00000, 0x00F00000); -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x20, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x040000, 0x040000); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ /* Reset TOP_SOFT_RESET_REG bit 4 (GXP2_RST) & 5 (GXP0_RST) & 6 (GXP1_RST) = 0 */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x00000070); -+ -+ mdelay(100); -+ -+ /* Give initial value */ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[23:20] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x0, 0x00F00000); -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x40000, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x040000); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ /* Reset TOP_SOFT_RESET_REG bit 4 (GXP2_RST) & 5 (GXP0_RST) & 6 (GXP1_RST) = 1 */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x00000070, 0x00000070); -+ } -+} -+#endif -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+static void *wrapaddr = 0; -+void gmac_set_amac_mdio(int en) -+{ -+ u32 tmp; -+#if defined(CONFIG_MACH_HX4) -+ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL; -+ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL; -+#elif defined(CONFIG_MACH_KT2) -+ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL; -+ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL; -+#endif -+ u32 iproc_mdio_sel= IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL; -+ -+ if (en) { -+ /* Get register base address */ -+ wrapaddr = get_iproc_wrap_ctrl_base() + IPROC_WRAP_MISC_CONTROL_OFFSET; -+ } -+ -+ tmp = ioread32(wrapaddr); -+ if (en) { -+#if defined(CONFIG_MACH_SB2) -+ /* set bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL -+ so AMAC can access the Serdes and Phy */ -+ tmp |= (1 << iproc_mdio_sel); -+#else -+ /* set bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL, -+ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL & -+ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL -+ so AMAC can access the Serdes and Phy */ -+ tmp |= ((1 << mdio_sel) | (1 << ctrl_sel) | (1 << iproc_mdio_sel)); -+#endif -+ } else { -+#if defined(CONFIG_MACH_SB2) -+ /* clear bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL -+ so CMIC can access the Serdes and Phy */ -+ tmp &= ~(1 << iproc_mdio_sel); -+#else -+ /* clear bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL & -+ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL -+ so CMIC can access the Serdes and Phy */ -+ tmp &= ~((1 << mdio_sel) | (1 << iproc_mdio_sel)); -+#endif -+ } -+ iowrite32(tmp, wrapaddr); -+ -+ if (!en) { -+ wrapaddr=0; -+ } -+} -+ -+int gmac_has_mdio_access(void) -+{ -+ u32 tmp; -+ u32 regmsk = (1 << IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL); -+ -+#if defined(CONFIG_MACH_HX4) -+ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL) | -+ (1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL)); -+#elif defined(CONFIG_MACH_KT2) -+ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL) | -+ (1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL)); -+#endif -+ -+ if (wrapaddr==0) { -+ /* if no wrapaddr then no access */ -+ return 0; -+ } -+ -+ tmp = ioread32(wrapaddr); -+ tmp &= ~regmsk; -+ if (tmp == regmsk) { -+ return 0; -+ } -+ -+ return 1; -+} -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) */ -+ -+/* This api will determine if this unit specified is the last interface. */ -+bool gmac_last_interface(int unit) -+{ -+ char name[128]; -+ int idx; -+ -+ /* if interface 2 or greater then must be last */ -+ if (unit >= 2) { -+ return true; -+ } -+ -+ /* Look to see if there is a next interface specified */ -+ for (idx = unit + 1; idx <= 2; idx++) { -+ nvram_env_gmac_name(idx, name); -+ if (getvar(NULL, name) != NULL) { -+ /* there is a next interface */ -+ return false; -+ } -+ } -+ /* no other interfaces */ -+ return true; -+} -+ -+ -+static bool -+chipid(uint vendor, uint device) -+{ -+ int idx; -+ -+ if (vendor != VENDOR_BROADCOM) { -+ ET_ERROR(("%s ERROR: NOT a BROADCOM Vendor ID (0x%x)\n", __FUNCTION__, vendor)); -+ return (FALSE); -+ } -+ -+ for (idx = 0; devices[idx]; idx++) { -+ if (device == devices[idx]) { -+ return (TRUE); -+ } -+ } -+ -+ ET_ERROR(("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device)); -+ printk("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device); -+ return (FALSE); -+} -+ -+static void * -+chipattach(etc_info_t *etc, void *osh, void *regsva) -+{ -+ ch_t *ch; -+ gmacregs_t *regs; -+ void *amacidmaddr; -+ uint32 idx, tmp; -+ char name[16], *var; -+ uint boardflags, boardtype; -+ uint coreidx; -+ ulong flags; -+ -+ ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva)); -+ -+ if ((ch = (ch_t *)MALLOC(osh, sizeof(ch_t))) == NULL) { -+ ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit, MALLOCED(osh))); -+ return (NULL); -+ } -+ bzero((char *)ch, sizeof(ch_t)); -+ -+ ch->etc = etc; -+ ch->et = etc->et; -+ ch->osh = osh; -+ -+ /* store the pointer to the sw mib */ -+ etc->mib = (void *)&ch->mib; -+ -+ /* get si handle */ -+ if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, SI_BUS, NULL, &ch->vars, -+ &ch->vars_size)) == NULL) { -+ ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit)); -+ goto fail; -+ } -+ -+ if ((regs = (gmacregs_t *)si_setcore(ch->sih, GMAC_CORE_ID, etc->unit)) == NULL) { -+ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC\n", etc->unit)); -+ goto fail; -+ } -+ -+ /* 2G_ENABLED: Enable IDM 250MHz for 2G mode */ -+ spin_lock_irqsave((spinlock_t *)&ch->sih->sih_lock, flags); -+ -+ coreidx = si_coreidx(ch->sih); -+ si_core_reset(ch->sih, 0, 0); -+ si_setcoreidx(ch->sih, coreidx); -+ -+ spin_unlock_irqrestore((spinlock_t *)&ch->sih->sih_lock, flags); -+ -+ ch->regs = regs; -+ etc->chip = ch->sih->chip; -+ etc->chiprev = ch->sih->chiprev; -+ etc->coreid = si_coreid(ch->sih); -+ etc->nicmode = !(ch->sih->bustype == SI_BUS); -+ etc->coreunit = si_coreunit(ch->sih); -+ etc->boardflags = getintvar(ch->vars, "boardflags"); -+ -+ boardflags = etc->boardflags; -+ boardtype = ch->sih->boardtype; -+ -+ etc->switch_mode = 0; -+ -+ /* -+ * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" . -+ * Instead, explicitly require the environment var "etphyaddr=". -+ */ -+ -+ /* get our phyaddr value */ -+ sprintf(name, "et%dphyaddr", etc->coreunit); -+ var = getvar(NULL, name); -+ if (var == NULL) { -+ etc->phyaddr = etc->unit + GMAC_EXT_PHY_ADDR; -+ etc->int_phyaddr = etc->unit + GMAC_INT_PHY_ADDR; -+ } else { -+ etc->phyaddr = bcm_atoi(var) & EPHY_MASK; -+ etc->int_phyaddr = etc->unit + GMAC_INT_PHY_ADDR; -+ } -+ printf("et%d: chipattach: phyaddr(0x%x)\n", etc->unit, etc->phyaddr); -+ -+ /* nvram says no phy is present */ -+ if (etc->phyaddr == EPHY_NONE) { -+ ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit)); -+ goto fail; -+ } -+ -+ /* reset the gmac core */ -+ chipreset(ch); -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ /* flip switch so AMAC can access serdes */ -+ if (wrapaddr == 0) { -+ gmac_set_amac_mdio(1); -+ } -+#elif defined(CONFIG_MACH_WH2) -+ /* power on SGMII/EGPHY most before chipphyreset() to read PHY ID */ -+ power_on_serdesphy(ch); -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) */ -+ -+ /* Get register base address */ -+ amacidmaddr = get_iproc_idm_base(0) + idm_ioctl_offset[etc->unit]; -+ tmp = ioread32(amacidmaddr); -+ tmp &= ~(1 << AMAC_IDM_IO_CONTROL_DIRECT__CLK_250_SEL); -+ tmp |= (1 << AMAC_IDM_IO_CONTROL_DIRECT__DIRECT_GMII_MODE); -+ tmp |= (1 << AMAC_IDM_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN); -+ iowrite32(tmp, amacidmaddr); -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) -+ /* enable serdes */ -+ gmac_serdes_init(ch); -+#elif defined(CONFIG_MACH_WH2) -+ if (select & 0x04) /* select Serdes (SGMII Plus2) path */ -+ gmac_serdes_init(ch); -+#endif -+ -+ /* dma attach */ -+ sprintf(name, "et%d", etc->coreunit); -+ -+ /* allocate dma resources for txqs */ -+ /* TX: TC_BK, RX: RX_Q0 */ -+ ch->di[0] = dma_attach(osh, name, ch->sih, -+ DMAREG(ch, DMA_TX, TX_Q0), -+ DMAREG(ch, DMA_RX, RX_Q0), -+ NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF, -+ &et_msg_level); -+ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ if (ch->di[idx] == NULL) { -+ ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit)); -+ goto fail; -+ } -+ } -+ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ if (ch->di[idx] != NULL) { -+ etc->txavail[idx] = (uint *)&ch->di[idx]->txavail; -+ } -+ } -+ -+ /* set default sofware intmask */ -+ sprintf(name, "et%d_no_txint", etc->coreunit); -+ if (getintvar(ch->vars, name)) { -+ /* if no_txint variable is non-zero we disable tx interrupts. -+ * we do the tx buffer reclaim once every few frames. -+ */ -+ ch->def_intmask = (DEF_INTMASK & ~(I_XI0 | I_XI1 | I_XI2 | I_XI3)); -+ etc->txrec_thresh = (((NTXD >> 2) > TXREC_THR) ? TXREC_THR - 1 : 1); -+ } else { -+ ch->def_intmask = DEF_INTMASK; -+ } -+ -+ ch->intmask = ch->def_intmask; -+ -+ /* reset phy: reset it once now */ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ if (ch->etc->unit == 0) { -+ serdes_reset_core(ch->etc->unit, etc->int_phyaddr); -+ } -+#endif -+ -+ chipphyreset(ch); -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ if (gmac_last_interface(etc->unit)) { -+ /* -+ * The 4-lane serdes is shared between XLDK and SDK. XLDK has to -+ * initialize the 3rd lane (phy address 3) that is used by SDK. -+ */ -+ serdes_init(etc->unit, 3); -+ serdes_start_pll(etc->unit, 1); -+ } -+#endif -+ -+ if (etc->forcespeed == ET_AUTO) { -+ etc->needautoneg = TRUE; -+ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); -+#if defined(CONFIG_MACH_HR2) -+ etc->advertise2 = 0; -+#else -+ etc->advertise2 = ADV_1000FULL; -+#endif -+ } -+ -+ return ((void *) ch); -+ -+fail: -+ chipdetach(ch); -+ return (NULL); -+} -+ -+static void -+chipdetach(ch_t *ch) -+{ -+ int32 idx; -+ -+ ET_TRACE(("et%d: chipdetach\n", ch->etc->unit)); -+ -+ if (ch == NULL) { -+ return; -+ } -+ -+ /* free dma state */ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ if (ch->di[idx] != NULL) { -+ dma_detach(ch->di[idx]); -+ ch->di[idx] = NULL; -+ } -+ } -+ -+ /* put the core back into reset */ -+ if (ch->sih) { -+ si_core_disable(ch->sih, 0); -+ } -+ -+ if (ch->etc) { -+ if (ch->etc->mib) { -+ ch->etc->mib = NULL; -+ } -+ } -+ -+ /* free si handle */ -+ if (ch->sih) { -+ si_detach(ch->sih); -+ ch->sih = NULL; -+ } -+ -+ /* free vars */ -+ if (ch->vars) { -+ MFREE(ch->osh, ch->vars, ch->vars_size); -+ } -+ -+ /* free chip private state */ -+ MFREE(ch->osh, ch, sizeof(ch_t)); -+} -+ -+static void -+chiplongname(ch_t *ch, char *buf, uint bufsize) -+{ -+ char *s; -+ -+ switch (ch->etc->deviceid) { -+ case BCM56150_CHIP_ID: -+ s = "Broadcom BCM5615x 10/100 Mbps Ethernet Controller"; -+ break; -+ case BCM56340_CHIP_ID: -+ s = "Broadcom BCM5634x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM56450_CHIP_ID: -+ s = "Broadcom BCM5645x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM53400_CHIP_ID: -+ s = "Broadcom BCM5340x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM56260_CHIP_ID: -+ s = "Broadcom BCM5626x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM56160_CHIP_ID: -+ s = "Broadcom BCM5616x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM53540_CHIP_ID: -+ s = "Broadcom BCM5354x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ case BCM56170_CHIP_ID: -+ s = "Broadcom BCM5617x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ default: -+ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; -+ break; -+ } -+ -+ strncpy(buf, s, bufsize); -+ buf[bufsize - 1] = '\0'; -+} -+ -+static void -+chipdump(ch_t *ch, struct bcmstrbuf *b) -+{ -+ bcm_bprintf(b, "regs 0x%lx etphy 0x%lx ch->intstatus 0x%x intmask 0x%x\n", -+ (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask); -+ bcm_bprintf(b, "\n"); -+ -+ /* registers */ -+ chipdumpregs(ch, ch->regs, b); -+ bcm_bprintf(b, "\n"); -+} -+ -+ -+#define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->name)) -+#define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->mib.name)) -+ -+static void -+chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b) -+{ -+ uint phyaddr; -+ -+ phyaddr = ch->etc->phyaddr; -+ -+ PRREG(devcontrol); PRREG(devstatus); -+ bcm_bprintf(b, "\n"); -+ PRREG(biststatus); -+ bcm_bprintf(b, "\n"); -+ PRREG(intstatus); PRREG(intmask); PRREG(gptimer); -+ bcm_bprintf(b, "\n"); -+ PRREG(intrecvlazy); -+ bcm_bprintf(b, "\n"); -+ PRREG(flowctlthresh); PRREG(wrrthresh); PRREG(gmac_idle_cnt_thresh); -+ bcm_bprintf(b, "\n"); -+ PRREG(phyaccess); PRREG(phycontrol); -+ bcm_bprintf(b, "\n"); -+ -+ PRREG(txqctl); PRREG(rxqctl); -+ bcm_bprintf(b, "\n"); -+ PRREG(gpioselect); PRREG(gpio_output_en); -+ bcm_bprintf(b, "\n"); -+ PRREG(clk_ctl_st); PRREG(pwrctl); -+ bcm_bprintf(b, "\n"); -+ -+ /* unimac registers */ -+ PRREG(hdbkpctl); -+ bcm_bprintf(b, "\n"); -+ PRREG(cmdcfg); -+ bcm_bprintf(b, "\n"); -+ PRREG(macaddrhigh); PRREG(macaddrlow); -+ bcm_bprintf(b, "\n"); -+ PRREG(rxmaxlength); PRREG(pausequanta); PRREG(macmode); -+ bcm_bprintf(b, "\n"); -+ PRREG(outertag); PRREG(innertag); PRREG(txipg); PRREG(pausectl); -+ bcm_bprintf(b, "\n"); -+ PRREG(txflush); PRREG(rxstatus); PRREG(txstatus); -+ bcm_bprintf(b, "\n"); -+#ifdef ENABLE_MIB_REG_DUMP -+ /* mib registers */ -+ PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts); -+ bcm_bprintf(b, "\n"); -+ -+ PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(rx_jabber_pkts); -+ PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs); -+ bcm_bprintf(b, "\n"); -+ PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts); -+#endif /* ENABLE_MIB_REG_DUMP */ -+ bcm_bprintf(b, "\n"); -+ if (phyaddr != EPHY_NOREG) { -+ /* print a few interesting phy registers */ -+ bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n", -+ chipphyrd(ch, phyaddr, 0), -+ chipphyrd(ch, phyaddr, 1), -+ chipphyrd(ch, phyaddr, 2), -+ chipphyrd(ch, phyaddr, 3)); -+ bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n", -+ chipphyrd(ch, phyaddr, 4), -+ chipphyrd(ch, phyaddr, 5), -+ chipphyrd(ch, phyaddr, 24), -+ chipphyrd(ch, phyaddr, 25)); -+ } -+ -+} -+ -+static void -+gmac_clearmib(ch_t *ch) -+{ -+ volatile uint32 *ptr; -+ -+ /* enable clear on read */ -+ OR_REG(ch->osh, &ch->regs->devcontrol, DC_MROR); -+ -+ for (ptr = &ch->regs->mib.tx_good_octets; ptr <= &ch->regs->mib.rx_uni_pkts; ptr++) { -+ (void)R_REG(ch->osh, ptr); -+ if (ptr == &ch->regs->mib.tx_q3_octets_high) { -+ ptr++; -+ } -+ } -+ -+ return; -+} -+ -+static void -+gmac_init_reset(ch_t *ch) -+{ -+ OR_REG(ch->osh, &ch->regs->cmdcfg, CC_SR); -+ OSL_DELAY(GMAC_RESET_DELAY); -+} -+ -+static void -+gmac_clear_reset(ch_t *ch) -+{ -+ AND_REG(ch->osh, &ch->regs->cmdcfg, ~CC_SR); -+ OSL_DELAY(GMAC_RESET_DELAY); -+} -+ -+static void -+gmac_reset(ch_t *ch) -+{ -+ uint32 ocmdcfg, cmdcfg; -+ -+ /* put the mac in reset */ -+ gmac_init_reset(ch); -+ -+ /* initialize default config */ -+ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | -+ CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF); -+ cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) -+ cmdcfg |= (CC_AE | CC_OT | CC_OR); -+#endif -+ -+ if (cmdcfg != ocmdcfg) { -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ } -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+} -+ -+static void -+gmac_promisc(ch_t *ch, bool mode) -+{ -+ uint32 cmdcfg; -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* put the mac in reset */ -+ gmac_init_reset(ch); -+ -+ /* enable or disable promiscuous mode */ -+ if (mode) { -+ cmdcfg |= CC_PROM; -+ } else { -+ cmdcfg &= ~CC_PROM; -+ } -+ -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+} -+ -+static int -+gmac_speed(ch_t *ch, uint32 speed) -+{ -+ uint32 cmdcfg; -+ uint32 hd_ena = 0; -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+ uint32_t sdctl; -+ uint32 set_speed = speed; -+#endif /* CONFIG_MACH_GH || CONFIG_MACH_HR3 */ -+ -+ switch (speed) { -+ case ET_10HALF: -+ hd_ena = CC_HD; -+ /* FALLTHRU */ -+ -+ case ET_10FULL: -+ speed = 0; -+ break; -+ -+ case ET_100HALF: -+ hd_ena = CC_HD; -+ /* FALLTHRU */ -+ -+ case ET_100FULL: -+ speed = 1; -+ break; -+ -+ case ET_1000FULL: -+ speed = 2; -+ break; -+ -+ case ET_1000HALF: -+ ET_ERROR(("et%d: gmac_speed: supports 1000 mbps full duplex only\n", -+ ch->etc->unit)); -+ return (FAILURE); -+ -+ case ET_2500FULL: -+ speed = 3; -+ break; -+ -+ default: -+ ET_ERROR(("et%d: gmac_speed: speed %d not supported\n", -+ ch->etc->unit, speed)); -+ return (FAILURE); -+ } -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* put mac in reset */ -+ gmac_init_reset(ch); -+ -+ /* set the speed */ -+ cmdcfg &= ~(CC_ES_MASK | CC_HD); -+ cmdcfg |= ((speed << CC_ES_SHIFT) | hd_ena); -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) -+ cmdcfg |= (CC_AE | CC_OT | CC_OR); -+#endif -+ -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+ -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl &= ~(SC_FORCE_SPD_STRAP_MASK); -+ switch (set_speed) { -+ case ET_1000FULL: -+ sdctl |= SC_FORCE_SPD_1G_VAL; -+ break; -+ case ET_100FULL: -+ case ET_100HALF: -+ sdctl |= SC_FORCE_SPD_100M_VAL; -+ break; -+ default: -+ break; -+ } -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ udelay(1000); -+#endif /* CONFIG_MACH_GH || CONFIG_MACH_HR3 */ -+ -+ return (SUCCESS); -+} -+ -+static void -+gmac_macloopback(ch_t *ch, bool on) -+{ -+ uint32 ocmdcfg, cmdcfg; -+ -+ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* put mac in reset */ -+ gmac_init_reset(ch); -+ -+ /* set/clear the mac loopback mode */ -+ if (on) { -+ cmdcfg |= CC_ML; -+ } else { -+ cmdcfg &= ~CC_ML; -+ } -+ -+ if (cmdcfg != ocmdcfg) { -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ } -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+} -+ -+static int -+gmac_loopback(ch_t *ch, uint32 mode) -+{ -+ switch (mode) { -+ case LOOPBACK_MODE_DMA: -+ /* to enable loopback for any channel set the loopback -+ * enable bit in xmt0control register. -+ */ -+ dma_fifoloopbackenable(ch->di[TX_Q0]); -+ break; -+ -+ case LOOPBACK_MODE_MAC: -+ gmac_macloopback(ch, TRUE); -+ break; -+ -+ case LOOPBACK_MODE_NONE: -+ gmac_macloopback(ch, FALSE); -+ break; -+ -+ default: -+ ET_ERROR(("et%d: gmac_loopaback: Unknown loopback mode %d\n", -+ ch->etc->unit, mode)); -+ return (FAILURE); -+ } -+ -+ return (SUCCESS); -+} -+ -+static void -+gmac_enable(ch_t *ch) -+{ -+ uint32 cmdcfg; -+ gmacregs_t *regs; -+ -+ regs = ch->regs; -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* put mac in reset */ -+ gmac_init_reset(ch); -+ -+ cmdcfg |= CC_SR; -+ -+ /* first deassert rx_ena and tx_ena while in reset */ -+ cmdcfg &= ~(CC_RE | CC_TE); -+ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+ -+ /* enable the mac transmit and receive paths now */ -+ OSL_DELAY(2); -+ cmdcfg &= ~CC_SR; -+ cmdcfg |= (CC_RE | CC_TE); -+ -+ /* assert rx_ena and tx_ena when out of reset to enable the mac */ -+ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); -+ -+ /* request ht clock */ -+ OR_REG(ch->osh, ®s->clk_ctl_st, CS_FH); -+ -+ return; -+} -+ -+static void -+gmac_txflowcontrol(ch_t *ch, bool on) -+{ -+ uint32 cmdcfg; -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* put the mac in reset */ -+ gmac_init_reset(ch); -+ -+ /* to enable tx flow control clear the rx pause ignore bit */ -+ if (on) { -+ cmdcfg &= ~CC_RPI; -+ } else { -+ cmdcfg |= CC_RPI; -+ } -+ -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+} -+ -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) || defined(CONFIG_MACH_WH2) -+static void -+gmac_serdes_init(ch_t *ch) -+{ -+ uint32_t sdctl, sdstat0, sdstat1; -+ gmacregs_t *regs; -+ -+ regs = ch->regs; -+ -+ ET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); -+ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); -+ -+ /* -+ * Bring up both digital and analog clocks -+ * -+ * NOTE: Many MAC registers are not accessible until the PLL is locked. -+ * An S-Channel timeout will occur before that. -+ */ -+ -+ sdctl = (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL); -+#if defined(CONFIG_MACH_HX4) -+ sdctl |= (SC_REFSEL_VAL|SC_REF_TERM_SEL_MASK); -+#elif defined(CONFIG_MACH_KT2) -+ sdctl |= SC_REF_TERM_SEL_MASK; -+#endif /* (defined(CONFIG_MACH_HX4) */ -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ udelay(1000); -+ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl |= (SC_IDDQ_MASK|SC_PWR_DOWN_MASK); -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl &= ~(SC_IDDQ_MASK|SC_PWR_DOWN_MASK); -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ /* Bring hardware out of reset */ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl |= (SC_RSTB_HW_MASK); -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ /* Bring MDIOREGS out of reset */ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl |= (SC_RSTB_MDIOREGS_MASK); -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ udelay(1000); -+ -+ /* Bring PLL out of reset */ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl |= (SC_RSTB_PLL_MASK); -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+ -+ udelay(1000); -+ -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); -+ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); -+ -+ return; -+} -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) || defined(CONFIG_MACH_WH2) */ -+ -+static void -+gmac_miiconfig(ch_t *ch) -+{ -+ /* BCM53010 GMAC DevStatus register has different definition of "Interface Mode" -+ * Bit 12:8 "interface_mode" This field is programmed through IDM control bits [6:2] -+ * -+ * Bit 0 : SOURCE_SYNC_MODE_EN - If set, Rx line clock input will be used by Unimac for -+ * sampling data.If this is reset, PLL reference clock (Clock 250 or Clk 125 based -+ * on CLK_250_SEL) will be used as receive side line clock. -+ * Bit 1 : DEST_SYNC_MODE_EN - If this is reset, PLL reference clock input (Clock 250 or -+ * Clk 125 based on CLK_250_SEL) will be used as transmit line clock. -+ * If this is set, TX line clock input (from external switch/PHY) is used as -+ * transmit line clock. -+ * Bit 2 : TX_CLK_OUT_INVERT_EN - If set, this will invert the TX clock out of AMAC. -+ * Bit 3 : DIRECT_GMII_MODE - If direct gmii is set to 0, then only 25 MHz clock needs to -+ * be fed at 25MHz reference clock input, for both 10/100 Mbps speeds. -+ * Unimac will internally divide the clock to 2.5 MHz for 10 Mbps speed -+ * Bit 4 : CLK_250_SEL - When set, this selects 250Mhz reference clock input and hence -+ * Unimac line rate will be 2G. -+ * If reset, this selects 125MHz reference clock input. -+ */ -+ -+ if (ch->etc->forcespeed == ET_AUTO) { -+ if (ch->etc->deviceid == BCM56150_CHIP_ID) { -+ gmac_speed(ch, ET_100FULL); -+ } else { -+ gmac_speed(ch, ET_1000FULL); -+ } -+ } else { -+ gmac_speed(ch, ch->etc->forcespeed); -+ } -+} -+ -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+void -+gmac_serdes_asym_mode(etc_info_t *etcptrs[]) -+{ -+ etc_info_t *etc; -+ -+ etc = etcptrs[0]; -+ -+ /* initialize serdes */ -+ gmac_serdes_init(etc->ch); -+ serdes_reset_core(etc->unit, etc->int_phyaddr); -+ -+ /* initialize lane 0 */ -+ serdes_set_asym_mode(etc->unit, etc->int_phyaddr); -+ serdes_init(etc->unit, etc->int_phyaddr); -+ serdes_speeddpx_set(etc->unit, etc->int_phyaddr, etc->speed, etc->duplex); -+ /* initialize lane 1 */ -+ etc = etcptrs[1]; -+ if (etc->linkstate) { -+ serdes_set_asym_mode(etc->unit, etc->int_phyaddr); -+ serdes_init(etc->unit, etc->int_phyaddr); -+ serdes_speeddpx_set(etc->unit, etc->int_phyaddr, etc->speed, etc->duplex); -+ } -+ -+ /* -+ * The 4-lane serdes is shared between XLDK and SDK. XLDK has to -+ * initialize the 3rd lane (phy address 3) that is used by SDK. -+ */ -+ serdes_init(etc->unit, 3); -+ -+ /* start PLL */ -+ serdes_start_pll(etc->unit, 1); -+} -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ -+ -+static void -+chipreset(ch_t *ch) -+{ -+ gmacregs_t *regs; -+ uint32 idx, sflags, flagbits = 0; -+ -+ ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); -+ -+ regs = ch->regs; -+ -+ if (!si_iscoreup(ch->sih)) { -+ /* power on reset: reset the enet core */ -+ goto chipinreset; -+ } -+ -+ /* Reset other three GMAC cores if needed */ -+ for (idx = 0; idx < IPROC_NUM_GMACS; idx++) { -+ /* As northstar requirement, we have to reset all GAMCs before accessing them. -+ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. -+ * then the other three GAMC didn't reset. -+ * We do it here. -+ */ -+ si_setcore(ch->sih, GMAC_CORE_ID, idx); -+ if (!si_iscoreup(ch->sih)) { -+ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, idx)); -+ si_core_reset(ch->sih, flagbits, 0); -+ } -+ } -+ si_setcore(ch->sih, GMAC_CORE_ID, 0); -+ -+ /* update software counters before resetting the chip */ -+ if (ch->mibgood) { -+ chipstatsupd(ch); -+ } -+ -+ /* reset the tx dma engines */ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ if (ch->di[idx]) { -+ ET_TRACE(("et%d: resetting tx dma%d\n", ch->etc->unit, idx)); -+ dma_txreset(ch->di[idx]); -+ } -+ } -+ -+ /* set gmac into loopback mode to ensure no rx traffic */ -+ gmac_loopback(ch, LOOPBACK_MODE_MAC); -+ OSL_DELAY(1); -+ -+ /* reset the rx dma engine */ -+ if (ch->di[RX_Q0]) { -+ ET_TRACE(("et%d: resetting rx dma\n", ch->etc->unit)); -+ dma_rxreset(ch->di[RX_Q0]); -+ } -+ -+ /* clear the multicast filter table */ -+ gmac_mf_cleanup(ch); -+ -+chipinreset: -+ sflags = si_core_sflags(ch->sih, 0, 0); -+ if (sflags & SISF_SW_ATTACHED) { -+ ET_TRACE(("et%d: internal switch attached\n", ch->etc->unit)); -+ flagbits = SICF_SWCLKE; -+ if (!ch->etc->robo) { -+ ET_TRACE(("et%d: reseting switch\n", ch->etc->unit)); -+ flagbits |= SICF_SWRST; -+ } -+ } -+ -+ /* Reset all GMAC cores */ -+ for (idx = 0; idx < IPROC_NUM_GMACS; idx++) { -+ /* As northstar requirement, we have to reset all GAMCs before accessing them. -+ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. -+ * then the other three GAMC didn't reset. -+ * We do it here. -+ */ -+ si_setcore(ch->sih, GMAC_CORE_ID, idx); -+ if (!si_iscoreup(ch->sih)) { -+ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, idx)); -+ si_core_reset(ch->sih, flagbits, 0); -+ } -+ } -+ si_setcore(ch->sih, GMAC_CORE_ID, 0); -+ -+ if ((sflags & SISF_SW_ATTACHED) && (!ch->etc->robo)) { -+ ET_TRACE(("et%d: taking switch out of reset\n", ch->etc->unit)); -+ si_core_cflags(ch->sih, SICF_SWRST, 0); -+ } -+ -+ /* reset gmac */ -+ gmac_reset(ch); -+ -+ /* clear mib */ -+ gmac_clearmib(ch); -+ ch->mibgood = TRUE; -+ -+ /* set mdc_transition_en */ -+ OR_REG(ch->osh, ®s->phycontrol, PC_MTE); -+ -+ /* Read the devstatus to figure out the configuration mode of -+ * the interface. Set the speed to 100 if the switch interface -+ * is mii/rmii. -+ */ -+ gmac_miiconfig(ch); -+ -+ /* clear persistent sw intstatus */ -+ ch->intstatus = 0; -+} -+ -+/* -+ * Lookup a multicast address in the filter hash table. -+ */ -+static int -+gmac_mf_lkup(ch_t *ch, struct ether_addr *mcaddr) -+{ -+ mflist_t *ptr; -+ -+ /* find the multicast address */ -+ for (ptr = ch->mf.bucket[GMAC_MCADDR_HASH(mcaddr)]; ptr != NULL; ptr = ptr->next) { -+ if (!ETHER_MCADDR_CMP(&ptr->mc_addr, mcaddr)) { -+ return (SUCCESS); -+ } -+ } -+ -+ return (FAILURE); -+} -+ -+/* -+ * Add a multicast address to the filter hash table. -+ */ -+static int -+gmac_mf_add(ch_t *ch, struct ether_addr *mcaddr) -+{ -+ uint32 hash; -+ mflist_t *entry; -+#ifdef BCMDBG -+ char mac[ETHER_ADDR_STR_LEN]; -+#endif /* BCMDBG */ -+ -+ /* add multicast addresses only */ -+ if (!ETHER_ISMULTI(mcaddr)) { -+ ET_ERROR(("et%d: adding invalid multicast address %s\n", -+ ch->etc->unit, bcm_ether_ntoa(mcaddr, mac))); -+ return (FAILURE); -+ } -+ -+ /* discard duplicate add requests */ -+ if (gmac_mf_lkup(ch, mcaddr) == SUCCESS) { -+ ET_ERROR(("et%d: adding duplicate mcast filter entry\n", ch->etc->unit)); -+ return (FAILURE); -+ } -+ -+ /* allocate memory for list entry */ -+ entry = MALLOC(ch->osh, sizeof(mflist_t)); -+ if (entry == NULL) { -+ ET_ERROR(("et%d: out of memory allocating mcast filter entry\n", ch->etc->unit)); -+ return (FAILURE); -+ } -+ -+ /* add the entry to the hash bucket */ -+ ether_copy(mcaddr, &entry->mc_addr); -+ hash = GMAC_MCADDR_HASH(mcaddr); -+ entry->next = ch->mf.bucket[hash]; -+ ch->mf.bucket[hash] = entry; -+ -+ return (SUCCESS); -+} -+ -+/* -+ * Cleanup the multicast filter hash table. -+ */ -+static void -+gmac_mf_cleanup(ch_t *ch) -+{ -+ mflist_t *ptr, *tmp; -+ int32 idx; -+ -+ for (idx = 0; idx < GMAC_HASHT_SIZE; idx++) { -+ ptr = ch->mf.bucket[idx]; -+ while (ptr) { -+ tmp = ptr; -+ ptr = ptr->next; -+ MFREE(ch->osh, tmp, sizeof(mflist_t)); -+ } -+ ch->mf.bucket[idx] = NULL; -+ } -+} -+ -+/* -+ * Initialize all the chip registers. If dma mode, init tx and rx dma engines -+ * but leave the devcontrol tx and rx (fifos) disabled. -+ */ -+static void -+chipinit(ch_t *ch, uint options) -+{ -+ etc_info_t *etc; -+ gmacregs_t *regs; -+ uint idx; -+ -+ regs = ch->regs; -+ etc = ch->etc; -+ -+ ET_TRACE(("et%d: chipinit\n", etc->unit)); -+ -+ /* enable one rx interrupt per received frame */ -+ W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); -+ -+ /* enable 802.3x tx flow control (honor received PAUSE frames) */ -+ gmac_txflowcontrol(ch, TRUE); -+ -+ /* enable/disable promiscuous mode */ -+ gmac_promisc(ch, etc->promisc); -+ -+ /* set our local address */ -+ W_REG(ch->osh, ®s->macaddrhigh, -+ hton32(*(uint32 *)&etc->cur_etheraddr.octet[0])); -+ W_REG(ch->osh, ®s->macaddrlow, -+ hton16(*(uint16 *)&etc->cur_etheraddr.octet[4])); -+ -+ if (!etc->promisc) { -+ /* gmac doesn't have a cam, hence do the multicast address filtering -+ * in the software -+ */ -+ /* allmulti or a list of discrete multicast addresses */ -+ if (!etc->allmulti && etc->nmulticast) { -+ for (idx = 0; idx < etc->nmulticast; idx++) { -+ (void)gmac_mf_add(ch, &etc->multicast[idx]); -+ } -+ } -+ } -+ -+ /* optionally enable mac-level loopback */ -+ if (etc->loopbk) { -+ gmac_loopback(ch, LOOPBACK_MODE_MAC); -+ } else { -+ gmac_loopback(ch, LOOPBACK_MODE_NONE); -+ } -+ -+ /* set max frame lengths - account for possible vlan tag */ -+ W_REG(ch->osh, ®s->rxmaxlength, BCM_ETHER_MAX_LEN + 32); -+ -+ /* -+ * Optionally, disable phy autonegotiation and force our speed/duplex -+ * or constrain our advertised capabilities. -+ */ -+ if (etc->forcespeed != ET_AUTO) { -+ gmac_speed(ch, etc->forcespeed); -+ chipphyforce(ch, etc->phyaddr); -+ switch (etc->forcespeed) { -+ case ET_1000FULL: -+ etc->speed = 1000; -+ etc->duplex = 1; -+ break; -+ case ET_1000HALF: -+ etc->speed = 1000; -+ etc->duplex = 0; -+ break; -+ case ET_100FULL: -+ etc->speed = 100; -+ etc->duplex = 1; -+ break; -+ case ET_100HALF: -+ etc->speed = 100; -+ etc->duplex = 0; -+ break; -+ case ET_10FULL: -+ etc->speed = 10; -+ etc->duplex = 1; -+ break; -+ case ET_10HALF: -+ etc->speed = 10; -+ etc->duplex = 0; -+ break; -+ default: -+ break; -+ } -+ } else if (etc->advertise && etc->needautoneg) { -+ chipphyadvertise(ch, etc->phyaddr); -+ } -+ /* enable the overflow continue feature and disable parity */ -+ dma_ctrlflags(ch->di[0], DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, -+ DMA_CTRL_ROC /* value */); -+ -+ if (options & ET_INIT_FULL) { -+ /* initialize the tx and rx dma channels */ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ dma_txinit(ch->di[idx]); -+ } -+ dma_rxinit(ch->di[RX_Q0]); -+ -+ /* post dma receive buffers */ -+ dma_rxfill(ch->di[RX_Q0]); -+ -+ /* lastly, enable interrupts */ -+ if (options & ET_INIT_INTRON) { -+ et_intrson(etc->et); -+ } -+ } else { -+ dma_rxenable(ch->di[RX_Q0]); -+ } -+ -+ /* turn on the emac */ -+ gmac_enable(ch); -+} -+ -+/* dma transmit */ -+static bool BCMFASTPATH -+chiptx(ch_t *ch, void *p0) -+{ -+ int error, len; -+ uint32 q = TX_Q0; -+ -+ ET_TRACE(("et%d: chiptx\n", ch->etc->unit)); -+ ET_LOG("et%d: chiptx", ch->etc->unit, 0); -+ -+ len = PKTLEN(ch->osh, p0); -+ -+ /* check tx max length */ -+ if (len > (BCM_ETHER_MAX_LEN + 32)) { -+ ET_ERROR(("et%d: chiptx: max frame length exceeded\n", -+ ch->etc->unit)); -+ PKTFREE(ch->osh, p0, TRUE); -+ return FALSE; -+ } -+ -+ /* gmac rev 0 workaround: unimac can only transmit frames of -+ * length 17 bytes or greater. so pad the frame and send a -+ * 17 byte frame. to do the padding just modify the packet -+ * length that we provide to the dma. unimac does the extra -+ * padding * required to send 64 byte frames. -+ */ -+ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) { -+ PKTSETLEN(ch->osh, p0, GMAC_MIN_FRAMESIZE); -+ } -+ -+ ASSERT(q < NUMTXQ); -+ -+ /* if tx completion intr is disabled then do the reclaim -+ * once every few frames transmitted. -+ */ -+ if ((ch->etc->txframes[q] & ch->etc->txrec_thresh) == 1) { -+ dma_txreclaim(ch->di[q], HNDDMA_RANGE_TRANSMITTED); -+ } -+ -+ error = dma_txfast(ch->di[q], p0, TRUE); -+ -+ if (error) { -+ ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit)); -+ ch->etc->txnobuf++; -+ return FALSE; -+ } -+ -+ ch->etc->txframes[q]++; -+ -+ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) { -+ if (skb_is_nonlinear((struct sk_buff*)p0)) { -+ printk("Modified nonlinear skb (et_ctf_pipeline_loopback) - not calling skb_trim\n"); -+ } else { -+ /* set back the orig length */ -+ PKTSETLEN(ch->osh, p0, len); -+ } -+ } -+ -+ return TRUE; -+} -+ -+/* reclaim completed transmit descriptors and packets */ -+static void BCMFASTPATH -+chiptxreclaim(ch_t *ch, bool forceall) -+{ -+ int32 idx; -+ -+ ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit)); -+ -+ for (idx = 0; idx < NUMTXQ; idx++) { -+ dma_txreclaim(ch->di[idx], forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED); -+ ch->intstatus &= ~(I_XI0 << idx); -+ } -+} -+ -+/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */ -+static void * BCMFASTPATH -+chiprx(ch_t *ch) -+{ -+ void *p; -+ struct ether_addr *da; -+ -+ ET_TRACE(("et%d: chiprx\n", ch->etc->unit)); -+ ET_LOG("et%d: chiprx", ch->etc->unit, 0); -+ -+ if (dma_rxstopped(ch->di[RX_Q0])) { -+ ch->etc->rxdmastopped++; -+ } -+ -+ /* gmac doesn't have a cam to do address filtering. so we implement -+ * the multicast address filtering here. -+ */ -+ while ((p = dma_rx(ch->di[RX_Q0])) != NULL) { -+ /* check for overflow error packet */ -+ if (RXH_FLAGS(ch->etc, PKTDATA(ch->osh, p)) & GRXF_OVF) { -+ PKTFREE(ch->osh, p, FALSE); -+ ch->etc->rxoflodiscards++; -+ continue; -+ } -+ -+#ifdef GMAC_RATE_LIMITING -+ /* rate limiting */ -+ /* printf("et%d: chiprx RXH_PT(0x%x)\n", ch->etc->unit, RXH_PT(ch->etc, PKTDATA(ch->osh, p))); */ -+ if (RXH_PT(ch->etc, PKTDATA(ch->osh, p)) == 2) -+ ch->etc->rx_bc_frame_cnt++; -+ if (ch->etc->rl_stopping_broadcasts) { -+ /* check if broadcast packet */ -+ if (RXH_PT(ch->etc, PKTDATA(ch->osh, p)) == 2) { -+ /* broadcast packet */ -+ PKTFREE(ch->osh, p, FALSE); -+ ch->etc->rl_dropped_bc_packets++; -+ ch->etc->rl_dropped_packets++; -+ continue; -+ } -+ } else if (ch->etc->rl_stopping_all_packets) { -+ PKTFREE(ch->osh, p, FALSE); -+ ch->etc->rl_dropped_all_packets++; -+ ch->etc->rl_dropped_packets++; -+ continue; -+ } -+#endif /* GMAC_RATE_LIMITING */ -+ -+ if (ch->etc->allmulti) { -+ return (p); -+ } else { -+ /* skip the rx header */ -+ PKTPULL(ch->osh, p, HWRXOFF); -+ -+ /* do filtering only for multicast packets when allmulti is false */ -+ da = (struct ether_addr *)PKTDATA(ch->osh, p); -+ if (!ETHER_ISMULTI(da) || -+ (gmac_mf_lkup(ch, da) == SUCCESS) || ETHER_ISBCAST(da)) { -+ PKTPUSH(ch->osh, p, HWRXOFF); -+ return (p); -+ } -+ PKTFREE(ch->osh, p, FALSE); -+ } -+ } -+ -+ ch->intstatus &= ~I_RI; -+ -+ /* post more rx buffers since we consumed a few */ -+ dma_rxfill(ch->di[RX_Q0]); -+ -+ return (NULL); -+} -+ -+/* reclaim completed dma receive descriptors and packets */ -+static void -+chiprxreclaim(ch_t *ch) -+{ -+ ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit)); -+ dma_rxreclaim(ch->di[RX_Q0]); -+ ch->intstatus &= ~I_RI; -+} -+ -+/* allocate and post dma receive buffers */ -+static void BCMFASTPATH -+chiprxfill(ch_t *ch) -+{ -+ ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit)); -+ ET_LOG("et%d: chiprxfill", ch->etc->unit, 0); -+ dma_rxfill(ch->di[RX_Q0]); -+} -+ -+#ifdef DBG_CHECK_ERR -+/* get current and pending interrupt events */ -+static void -+check_errs(ch_t *ch) -+{ -+ static uint32 crserrs = 0; -+ uint32 err; -+ -+ /* read the interrupt status register */ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_jabber_pkts); -+ if (err) { -+ printk("%s tx_jabber_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_oversize_pkts); -+ if (err) { -+ printk("%s tx_oversize_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_fragment_pkts); -+ if (err) { -+ printk("%s tx_fragment_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_underruns); -+ if (err) { -+ printk("%s tx_underruns (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_total_cols); -+ if (err) { -+ printk("%s tx_total_cols (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_single_cols); -+ if (err) { -+ printk("%s tx_single_cols (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_multiple_cols); -+ if (err) { -+ printk("%s tx_multiple_cols (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_excessive_cols); -+ if (err) { -+ printk("%s tx_excessive_cols (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_late_cols); -+ if (err) { -+ printk("%s tx_late_cols (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_defered); -+ if (err) { -+ printk("%s tx_defered (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_carrier_lost); -+ crserrs += err; -+ if (crserrs > 100) { -+ printk("%s tx_carrier_lost crserrs(0x%x)\n", __FUNCTION__, crserrs); -+ crserrs = 0; -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.tx_pause_pkts); -+ if (err) { -+ printk("%s tx_pause_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_jabber_pkts); -+ if (err) { -+ printk("%s rx_jabber_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_oversize_pkts); -+ if (err) { -+ printk("%s rx_oversize_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_fragment_pkts); -+ if (err) { -+ printk("%s rx_fragment_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_missed_pkts); -+ if (err) { -+ printk("%s rx_missed_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_crc_align_errs); -+ if (err) { -+ printk("%s rx_crc_align_errs (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_undersize); -+ if (err) { -+ printk("%s rx_undersize (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_crc_errs); -+ if (err) { -+ printk("%s rx_crc_errs (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_align_errs); -+ if (err) { -+ printk("%s rx_align_errs (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_symbol_errs); -+ if (err) { -+ printk("%s rx_symbol_errs (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_pause_pkts); -+ if (err) { -+ printk("%s rx_pause_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_nonpause_pkts); -+ if (err) { -+ printk("%s rx_nonpause_pkts (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->mib.rx_sachanges); -+ if (err) { -+ printk("%s rx_sachanges (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->dmaregs[0].dmaxmt.status1); -+ if (err & 0xf0000000) { -+ printk("%s dma0 xmit status (0x%x)\n", __FUNCTION__, err); -+ } -+ -+ err = R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status1); -+ if (err & 0xf0000000) { -+ printk("%s dma0 rcv status (0x%x)\n", __FUNCTION__, err); -+ } -+ -+#if defined(CONFIG_MACH_HR2) -+ phy5221_chk_err(ch->etc->unit, ch->etc->phyaddr); -+#endif /* defined(CONFIG_MACH_HR2) */ -+} -+#endif /* DBG_CHECK_ERR */ -+ -+/* get current and pending interrupt events */ -+static int BCMFASTPATH -+chipgetintrevents(ch_t *ch, bool in_isr) -+{ -+ uint32 intstatus; -+ int events; -+ -+ events = 0; -+ -+ /* read the interrupt status register */ -+ intstatus = R_REG(ch->osh, &ch->regs->intstatus); -+ -+ /* defer unsolicited interrupts */ -+ intstatus &= (in_isr ? ch->intmask : ch->def_intmask); -+ -+ if (intstatus != 0) { -+ events = INTR_NEW; -+ } -+ -+ /* or new bits into persistent intstatus */ -+ intstatus = (ch->intstatus |= intstatus); -+ -+ /* return if no events */ -+ if (intstatus == 0) { -+ return (0); -+ } -+ -+#ifdef DBG_CHECK_ERR -+ check_errs(ch); -+#endif /* DBG_CHECK_ERR */ -+ -+ /* convert chip-specific intstatus bits into generic intr event bits */ -+ if (intstatus & I_RI) { -+ events |= INTR_RX; -+ } -+ if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) { -+ events |= INTR_TX; -+ } -+ if (intstatus & I_ERRORS) { -+ events |= INTR_ERROR; -+ } -+ -+ return (events); -+} -+ -+/* enable chip interrupts */ -+static void BCMFASTPATH -+chipintrson(ch_t *ch) -+{ -+ ch->intmask = ch->def_intmask; -+ W_REG(ch->osh, &ch->regs->intmask, ch->intmask); -+} -+ -+/* disable chip interrupts */ -+static void BCMFASTPATH -+chipintrsoff(ch_t *ch) -+{ -+ /* disable further interrupts from gmac */ -+ W_REG(ch->osh, &ch->regs->intmask, 0); -+ (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */ -+ ch->intmask = 0; -+ -+ /* clear the interrupt conditions */ -+ W_REG(ch->osh, &ch->regs->intstatus, ch->intstatus); -+} -+ -+/* return true of caller should re-initialize, otherwise false */ -+static bool BCMFASTPATH -+chiperrors(ch_t *ch) -+{ -+ uint32 intstatus; -+ etc_info_t *etc; -+ -+ etc = ch->etc; -+ -+ intstatus = ch->intstatus; -+ ch->intstatus &= ~(I_ERRORS); -+ -+ ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus)); -+ -+ if (intstatus & I_PDEE) { -+ ET_ERROR(("et%d: descriptor error\n", etc->unit)); -+ etc->dmade++; -+ } -+ -+ if (intstatus & I_PDE) { -+ ET_ERROR(("et%d: data error\n", etc->unit)); -+ etc->dmada++; -+ } -+ -+ if (intstatus & I_DE) { -+ ET_ERROR(("et%d: descriptor protocol error\n", etc->unit)); -+ etc->dmape++; -+ } -+ -+ if (intstatus & I_RDU) { -+ ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit)); -+ etc->rxdmauflo++; -+ } -+ -+ if (intstatus & I_RFO) { -+ ET_TRACE(("et%d: receive fifo overflow\n", etc->unit)); -+ etc->rxoflo++; -+ } -+ -+ if (intstatus & I_XFU) { -+ ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit)); -+ etc->txuflo++; -+ } -+ -+ /* if overflows or decriptors underflow, don't report it -+ * as an error and provoque a reset -+ */ -+ if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS) { -+ return (TRUE); -+ } -+ -+ return (FALSE); -+} -+ -+static void -+chipstatsupd(ch_t *ch) -+{ -+ etc_info_t *etc; -+ gmacregs_t *regs; -+ volatile uint32 *s; -+ uint32 *d; -+ -+ etc = ch->etc; -+ regs = ch->regs; -+ -+ /* read the mib counters and update the driver maintained software -+ * counters. -+ */ -+ OR_REG(ch->osh, ®s->devcontrol, DC_MROR); -+ for (s = ®s->mib.tx_good_octets, d = &ch->mib.tx_good_octets; -+ s <= ®s->mib.rx_uni_pkts; s++, d++) { -+ *d += R_REG(ch->osh, s); -+ if (s == &ch->regs->mib.tx_q3_octets_high) { -+ s++; -+ d++; -+ } -+ } -+ -+ /* -+ * Aggregate transmit and receive errors that probably resulted -+ * in the loss of a frame are computed on the fly. -+ * -+ * We seem to get lots of tx_carrier_lost errors when flipping -+ * speed modes so don't count these as tx errors. -+ * -+ * Arbitrarily lump the non-specific dma errors as tx errors. -+ */ -+ etc->txerror = ch->mib.tx_jabber_pkts + ch->mib.tx_oversize_pkts -+ + ch->mib.tx_underruns + ch->mib.tx_excessive_cols -+ + ch->mib.tx_late_cols + etc->txnobuf + etc->dmade -+ + etc->dmada + etc->dmape + etc->txuflo; -+ etc->rxerror = ch->mib.rx_jabber_pkts + ch->mib.rx_oversize_pkts -+ + ch->mib.rx_missed_pkts + ch->mib.rx_crc_align_errs -+ + ch->mib.rx_undersize + ch->mib.rx_crc_errs -+ + ch->mib.rx_align_errs -+ + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen; -+ etc->rxgiants = (ch->di[RX_Q0])->rxgiants; -+} -+ -+static void -+chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear) -+{ -+ gmacmib_t *m; -+ -+ m = &ch->mib; -+ -+ if (clear) { -+ bzero((char *)m, sizeof(gmacmib_t)); -+ return; -+ } -+ -+ bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d " -+ "tx_oversize_pkts %d\n", -+ m->tx_broadcast_pkts, m->tx_multicast_pkts, -+ m->tx_jabber_pkts, -+ m->tx_oversize_pkts); -+ bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n", -+ m->tx_fragment_pkts, m->tx_underruns); -+ bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d " -+ "tx_excessive_cols %d\n", -+ m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols, -+ m->tx_excessive_cols); -+ bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n", -+ m->tx_late_cols, m->tx_defered, m->tx_carrier_lost, -+ m->tx_pause_pkts); -+ -+ /* receive stat counters */ -+ /* hardware mib pkt and octet counters wrap too quickly to be useful */ -+ bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d " -+ "rx_oversize_pkts %d\n", -+ m->rx_broadcast_pkts, m->rx_multicast_pkts, -+ m->rx_jabber_pkts, m->rx_oversize_pkts); -+ bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d " -+ "rx_undersize %d\n", -+ m->rx_fragment_pkts, m->rx_missed_pkts, -+ m->rx_crc_align_errs, m->rx_undersize); -+ bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n", -+ m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs); -+ bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n", -+ m->rx_pause_pkts, m->rx_nonpause_pkts); -+} -+ -+static void -+chipenablepme(ch_t *ch) -+{ -+ return; -+} -+ -+static void -+chipdisablepme(ch_t *ch) -+{ -+ return; -+} -+ -+static void -+chipduplexupd(ch_t *ch) -+{ -+ uint32 cmdcfg; -+ int32 duplex, speed; -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+ uint32_t sdctl; -+#endif /* defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) */ -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* check if duplex mode changed */ -+ if (ch->etc->duplex && (cmdcfg & CC_HD)) { -+ duplex = 0; -+ } else if (!ch->etc->duplex && ((cmdcfg & CC_HD) == 0)) { -+ duplex = CC_HD; -+ } else { -+ duplex = -1; -+ } -+ -+ /* check if the speed changed */ -+ speed = ((cmdcfg & CC_ES_MASK) >> CC_ES_SHIFT); -+ if ((ch->etc->speed == 1000) && (speed != 2)) { -+ speed = 2; -+ } else if ((ch->etc->speed == 100) && (speed != 1)) { -+ speed = 1; -+ } else if ((ch->etc->speed == 10) && (speed != 0)) { -+ speed = 0; -+ } else { -+ speed = -1; -+ } -+ -+ /* no duplex or speed change required */ -+ if ((speed == -1) && (duplex == -1)) { -+ return; -+ } -+ -+ /* update the speed */ -+ if (speed != -1) { -+ cmdcfg &= ~CC_ES_MASK; -+ cmdcfg |= (speed << CC_ES_SHIFT); -+ } -+ -+ /* update the duplex mode */ -+ if (duplex != -1) { -+ cmdcfg &= ~CC_HD; -+ cmdcfg |= duplex; -+ } -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) -+ cmdcfg |= (CC_AE | CC_OT | CC_OR); -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2) */ -+ -+ ET_TRACE(("chipduplexupd: updating speed & duplex %x\n", cmdcfg)); -+ -+ /* put mac in reset */ -+ gmac_init_reset(ch); -+ -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+ -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); -+ sdctl &= ~(SC_FORCE_SPD_STRAP_MASK); -+ switch (ch->etc->speed) { -+ case 1000: -+ sdctl |= SC_FORCE_SPD_1G_VAL; -+ break; -+ case 100: -+ sdctl |= SC_FORCE_SPD_100M_VAL; -+ break; -+ default: -+ break; -+ } -+ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); -+#endif /* (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) */ -+} -+ -+#ifdef CONFIG_SERDES_ASYMMETRIC_MODE -+static void -+chipforcespddpx(ch_t *ch) -+{ -+ uint32 cmdcfg; -+ int32 duplex=0, speed; -+ -+ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); -+ -+ /* set duplex */ -+ if (!ch->etc->duplex) -+ duplex = CC_HD; -+ -+ /* set speed */ -+ if (ch->etc->speed == 10) { -+ speed = 0; -+ } else if (ch->etc->speed == 100) { -+ speed = 1; -+ } else { -+ speed = 2; -+ } -+ -+ /* update the speed */ -+ cmdcfg &= ~CC_ES_MASK; -+ cmdcfg |= (speed << CC_ES_SHIFT); -+ -+ /* update the duplex mode */ -+ cmdcfg &= ~CC_HD; -+ cmdcfg |= duplex; -+ -+ ET_TRACE(("chipforcespddpx: forcing speed & duplex %x\n", cmdcfg)); -+ -+ /* put mac in reset */ -+ gmac_init_reset(ch); -+ -+ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); -+ -+ /* bring mac out of reset */ -+ gmac_clear_reset(ch); -+ -+ if (ch->etc->up) { -+ serdes_speeddpx_set(ch->etc->unit, ch->etc->int_phyaddr, ch->etc->speed, ch->etc->duplex); -+ } -+} -+#endif /* CONFIG_SERDES_ASYMMETRIC_MODE */ -+ -+ -+static uint16 -+chipphyrd(ch_t *ch, uint phyaddr, uint reg) -+{ -+ uint16 val = 0; -+ uint32 addr = PHY_REG_ADDR(phyaddr); -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ if (PHY_REG_BUS(phyaddr)) { /* Internal serdes */ -+ val = serdes_rd_reg(ch->etc->unit, addr, reg); -+ } else { -+ phy5461_rd_reg(ch->etc->unit, addr, -+ PHY_REG_FLAGS(phyaddr) ? SOC_PHY_REG_1000X : 0, -+ PHY_REG_BANK(phyaddr), reg, &val); -+ } -+#elif defined(CONFIG_MACH_HR2) -+ phy5221_rd_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#elif defined(CONFIG_MACH_HR3) -+#if defined(CONFIG_MACH_WH2) -+ iproc_mii_read(MII_DEV_LOCAL, addr, reg, &val); -+#else -+ phy5481_rd_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#endif -+#elif defined(CONFIG_MACH_GH) -+ phy5481_rd_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#elif defined(CONFIG_MACH_GH2) -+ phy542xx_rd_reg(addr, PHY_REG_FLAGS(phyaddr), reg, &val); -+#endif /* defined(CONFIG_MACH_GH2) */ -+ -+ return val; -+} -+ -+static void -+chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 val) -+{ -+ uint32 addr = PHY_REG_ADDR(phyaddr); -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ if (PHY_REG_BUS(phyaddr)) { /* Internal serdes */ -+ serdes_wr_reg(ch->etc->unit, addr, reg, val); -+ } else { -+ phy5461_wr_reg(ch->etc->unit, addr, -+ PHY_REG_FLAGS(phyaddr) ? SOC_PHY_REG_1000X : 0, -+ PHY_REG_BANK(phyaddr), reg, &val); -+ } -+#elif defined(CONFIG_MACH_HR2) -+ phy5221_wr_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#elif defined(CONFIG_MACH_HR3) -+#if defined(CONFIG_MACH_WH2) -+ iproc_mii_write(MII_DEV_LOCAL, addr, reg, val); -+#else -+ phy5481_wr_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#endif -+#elif defined(CONFIG_MACH_GH) -+ phy5481_wr_reg(ch->etc->unit, addr, PHY_REG_BANK(phyaddr), reg, &val); -+#elif defined(CONFIG_MACH_GH2) -+ phy542xx_wr_reg(addr, PHY_REG_FLAGS(phyaddr), reg, val); -+#endif /* defined(CONFIG_MACH_GH2) */ -+} -+ -+static void -+chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 val) -+{ -+ uint16 tmp; -+ -+ tmp = chipphyrd(ch, phyaddr, reg); -+ tmp |= val; -+ chipphywr(ch, phyaddr, reg, tmp); -+} -+ -+static void -+chipphyreset(ch_t *ch) -+{ -+ uint ext_phyaddr = ch->etc->phyaddr; -+ uint int_phyaddr = ch->etc->int_phyaddr; -+ -+ ASSERT(ext_phyaddr < MAXEPHY); -+ if (ext_phyaddr == EPHY_NOREG) { -+ return; -+ } -+ -+ ET_TRACE(("et%d: chipphyreset, ext_phyaddr: 0x%x, int_phyaddr: 0x%x\n", -+ ch->etc->unit, ext_phyaddr, int_phyaddr)); -+ -+ chipphywr(ch, ext_phyaddr, 0, CTL_RESET); -+ OSL_DELAY(100); -+ if (chipphyrd(ch, ext_phyaddr, 0) & CTL_RESET) { -+ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); -+ } -+ -+ /* Internal serdes reset */ -+ if (int_phyaddr < MAXEPHY) { -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ serdes_reset(ch->etc->unit, int_phyaddr); -+#elif defined(CONFIG_MACH_GH2) -+ sgmiiplus2_serdes_reset(ch->etc->unit, int_phyaddr); -+#elif defined(CONFIG_MACH_WH2) -+ if (select & 0x04) /* select Serdes (SGMII Plus2) path */ -+ sgmiiplus2_serdes_reset(ch->etc->unit, int_phyaddr); -+#endif -+ } -+ -+ chipphyinit(ch); -+} -+ -+static void -+chipphyinit(ch_t *ch) -+{ -+ uint ext_phyaddr = ch->etc->phyaddr; -+ uint int_phyaddr = ch->etc->int_phyaddr; -+ -+ ASSERT(ext_phyaddr < MAXEPHY); -+ if (ext_phyaddr == EPHY_NOREG) { -+ return; -+ } -+ -+ ET_TRACE(("et%d: chipphyinit, ext_phyaddr: 0x%x, int_phyaddr: 0x%x\n", -+ ch->etc->unit, ext_phyaddr, int_phyaddr)); -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ phy5461_init(ch->etc->unit, ext_phyaddr); -+#elif defined(CONFIG_MACH_HR2) -+ phy5221_init(ch->etc->unit, ext_phyaddr); -+#elif defined(CONFIG_MACH_GH) -+ phy5481_init(ch->etc->unit, ext_phyaddr); -+#elif defined(CONFIG_MACH_HR3) -+ -+#if defined(CONFIG_MACH_WH2) -+ if ((select & 0x04) == 0x0) /* select egphy28 path */ -+ { -+ void __iomem *base; -+ base = of_iomap(of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE), 0); -+ egphy28_init(base, ext_phyaddr); -+ } -+#else -+ phy5481_init(ch->etc->unit, ext_phyaddr); -+#endif -+ -+#elif defined(CONFIG_MACH_GH2) -+ phy542xx_init(ext_phyaddr); -+#endif /* defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) */ -+ -+ /* Internal serdes reset */ -+ if (int_phyaddr < MAXEPHY) { -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ serdes_init(ch->etc->unit, int_phyaddr); -+#elif defined(CONFIG_MACH_GH2) -+ sgmiiplus2_serdes_init(ch->etc->unit, int_phyaddr); -+#elif defined(CONFIG_MACH_WH2) -+ if (select & 0x04) /* select Serdes (SGMII Plus2) path */ -+ { -+ sgmiiplus2_serdes_init(ch->etc->unit, int_phyaddr); -+ } -+#endif -+ } -+} -+ -+static void -+chipphyforce(ch_t *ch, uint phyaddr) -+{ -+ etc_info_t *etc; -+ uint16 ctl; -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ uint16 adv; -+#endif -+ ASSERT(phyaddr < MAXEPHY); -+ -+ if (phyaddr == EPHY_NOREG) { -+ return; -+ } -+ -+ etc = ch->etc; -+ -+ if (etc->forcespeed == ET_AUTO) { -+ return; -+ } -+ -+ ET_TRACE(("et%d: chipphyforce: phyaddr %d speed %d\n", -+ ch->etc->unit, phyaddr, etc->forcespeed)); -+ -+ ctl = chipphyrd(ch, phyaddr, PHY_MII_CTRLr_ADDR); -+ ctl &= ~(CTL_SPEED | CTL_SPEED_MSB | CTL_ANENAB | CTL_DUPLEX); -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ adv = chipphyrd(ch, phyaddr, PHY_MII_GB_CTRLr_ADDR); -+ adv &= ~(ADV_1000FULL | ADV_1000HALF); -+ chipphywr(ch, phyaddr, PHY_MII_GB_CTRLr_ADDR, adv); -+ -+ adv = chipphyrd(ch, phyaddr, PHY_MII_ANAr_ADDR); -+ adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); -+#endif -+ switch (etc->forcespeed) { -+ case ET_10HALF: -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ adv |= ADV_10HALF; -+#endif -+ break; -+ -+ case ET_10FULL: -+ ctl |= CTL_DUPLEX; -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ adv |= ADV_10FULL; -+#endif -+ break; -+ -+ case ET_100HALF: -+ ctl |= CTL_SPEED_100; -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ adv |= ADV_100HALF; -+#endif -+ break; -+ -+ case ET_100FULL: -+ ctl |= (CTL_SPEED_100 | CTL_DUPLEX); -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ adv |= ADV_100FULL; -+#endif -+ break; -+ -+ case ET_1000FULL: -+ ctl |= (CTL_SPEED_1000 | CTL_DUPLEX); -+ break; -+ } -+ -+ chipphywr(ch, phyaddr, PHY_MII_CTRLr_ADDR, ctl); -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+ chipphywr(ch, phyaddr, PHY_MII_ANAr_ADDR, adv); -+ if (etc->forcespeed != ET_1000FULL) { -+#if defined(CONFIG_MACH_GH2) -+ phy542xx_force_auto_mdix(phyaddr, 0); -+#else -+ adv = chipphyrd(ch, phyaddr | (PHY_MII_MISC_CTRLr_BANK << 8), PHY_MII_MISC_CTRLr_ADDR); -+ adv |= MII_FORCED_AUTO_MDIX; -+ chipphywr(ch, phyaddr | (PHY_MII_MISC_CTRLr_BANK << 8), PHY_MII_MISC_CTRLr_ADDR, adv); -+#endif /* defined(CONFIG_MACH_GH2) */ -+ } -+#endif -+} -+ -+/* set selected capability bits in autonegotiation advertisement */ -+static void -+chipphyadvertise(ch_t *ch, uint phyaddr) -+{ -+ etc_info_t *etc; -+ uint16 adv, adv2; -+ -+ ASSERT(phyaddr < MAXEPHY); -+ -+ if (phyaddr == EPHY_NOREG) { -+ return; -+ } -+ -+ etc = ch->etc; -+ -+ if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg) { -+ return; -+ } -+ -+ ASSERT(etc->advertise); -+ -+ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d advertise %x\n", -+ ch->etc->unit, phyaddr, etc->advertise)); -+ -+ /* reset our advertised capabilitity bits */ -+ adv = chipphyrd(ch, phyaddr, PHY_MII_ANAr_ADDR); -+ adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); -+ adv |= (etc->advertise | ADV_PAUSE); -+ chipphywr(ch, phyaddr, PHY_MII_ANAr_ADDR, adv); -+ -+ adv2 = chipphyrd(ch, phyaddr, PHY_MII_GB_CTRLr_ADDR); -+ adv2 &= ~(ADV_1000FULL | ADV_1000HALF); -+ adv2 |= etc->advertise2; -+ chipphywr(ch, phyaddr, PHY_MII_GB_CTRLr_ADDR, adv2); -+ -+ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d adv %x adv2 %x phyad0 %x\n", -+ ch->etc->unit, phyaddr, adv, adv2, chipphyrd(ch, phyaddr, 0))); -+#ifdef CONFIG_FORCED_MODE_AUTO_MDIX -+#if defined(CONFIG_MACH_GH2) -+ phy542xx_force_auto_mdix(phyaddr, 0); -+#else -+ adv = chipphyrd(ch, phyaddr | (PHY_MII_MISC_CTRLr_BANK << 8), PHY_MII_MISC_CTRLr_ADDR); -+ if (adv & MII_FORCED_AUTO_MDIX) { -+ adv &= ~MII_FORCED_AUTO_MDIX; -+ chipphywr(ch, phyaddr | (PHY_MII_MISC_CTRLr_BANK << 8), PHY_MII_MISC_CTRLr_ADDR, adv); -+ } -+#endif /* defined(CONFIG_MACH_GH2) */ -+#endif -+ /* restart autonegotiation */ -+ chipphyor(ch, phyaddr, PHY_MII_CTRLr_ADDR, CTL_RESTART); -+ etc->needautoneg = FALSE; -+} -+ -+static void -+chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable) -+{ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2)) -+ phy5461_enable_set(eth_num, phyaddr, enable); -+#elif defined(CONFIG_MACH_HR2) -+ phy5221_enable_set(eth_num, phyaddr, enable); -+#elif defined(CONFIG_MACH_GH) -+ phy5481_enable_set(eth_num, phyaddr, enable); -+#elif defined(CONFIG_MACH_HR3) -+#if defined(CONFIG_MACH_WH2) -+ if ((select & 0x04) == 0x0) /* Select EGPHY28 path */ -+ egphy28_enable_set(phyaddr, enable); -+#else -+ phy5481_enable_set(eth_num, phyaddr, enable); -+#endif -+#elif defined(CONFIG_MACH_GH2) -+ phy542xx_enable_set(phyaddr, enable); -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2) */ -+} -+ -+#ifdef GMAC_RATE_LIMITING -+void -+etc_check_rate_limiting(etc_info_t *etc, void *pch) -+{ -+ /*ch_t *ch = (ch_t*)pch;*/ -+ uint32 timediff, unit; -+ int bc_cnt_diff; -+ static uint32 first_run[2]={1,1}; -+ static uint32 prev_bc_frame_cnt[2]={0,0}, bc_frame_cnt[2]={0,0}; -+ -+ unit = etc->unit; -+ if (first_run[unit]) { -+ bc_frame_cnt[unit] = etc->rx_bc_frame_cnt; -+ prev_bc_frame_cnt[unit] = bc_frame_cnt[unit]; -+ first_run[unit] = 0; -+ } -+ else { -+ bc_cnt_diff = etc->rx_bc_frame_cnt - prev_bc_frame_cnt[unit]; -+ if (bc_cnt_diff >= 0) -+ bc_frame_cnt[unit] += bc_cnt_diff; -+ else -+ bc_frame_cnt[unit] += (bc_cnt_diff + 0xffffffff + 0x1); -+ prev_bc_frame_cnt[unit] = etc->rx_bc_frame_cnt; -+ } -+ -+ timediff = ((long)jiffies - (long)(etc->rl_prior_jiffies)); -+ if ((timediff >> 5) != 0) { -+ /* -+ * 32 or more jiffies have gone by, See if -+ * we're seeing too many broadcast packets. -+ */ -+ if ((timediff >> 5) == 1) { -+ /* 32-63 jiffies elapsed */ -+ if (((bc_frame_cnt[unit] >> 10) != 0) && -+ !(etc->rl_stopping_broadcasts)) { -+ /* 1K or more broadcast packets have arrived in -+ * 32-63 jiffies; try to throttle back the -+ * incoming packets -+ */ -+ etc->rl_stopping_broadcasts = 1; -+ printk("et%d: %s: stopping broadcasts bc_frame_cnts(0x%x)\n", -+ etc->unit, __FUNCTION__, bc_frame_cnt[unit]); -+ if (!timer_pending(&etc->rl_timer)) { -+ etc->rl_timer.expires = jiffies + HZ; -+ add_timer(&etc->rl_timer); -+ etc->rl_set=TRUE; -+ } -+ } -+ } -+ etc->rl_prior_jiffies = jiffies; -+ bc_frame_cnt[unit] = 0; -+ } -+} -+#endif /* GMAC_RATE_LIMITING */ -+ -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.h b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.h ---- a/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/et/sys/etcgmac.h 2017-11-09 17:53:43.905290000 +0800 -@@ -0,0 +1,65 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Broadcom Gigabit Ethernet MAC defines. -+ * -+ * $Id: etcgmac.h 267700 2011-06-19 15:41:07Z sudhirbs $ -+ */ -+ -+#ifndef _ETCGMAC_H_ -+#define _ETCGMAC_H_ -+ -+#if (defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+#define IPROC_NUM_GMACS 1 -+#else -+#define IPROC_NUM_GMACS 2 -+#endif -+ -+/* chip interrupt bit error summary */ -+#define I_ERRORS (I_PDEE | I_PDE | I_DE | I_RDU | I_RFO | I_XFU) -+#define DEF_INTMASK (I_XI0 | I_XI1 | I_XI2 | I_XI3 | I_RI | I_ERRORS) -+ -+#define GMAC_RESET_DELAY 2 -+ -+#define GMAC_MIN_FRAMESIZE 17 /* gmac can only send frames of -+ * size above 17 octetes. -+ */ -+ -+#define LOOPBACK_MODE_DMA 0 /* loopback the packet at the DMA engine */ -+#define LOOPBACK_MODE_MAC 1 /* loopback the packet at MAC */ -+#define LOOPBACK_MODE_NONE 2 /* no Loopback */ -+ -+#define FA2_GMAC_MAX_LEN 2048 -+ -+#define DMAREG(ch, dir, qnum) ((dir == DMA_TX) ? \ -+ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmaxmt) : \ -+ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmarcv)) -+ -+/* -+ * Add multicast address to the list. Multicast address are maintained as -+ * hash table with chaining. -+ */ -+typedef struct mclist { -+ struct ether_addr mc_addr; /* multicast address to allow */ -+ struct mclist *next; /* next entry */ -+} mflist_t; -+ -+#define GMAC_HASHT_SIZE 16 /* hash table size */ -+#define GMAC_MCADDR_HASH(m) ((((uint8 *)(m))[3] + ((uint8 *)(m))[4] + \ -+ ((uint8 *)(m))[5]) & (GMAC_HASHT_SIZE - 1)) -+ -+#define ETHER_MCADDR_CMP(x, y) ((((uint16 *)(x))[0] ^ ((uint16 *)(y))[0]) | \ -+ (((uint16 *)(x))[1] ^ ((uint16 *)(y))[1]) | \ -+ (((uint16 *)(x))[2] ^ ((uint16 *)(y))[2])) -+ -+#define SUCCESS 0 -+#define FAILURE -1 -+ -+typedef struct mcfilter { -+ /* hash table for multicast filtering */ -+ mflist_t *bucket[GMAC_HASHT_SIZE]; -+} mcfilter_t; -+ -+extern uint32 find_priq(uint32 pri_map); -+ -+#endif /* _ETCGMAC_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/Makefile b/drivers/net/ethernet/broadcom/gmac/src/include/Makefile ---- a/drivers/net/ethernet/broadcom/gmac/src/include/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/Makefile 2017-11-09 17:53:43.912294000 +0800 -@@ -0,0 +1,62 @@ -+# This script serves following purpose: -+# -+# 1. It generates native version information by querying -+# automerger maintained database to see where src/include -+# came from -+# 2. For select components, as listed in compvers.sh -+# it generates component version files -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+# -+ -+SRCBASE := .. -+ -+TARGETS := epivers.h -+ -+ifdef VERBOSE -+export VERBOSE -+endif -+ -+all release: epivers compvers -+ -+# Generate epivers.h for native branch version -+epivers: -+ bash epivers.sh -+ -+# Generate epivers.h for native branch version -+compvers: -+ @if [ -s "compvers.sh" ]; then \ -+ echo "Generating component versions, if any"; \ -+ bash compvers.sh; \ -+ else \ -+ echo "Skipping component version generation"; \ -+ fi -+ -+# Generate epivers.h for native branch version -+clean_compvers: -+ @if [ -s "compvers.sh" ]; then \ -+ echo "bash compvers.sh clean"; \ -+ bash compvers.sh clean; \ -+ else \ -+ echo "Skipping component version clean"; \ -+ fi -+ -+clean: -+ rm -f $(TARGETS) *.prev -+ -+clean_all: clean clean_compvers -+ -+.PHONY: all release clean epivers compvers clean_compvers -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/aidmp.h b/drivers/net/ethernet/broadcom/gmac/src/include/aidmp.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/aidmp.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/aidmp.h 2017-11-09 17:53:43.913291000 +0800 -@@ -0,0 +1,383 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom AMBA Interconnect definitions. -+ * -+ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _AIDMP_H -+#define _AIDMP_H -+ -+/* Manufacturer Ids */ -+#define MFGID_ARM 0x43b -+#define MFGID_BRCM 0x4bf -+#define MFGID_MIPS 0x4a7 -+ -+/* Component Classes */ -+#define CC_SIM 0 -+#define CC_EROM 1 -+#define CC_CORESIGHT 9 -+#define CC_VERIF 0xb -+#define CC_OPTIMO 0xd -+#define CC_GEN 0xe -+#define CC_PRIMECELL 0xf -+ -+/* Enumeration ROM registers */ -+#define ER_EROMENTRY 0x000 -+#define ER_REMAPCONTROL 0xe00 -+#define ER_REMAPSELECT 0xe04 -+#define ER_MASTERSELECT 0xe10 -+#define ER_ITCR 0xf00 -+#define ER_ITIP 0xf04 -+ -+/* Erom entries */ -+#define ER_TAG 0xe -+#define ER_TAG1 0x6 -+#define ER_VALID 1 -+#define ER_CI 0 -+#define ER_MP 2 -+#define ER_ADD 4 -+#define ER_END 0xe -+#define ER_BAD 0xffffffff -+ -+/* EROM CompIdentA */ -+#define CIA_MFG_MASK 0xfff00000 -+#define CIA_MFG_SHIFT 20 -+#define CIA_CID_MASK 0x000fff00 -+#define CIA_CID_SHIFT 8 -+#define CIA_CCL_MASK 0x000000f0 -+#define CIA_CCL_SHIFT 4 -+ -+/* EROM CompIdentB */ -+#define CIB_REV_MASK 0xff000000 -+#define CIB_REV_SHIFT 24 -+#define CIB_NSW_MASK 0x00f80000 -+#define CIB_NSW_SHIFT 19 -+#define CIB_NMW_MASK 0x0007c000 -+#define CIB_NMW_SHIFT 14 -+#define CIB_NSP_MASK 0x00003e00 -+#define CIB_NSP_SHIFT 9 -+#define CIB_NMP_MASK 0x000001f0 -+#define CIB_NMP_SHIFT 4 -+ -+/* EROM MasterPortDesc */ -+#define MPD_MUI_MASK 0x0000ff00 -+#define MPD_MUI_SHIFT 8 -+#define MPD_MP_MASK 0x000000f0 -+#define MPD_MP_SHIFT 4 -+ -+/* EROM AddrDesc */ -+#define AD_ADDR_MASK 0xfffff000 -+#define AD_SP_MASK 0x00000f00 -+#define AD_SP_SHIFT 8 -+#define AD_ST_MASK 0x000000c0 -+#define AD_ST_SHIFT 6 -+#define AD_ST_SLAVE 0x00000000 -+#define AD_ST_BRIDGE 0x00000040 -+#define AD_ST_SWRAP 0x00000080 -+#define AD_ST_MWRAP 0x000000c0 -+#define AD_SZ_MASK 0x00000030 -+#define AD_SZ_SHIFT 4 -+#define AD_SZ_4K 0x00000000 -+#define AD_SZ_8K 0x00000010 -+#define AD_SZ_16K 0x00000020 -+#define AD_SZ_SZD 0x00000030 -+#define AD_AG32 0x00000008 -+#define AD_ADDR_ALIGN 0x00000fff -+#define AD_SZ_BASE 0x00001000 /* 4KB */ -+ -+/* EROM SizeDesc */ -+#define SD_SZ_MASK 0xfffff000 -+#define SD_SG32 0x00000008 -+#define SD_SZ_ALIGN 0x00000fff -+ -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+typedef volatile struct _aidmp { -+ uint32 oobselina30; /* 0x000 */ -+ uint32 oobselina74; /* 0x004 */ -+ uint32 PAD[6]; -+ uint32 oobselinb30; /* 0x020 */ -+ uint32 oobselinb74; /* 0x024 */ -+ uint32 PAD[6]; -+ uint32 oobselinc30; /* 0x040 */ -+ uint32 oobselinc74; /* 0x044 */ -+ uint32 PAD[6]; -+ uint32 oobselind30; /* 0x060 */ -+ uint32 oobselind74; /* 0x064 */ -+ uint32 PAD[38]; -+ uint32 oobselouta30; /* 0x100 */ -+ uint32 oobselouta74; /* 0x104 */ -+ uint32 PAD[6]; -+ uint32 oobseloutb30; /* 0x120 */ -+ uint32 oobseloutb74; /* 0x124 */ -+ uint32 PAD[6]; -+ uint32 oobseloutc30; /* 0x140 */ -+ uint32 oobseloutc74; /* 0x144 */ -+ uint32 PAD[6]; -+ uint32 oobseloutd30; /* 0x160 */ -+ uint32 oobseloutd74; /* 0x164 */ -+ uint32 PAD[38]; -+ uint32 oobsynca; /* 0x200 */ -+ uint32 oobseloutaen; /* 0x204 */ -+ uint32 PAD[6]; -+ uint32 oobsyncb; /* 0x220 */ -+ uint32 oobseloutben; /* 0x224 */ -+ uint32 PAD[6]; -+ uint32 oobsyncc; /* 0x240 */ -+ uint32 oobseloutcen; /* 0x244 */ -+ uint32 PAD[6]; -+ uint32 oobsyncd; /* 0x260 */ -+ uint32 oobseloutden; /* 0x264 */ -+ uint32 PAD[38]; -+ uint32 oobaextwidth; /* 0x300 */ -+ uint32 oobainwidth; /* 0x304 */ -+ uint32 oobaoutwidth; /* 0x308 */ -+ uint32 PAD[5]; -+ uint32 oobbextwidth; /* 0x320 */ -+ uint32 oobbinwidth; /* 0x324 */ -+ uint32 oobboutwidth; /* 0x328 */ -+ uint32 PAD[5]; -+ uint32 oobcextwidth; /* 0x340 */ -+ uint32 oobcinwidth; /* 0x344 */ -+ uint32 oobcoutwidth; /* 0x348 */ -+ uint32 PAD[5]; -+ uint32 oobdextwidth; /* 0x360 */ -+ uint32 oobdinwidth; /* 0x364 */ -+ uint32 oobdoutwidth; /* 0x368 */ -+ uint32 PAD[37]; -+ uint32 ioctrlset; /* 0x400 */ -+ uint32 ioctrlclear; /* 0x404 */ -+ uint32 ioctrl; /* 0x408 */ -+ uint32 PAD[61]; -+ uint32 iostatus; /* 0x500 */ -+ uint32 PAD[127]; -+ uint32 ioctrlwidth; /* 0x700 */ -+ uint32 iostatuswidth; /* 0x704 */ -+ uint32 PAD[62]; -+ uint32 resetctrl; /* 0x800 */ -+ uint32 resetstatus; /* 0x804 */ -+ uint32 resetreadid; /* 0x808 */ -+ uint32 resetwriteid; /* 0x80c */ -+ uint32 PAD[60]; -+ uint32 errlogctrl; /* 0x900 */ -+ uint32 errlogdone; /* 0x904 */ -+ uint32 errlogstatus; /* 0x908 */ -+ uint32 errlogaddrlo; /* 0x90c */ -+ uint32 errlogaddrhi; /* 0x910 */ -+ uint32 errlogid; /* 0x914 */ -+ uint32 errloguser; /* 0x918 */ -+ uint32 errlogflags; /* 0x91c */ -+ uint32 PAD[56]; -+ uint32 intstatus; /* 0xa00 */ -+ uint32 PAD[255]; -+ uint32 config; /* 0xe00 */ -+ uint32 PAD[63]; -+ uint32 itcr; /* 0xf00 */ -+ uint32 PAD[3]; -+ uint32 itipooba; /* 0xf10 */ -+ uint32 itipoobb; /* 0xf14 */ -+ uint32 itipoobc; /* 0xf18 */ -+ uint32 itipoobd; /* 0xf1c */ -+ uint32 PAD[4]; -+ uint32 itipoobaout; /* 0xf30 */ -+ uint32 itipoobbout; /* 0xf34 */ -+ uint32 itipoobcout; /* 0xf38 */ -+ uint32 itipoobdout; /* 0xf3c */ -+ uint32 PAD[4]; -+ uint32 itopooba; /* 0xf50 */ -+ uint32 itopoobb; /* 0xf54 */ -+ uint32 itopoobc; /* 0xf58 */ -+ uint32 itopoobd; /* 0xf5c */ -+ uint32 PAD[4]; -+ uint32 itopoobain; /* 0xf70 */ -+ uint32 itopoobbin; /* 0xf74 */ -+ uint32 itopoobcin; /* 0xf78 */ -+ uint32 itopoobdin; /* 0xf7c */ -+ uint32 PAD[4]; -+ uint32 itopreset; /* 0xf90 */ -+ uint32 PAD[15]; -+ uint32 peripherialid4; /* 0xfd0 */ -+ uint32 peripherialid5; /* 0xfd4 */ -+ uint32 peripherialid6; /* 0xfd8 */ -+ uint32 peripherialid7; /* 0xfdc */ -+ uint32 peripherialid0; /* 0xfe0 */ -+ uint32 peripherialid1; /* 0xfe4 */ -+ uint32 peripherialid2; /* 0xfe8 */ -+ uint32 peripherialid3; /* 0xfec */ -+ uint32 componentid0; /* 0xff0 */ -+ uint32 componentid1; /* 0xff4 */ -+ uint32 componentid2; /* 0xff8 */ -+ uint32 componentid3; /* 0xffc */ -+} aidmp_t; -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+/* Out-of-band Router registers */ -+#define OOB_BUSCONFIG 0x020 -+#define OOB_STATUSA 0x100 -+#define OOB_STATUSB 0x104 -+#define OOB_STATUSC 0x108 -+#define OOB_STATUSD 0x10c -+#define OOB_ENABLEA0 0x200 -+#define OOB_ENABLEA1 0x204 -+#define OOB_ENABLEA2 0x208 -+#define OOB_ENABLEA3 0x20c -+#define OOB_ENABLEB0 0x280 -+#define OOB_ENABLEB1 0x284 -+#define OOB_ENABLEB2 0x288 -+#define OOB_ENABLEB3 0x28c -+#define OOB_ENABLEC0 0x300 -+#define OOB_ENABLEC1 0x304 -+#define OOB_ENABLEC2 0x308 -+#define OOB_ENABLEC3 0x30c -+#define OOB_ENABLED0 0x380 -+#define OOB_ENABLED1 0x384 -+#define OOB_ENABLED2 0x388 -+#define OOB_ENABLED3 0x38c -+#define OOB_ITCR 0xf00 -+#define OOB_ITIPOOBA 0xf10 -+#define OOB_ITIPOOBB 0xf14 -+#define OOB_ITIPOOBC 0xf18 -+#define OOB_ITIPOOBD 0xf1c -+#define OOB_ITOPOOBA 0xf30 -+#define OOB_ITOPOOBB 0xf34 -+#define OOB_ITOPOOBC 0xf38 -+#define OOB_ITOPOOBD 0xf3c -+ -+/* DMP wrapper registers */ -+#define AI_OOBSELINA30 0x000 -+#define AI_OOBSELINA74 0x004 -+#define AI_OOBSELINB30 0x020 -+#define AI_OOBSELINB74 0x024 -+#define AI_OOBSELINC30 0x040 -+#define AI_OOBSELINC74 0x044 -+#define AI_OOBSELIND30 0x060 -+#define AI_OOBSELIND74 0x064 -+#define AI_OOBSELOUTA30 0x100 -+#define AI_OOBSELOUTA74 0x104 -+#define AI_OOBSELOUTB30 0x120 -+#define AI_OOBSELOUTB74 0x124 -+#define AI_OOBSELOUTC30 0x140 -+#define AI_OOBSELOUTC74 0x144 -+#define AI_OOBSELOUTD30 0x160 -+#define AI_OOBSELOUTD74 0x164 -+#define AI_OOBSYNCA 0x200 -+#define AI_OOBSELOUTAEN 0x204 -+#define AI_OOBSYNCB 0x220 -+#define AI_OOBSELOUTBEN 0x224 -+#define AI_OOBSYNCC 0x240 -+#define AI_OOBSELOUTCEN 0x244 -+#define AI_OOBSYNCD 0x260 -+#define AI_OOBSELOUTDEN 0x264 -+#define AI_OOBAEXTWIDTH 0x300 -+#define AI_OOBAINWIDTH 0x304 -+#define AI_OOBAOUTWIDTH 0x308 -+#define AI_OOBBEXTWIDTH 0x320 -+#define AI_OOBBINWIDTH 0x324 -+#define AI_OOBBOUTWIDTH 0x328 -+#define AI_OOBCEXTWIDTH 0x340 -+#define AI_OOBCINWIDTH 0x344 -+#define AI_OOBCOUTWIDTH 0x348 -+#define AI_OOBDEXTWIDTH 0x360 -+#define AI_OOBDINWIDTH 0x364 -+#define AI_OOBDOUTWIDTH 0x368 -+ -+#if defined(IL_BIGENDIAN) && defined(BCMHND74K) -+/* Selective swapped defines for those registers we need in -+ * big-endian code. -+ */ -+#define AI_IOCTRLSET 0x404 -+#define AI_IOCTRLCLEAR 0x400 -+#define AI_IOCTRL 0x40c -+#define AI_IOSTATUS 0x504 -+#define AI_RESETCTRL 0x804 -+#define AI_RESETSTATUS 0x800 -+ -+#else /* !IL_BIGENDIAN || !BCMHND74K */ -+ -+#define AI_IOCTRLSET 0x400 -+#define AI_IOCTRLCLEAR 0x404 -+#define AI_IOCTRL 0x408 -+#define AI_IOSTATUS 0x500 -+#define AI_RESETCTRL 0x800 -+#define AI_RESETSTATUS 0x804 -+ -+#endif /* IL_BIGENDIAN && BCMHND74K */ -+ -+#define AI_IOCTRLWIDTH 0x700 -+#define AI_IOSTATUSWIDTH 0x704 -+ -+#define AI_RESETREADID 0x808 -+#define AI_RESETWRITEID 0x80c -+#define AI_ERRLOGCTRL 0xa00 -+#define AI_ERRLOGDONE 0xa04 -+#define AI_ERRLOGSTATUS 0xa08 -+#define AI_ERRLOGADDRLO 0xa0c -+#define AI_ERRLOGADDRHI 0xa10 -+#define AI_ERRLOGID 0xa14 -+#define AI_ERRLOGUSER 0xa18 -+#define AI_ERRLOGFLAGS 0xa1c -+#define AI_INTSTATUS 0xa00 -+#define AI_CONFIG 0xe00 -+#define AI_ITCR 0xf00 -+#define AI_ITIPOOBA 0xf10 -+#define AI_ITIPOOBB 0xf14 -+#define AI_ITIPOOBC 0xf18 -+#define AI_ITIPOOBD 0xf1c -+#define AI_ITIPOOBAOUT 0xf30 -+#define AI_ITIPOOBBOUT 0xf34 -+#define AI_ITIPOOBCOUT 0xf38 -+#define AI_ITIPOOBDOUT 0xf3c -+#define AI_ITOPOOBA 0xf50 -+#define AI_ITOPOOBB 0xf54 -+#define AI_ITOPOOBC 0xf58 -+#define AI_ITOPOOBD 0xf5c -+#define AI_ITOPOOBAIN 0xf70 -+#define AI_ITOPOOBBIN 0xf74 -+#define AI_ITOPOOBCIN 0xf78 -+#define AI_ITOPOOBDIN 0xf7c -+#define AI_ITOPRESET 0xf90 -+#define AI_PERIPHERIALID4 0xfd0 -+#define AI_PERIPHERIALID5 0xfd4 -+#define AI_PERIPHERIALID6 0xfd8 -+#define AI_PERIPHERIALID7 0xfdc -+#define AI_PERIPHERIALID0 0xfe0 -+#define AI_PERIPHERIALID1 0xfe4 -+#define AI_PERIPHERIALID2 0xfe8 -+#define AI_PERIPHERIALID3 0xfec -+#define AI_COMPONENTID0 0xff0 -+#define AI_COMPONENTID1 0xff4 -+#define AI_COMPONENTID2 0xff8 -+#define AI_COMPONENTID3 0xffc -+ -+/* resetctrl */ -+#define AIRC_RESET 1 -+ -+/* config */ -+#define AICFG_OOB 0x00000020 -+#define AICFG_IOS 0x00000010 -+#define AICFG_IOC 0x00000008 -+#define AICFG_TO 0x00000004 -+#define AICFG_ERRL 0x00000002 -+#define AICFG_RST 0x00000001 -+ -+/* bit defines for AI_OOBSELOUTB74 reg */ -+#define OOB_SEL_OUTEN_B_5 15 -+#define OOB_SEL_OUTEN_B_6 23 -+ -+#endif /* _AIDMP_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/arminc.h b/drivers/net/ethernet/broadcom/gmac/src/include/arminc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/arminc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/arminc.h 2017-11-09 17:53:43.914306000 +0800 -@@ -0,0 +1,317 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * HND Run Time Environment for standalone ARM programs. -+ * -+ * $Id: arminc.h 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#ifndef _ARMINC_H -+#define _ARMINC_H -+ -+ -+/* ARM defines */ -+ -+#ifdef _LANGUAGE_ASSEMBLY -+ -+/* -+ * LEAF - declare leaf routine -+ */ -+#define LEAF(function) \ -+ .section .text.function, "ax"; \ -+ .global function; \ -+ .func function; \ -+function: -+ -+#define THUMBLEAF(function) \ -+ .section .text.function, "ax"; \ -+ .global function; \ -+ .func function; \ -+ .thumb; \ -+ .thumb_func; \ -+function: -+ -+/* -+ * END - mark end of function -+ */ -+#define END(function) \ -+ .ltorg; \ -+ .endfunc; \ -+ .size function, . - function -+ -+#define DW(var, val) \ -+ .global var; \ -+ .type var, %object; \ -+ .size var, 4; \ -+ .align 2; \ -+var: .word val -+ -+ -+#define _ULCAST_ -+ -+#else -+ -+/* -+ * The following macros are especially useful for __asm__ -+ * inline assembler. -+ */ -+#ifndef __STR -+#define __STR(x) #x -+#endif -+#ifndef STR -+#define STR(x) __STR(x) -+#endif -+ -+#define _ULCAST_ (unsigned long) -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+ -+#if defined(__ARM_ARCH_7M__) /* Cortex-M3 */ -+ -+/* Data Watchpoint and Trigger */ -+#define CM3_DWT_CTRL 0xe0001000 -+#define CM3_DWT_CYCCNT 0xe0001004 -+#define CM3_DWT_CPICNT 0xe0001008 -+#define CM3_DWT_EXCCNT 0xe000100c -+#define CM3_DWT_SLEEPCNT 0xe0001010 -+#define CM3_DWT_LSUCNT 0xe0001014 -+#define CM3_DWT_FOLDCNT 0xe0001018 -+#define CM3_DWT_COMP0 0xe0001020 -+#define CM3_DWT_MASK0 0xe0001024 -+#define CM3_DWT_FUNCTION0 0xe0001028 -+#define CM3_DWT_COMP1 0xe0001030 -+#define CM3_DWT_MASK1 0xe0001034 -+#define CM3_DWT_FUNCTION1 0xe0001038 -+#define CM3_DWT_COMP2 0xe0001040 -+#define CM3_DWT_MASK2 0xe0001044 -+#define CM3_DWT_FUNCTION2 0xe0001048 -+#define CM3_DWT_COMP3 0xe0001050 -+#define CM3_DWT_MASK3 0xe0001054 -+#define CM3_DWT_FUNCTION3 0xe0001058 -+ -+#define CM3_DWT_FUNCTION_DISAB 0 -+#define CM3_DWT_FUNCTION_WP_PCMATCH 4 -+#define CM3_DWT_FUNCTION_WP_READ 5 -+#define CM3_DWT_FUNCTION_WP_WRITE 6 -+#define CM3_DWT_FUNCTION_WP_RDWR 7 -+ -+#define CM3_NVIC_IC_TYPE 0xe000e004 /* Interrupt Control Type Reg */ -+#define CM3_NVIC_TICK_CSR 0xe000e010 /* SysTick Control and Status Reg */ -+#define CM3_NVIC_TICK_CSR_COUNTFLAG 0x10000 -+#define CM3_NVIC_TICK_CSR_CLKSOURCE 0x4 /* Set for core clock, 0 for ext ref */ -+#define CM3_NVIC_TICK_CSR_TICKINT 0x2 /* Set for intr on count going 1 => 0 */ -+#define CM3_NVIC_TICK_CSR_ENABLE 0x1 -+#define CM3_NVIC_TICK_RLDVAL 0xe000e014 /* SysTick Reload Value Reg */ -+#define CM3_NVIC_TICK_CURVAL 0xe000e018 /* SysTick Current Value Reg */ -+#define CM3_NVIC_TICK_CALVAL 0xe000e01c /* SysTick Calibration Value Reg */ -+ -+/* Interrupt enable/disable register */ -+#define CM3_NVIC_IRQ_SET_EN0 0xe000e100 /* Irq 0 to 31 Set Enable Reg */ -+#define CM3_NVIC_IRQ_SET_EN(n) (0xe000e100 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+#define CM3_NVIC_IRQ_CLR_EN0 0xe000e180 /* Irq 0 to 31 Clear Enable Reg [...] */ -+#define CM3_NVIC_IRQ_CLR_EN(n) (0xe000e180 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+#define CM3_NVIC_IRQ_SET_PND0 0xe000e200 /* Irq 0 to 31 Set Pending Reg [...] */ -+#define CM3_NVIC_IRQ_SET_PND(n) (0xe000e200 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+#define CM3_NVIC_IRQ_CLR_PND0 0xe000e280 /* Irq 0 to 31 Clear Pending Reg [...] */ -+#define CM3_NVIC_IRQ_CLR_PND(n) (0xe000e280 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+#define CM3_NVIC_IRQ_ACT_BIT0 0xe000e300 /* Irq 0 to 31 Active Bit Reg [...] */ -+#define CM3_NVIC_IRQ_ACT_BIT(n) (0xe000e300 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+#define CM3_NVIC_IRQ_PRIO0 0xe000e400 /* Irq 0 to 31 Priority Reg [...] */ -+#define CM3_NVIC_IRQ_PRIO(n) (0xe000e400 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ -+ -+/* CPU control */ -+#define CM3_CPUID 0xe000ed00 -+#define CM3_INTCTLSTATE 0xe000ed04 -+#define CM3_VTOFF 0xe000ed08 /* Vector Table Offset */ -+#define CM3_SYSCTRL 0xe000ed10 -+#define CM3_CFGCTRL 0xe000ed14 -+#define CM3_CFGCTRL_UNALIGN_TRP 0x8 -+#define CM3_CFGCTRL_DIV_0_TRP 0x10 -+#define CM3_CFGCTRL_STKALIGN 0x200 -+ -+#define CM3_PFR0 0xe000ed40 -+#define CM3_PFR1 0xe000ed44 -+#define CM3_DFR0 0xe000ed48 -+#define CM3_AFR0 0xe000ed4c -+#define CM3_MMFR0 0xe000ed50 -+#define CM3_MMFR1 0xe000ed54 -+#define CM3_MMFR2 0xe000ed58 -+#define CM3_MMFR3 0xe000ed5c -+#define CM3_ISAR0 0xe000ed60 -+#define CM3_ISAR1 0xe000ed64 -+#define CM3_ISAR2 0xe000ed68 -+#define CM3_ISAR3 0xe000ed6c -+#define CM3_ISAR4 0xe000ed70 -+#define CM3_ISAR5 0xe000ed74 -+ -+#define CM3_MPUTYPE 0xe000ed90 -+#define CM3_MPUCTRL 0xe000ed94 -+#define CM3_REGNUM 0xe000ed98 -+#define CM3_REGBAR 0xe000ed9c -+#define CM3_REGASZ 0xe000eda0 -+#define CM3_AL1BAR 0xe000eda4 -+#define CM3_AL1ASZ 0xe000eda8 -+#define CM3_AL2BAR 0xe000edac -+#define CM3_AL2ASZ 0xe000edb0 -+#define CM3_AL3BAR 0xe000edb4 -+#define CM3_AL3ASZ 0xe000edb8 -+ -+#define CM3_DBG_HCSR 0xe000edf0 /* Debug Halting Control and Status Reg */ -+#define CM3_DBG_CRSR 0xe000edf4 /* Debug Core Register Selector Reg */ -+#define CM3_DBG_CRDR 0xe000edf8 /* Debug Core Register Data Reg */ -+#define CM3_DBG_EMCR 0xe000edfc /* Debug Exception and Monitor Control Reg */ -+#define CM3_DBG_EMCR_TRCENA (1U << 24) -+#define CM3_DBG_EMCR_MON_EN (1U << 16) -+ -+/* Trap types */ -+#define TR_RST 1 /* Reset */ -+#define TR_NMI 2 /* NMI */ -+#define TR_FAULT 3 /* Hard Fault */ -+#define TR_MM 4 /* Memory Management */ -+#define TR_BUS 5 /* Bus Fault */ -+#define TR_USAGE 6 /* Usage Fault */ -+#define TR_SVC 11 /* SVCall */ -+#define TR_DMON 12 /* Debug Monitor */ -+#define TR_PENDSV 14 /* PendSV */ -+#define TR_SYSTICK 15 /* SysTick */ -+#define TR_ISR 16 /* External Interrupts start here */ -+ -+#define TR_BAD 256 /* Bad trap: Not used by CM3 */ -+ -+/* Offsets of automatically saved registers from sp upon trap */ -+#define CM3_TROFF_R0 0 -+#define CM3_TROFF_R1 4 -+#define CM3_TROFF_R2 8 -+#define CM3_TROFF_R3 12 -+#define CM3_TROFF_R12 16 -+#define CM3_TROFF_LR 20 -+#define CM3_TROFF_PC 24 -+#define CM3_TROFF_xPSR 28 -+ -+#elif defined(__ARM_ARCH_7A__) /* Cortex-A9 */ -+/* Fields in cpsr */ -+#define PS_USR 0x00000010 /* Mode: User */ -+#define PS_FIQ 0x00000011 /* Mode: FIQ */ -+#define PS_IRQ 0x00000012 /* Mode: IRQ */ -+#define PS_SVC 0x00000013 /* Mode: Supervisor */ -+#define PS_ABT 0x00000017 /* Mode: Abort */ -+#define PS_UND 0x0000001b /* Mode: Undefined */ -+#define PS_SYS 0x0000001f /* Mode: System */ -+#define PS_MM 0x0000001f /* Mode bits mask */ -+#define PS_T 0x00000020 /* Thumb mode */ -+#define PS_F 0x00000040 /* FIQ disable */ -+#define PS_I 0x00000080 /* IRQ disable */ -+#define PS_A 0x00000100 /* Imprecise abort */ -+#define PS_E 0x00000200 /* Endianess */ -+#define PS_IT72 0x0000fc00 /* IT[7:2] */ -+#define PS_GE 0x000f0000 /* IT[7:2] */ -+#define PS_J 0x01000000 /* Java state */ -+#define PS_IT10 0x06000000 /* IT[1:0] */ -+#define PS_Q 0x08000000 /* Sticky overflow */ -+#define PS_V 0x10000000 /* Overflow cc */ -+#define PS_C 0x20000000 /* Carry cc */ -+#define PS_Z 0x40000000 /* Zero cc */ -+#define PS_N 0x80000000 /* Negative cc */ -+ -+/* Trap types */ -+#define TR_RST 0 /* Reset trap */ -+#define TR_UND 1 /* Indefined instruction trap */ -+#define TR_SWI 2 /* Software intrrupt */ -+#define TR_IAB 3 /* Instruction fetch abort */ -+#define TR_DAB 4 /* Data access abort */ -+#define TR_BAD 5 /* Bad trap: Not used by ARM */ -+#define TR_IRQ 6 /* Interrupt */ -+#define TR_FIQ 7 /* Fast interrupt */ -+ -+/* -+ * Memory segments (32bit kernel mode addresses) -+ */ -+#define PHYSADDR_MASK 0xffffffff -+ -+/* -+ * Map an address to a certain kernel segment -+ */ -+#undef PHYSADDR -+#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) -+#else /* !__ARM_ARCH_7M__ */ -+ -+/* Fields in cpsr */ -+#define PS_USR 0x00000010 /* Mode: User */ -+#define PS_FIQ 0x00000011 /* Mode: FIQ */ -+#define PS_IRQ 0x00000012 /* Mode: IRQ */ -+#define PS_SVC 0x00000013 /* Mode: Supervisor */ -+#define PS_ABT 0x00000017 /* Mode: Abort */ -+#define PS_UND 0x0000001b /* Mode: Undefined */ -+#define PS_SYS 0x0000001f /* Mode: System */ -+#define PS_MM 0x0000001f /* Mode bits mask */ -+#define PS_T 0x00000020 /* Thumb mode */ -+#define PS_F 0x00000040 /* FIQ disable */ -+#define PS_I 0x00000080 /* IRQ disable */ -+#define PS_A 0x00000100 /* Imprecise abort */ -+#define PS_E 0x00000200 /* Endianess */ -+#define PS_IT72 0x0000fc00 /* IT[7:2] */ -+#define PS_GE 0x000f0000 /* IT[7:2] */ -+#define PS_J 0x01000000 /* Java state */ -+#define PS_IT10 0x06000000 /* IT[1:0] */ -+#define PS_Q 0x08000000 /* Sticky overflow */ -+#define PS_V 0x10000000 /* Overflow cc */ -+#define PS_C 0x20000000 /* Carry cc */ -+#define PS_Z 0x40000000 /* Zero cc */ -+#define PS_N 0x80000000 /* Negative cc */ -+ -+/* Trap types */ -+#define TR_RST 0 /* Reset trap */ -+#define TR_UND 1 /* Indefined instruction trap */ -+#define TR_SWI 2 /* Software intrrupt */ -+#define TR_IAB 3 /* Instruction fetch abort */ -+#define TR_DAB 4 /* Data access abort */ -+#define TR_BAD 5 /* Bad trap: Not used by ARM */ -+#define TR_IRQ 6 /* Interrupt */ -+#define TR_FIQ 7 /* Fast interrupt */ -+ -+#ifdef BCMDBG_ARMRST -+#define TR_ARMRST 0xF /* Debug facility to trap Arm reset */ -+#endif -+ -+/* used to fill an overlay region with nop's */ -+#define NOP_UINT32 0x46c046c0 -+ -+ -+#define mrc(cp, a, b, n) \ -+({ \ -+ int __res; \ -+ __asm__ __volatile__("\tmrc\tp"STR(cp)", 0, %0, c"STR(a)", c"STR(b)", "STR(n) \ -+ :"=r" (__res)); \ -+ __res; \ -+}) -+ -+ -+#endif /* !__ARM_ARCH_7M__ */ -+ -+/* Pieces of a CPU Id */ -+#define CID_IMPL 0xff000000 /* Implementor: 0x41 for ARM Ltd. */ -+#define CID_VARIANT 0x00f00000 -+#define CID_ARCH 0x000f0000 -+#define CID_PART 0x0000fff0 -+#define CID_REV 0x0000000f -+#define CID_MASK (CID_IMPL | CID_ARCH | CID_PART) -+ -+#endif /* _ARMINC_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcm_cfg.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcm_cfg.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcm_cfg.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcm_cfg.h 2017-11-09 17:53:43.915303000 +0800 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * BCM common config options -+ * -+ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ -+ */ -+ -+#ifndef _bcm_cfg_h_ -+#define _bcm_cfg_h_ -+#if defined(__NetBSD__) || defined(__FreeBSD__) -+#if defined(_KERNEL) -+#include -+#endif /* defined(_KERNEL) */ -+#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ -+#endif /* _bcm_cfg_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcm_mpool_pub.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcm_mpool_pub.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcm_mpool_pub.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcm_mpool_pub.h 2017-11-09 17:53:43.916305000 +0800 -@@ -0,0 +1,355 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Memory pools library, Public interface -+ * -+ * API Overview -+ * -+ * This package provides a memory allocation subsystem based on pools of -+ * homogenous objects. -+ * -+ * Instrumentation is available for reporting memory utilization both -+ * on a per-data-structure basis and system wide. -+ * -+ * There are two main types defined in this API. -+ * -+ * pool manager: A singleton object that acts as a factory for -+ * pool allocators. It also is used for global -+ * instrumentation, such as reporting all blocks -+ * in use across all data structures. The pool manager -+ * creates and provides individual memory pools -+ * upon request to application code. -+ * -+ * memory pool: An object for allocating homogenous memory blocks. -+ * -+ * Global identifiers in this module use the following prefixes: -+ * bcm_mpm_* Memory pool manager -+ * bcm_mp_* Memory pool -+ * -+ * There are two main types of memory pools: -+ * -+ * prealloc: The contiguous memory block of objects can either be supplied -+ * by the client or malloc'ed by the memory manager. The objects are -+ * allocated out of a block of memory and freed back to the block. -+ * -+ * heap: The memory pool allocator uses the heap (malloc/free) for memory. -+ * In this case, the pool allocator is just providing statistics -+ * and instrumentation on top of the heap, without modifying the heap -+ * allocation implementation. -+ * -+ * $Id$ -+ */ -+ -+#ifndef _BCM_MPOOL_PUB_H -+#define _BCM_MPOOL_PUB_H 1 -+ -+#include /* needed for uint16 */ -+ -+ -+/* -+************************************************************************** -+* -+* Type definitions, handles -+* -+************************************************************************** -+*/ -+ -+/* Forward declaration of OSL handle. */ -+struct osl_info; -+ -+/* Forward declaration of string buffer. */ -+struct bcmstrbuf; -+ -+/* -+ * Opaque type definition for the pool manager handle. This object is used for global -+ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and -+ * instrumentation/debugging. -+ */ -+struct bcm_mpm_mgr; -+typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; -+ -+/* -+ * Opaque type definition for an instance of a pool. This handle is used for allocating -+ * and freeing memory through the pool, as well as management/instrumentation on this -+ * specific pool. -+ */ -+struct bcm_mp_pool; -+typedef struct bcm_mp_pool *bcm_mp_pool_h; -+ -+ -+/* -+ * To make instrumentation more readable, every memory -+ * pool must have a readable name. Pool names are up to -+ * 8 bytes including '\0' termination. (7 printable characters.) -+ */ -+#define BCM_MP_NAMELEN 8 -+ -+ -+/* -+ * Type definition for pool statistics. -+ */ -+typedef struct bcm_mp_stats { -+ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ -+ unsigned int objsz; /* Object size allocated in this pool */ -+ uint16 nobj; /* Total number of objects in this pool */ -+ uint16 num_alloc; /* Number of objects currently allocated */ -+ uint16 high_water; /* Max number of allocated objects. */ -+ uint16 failed_alloc; /* Failed allocations. */ -+} bcm_mp_stats_t; -+ -+ -+/* -+************************************************************************** -+* -+* API Routines on the pool manager. -+* -+************************************************************************** -+*/ -+ -+/* -+ * bcm_mpm_init() - initialize the whole memory pool system. -+ * -+ * Parameters: -+ * osh: INPUT Operating system handle. Needed for heap memory allocation. -+ * max_pools: INPUT Maximum number of mempools supported. -+ * mgr: OUTPUT The handle is written with the new pools manager object/handle. -+ * -+ * Returns: -+ * BCME_OK Object initialized successfully. May be used. -+ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. -+ */ -+int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); -+ -+ -+/* -+ * bcm_mpm_deinit() - de-initialize the whole memory pool system. -+ * -+ * Parameters: -+ * mgr: INPUT Pointer to pool manager handle. -+ * -+ * Returns: -+ * BCME_OK Memory pool manager successfully de-initialized. -+ * other Indicated error occured during de-initialization. -+ */ -+int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); -+ -+/* -+ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The -+ * pool uses a contiguous block of pre-alloced -+ * memory. The memory block may either be provided -+ * by the client or dynamically allocated by the -+ * pool manager. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pool manager -+ * obj_sz: INPUT Size of objects that will be allocated by the new pool -+ * Must be >= sizeof(void *). -+ * nobj: INPUT Maximum number of concurrently existing objects to support -+ * memstart INPUT Pointer to the memory to use, or NULL to malloc() -+ * memsize INPUT Number of bytes referenced from memstart (for error checking). -+ * Must be 0 if 'memstart' is NULL. -+ * poolname INPUT For instrumentation, the name of the pool -+ * newp: OUTPUT The handle for the new pool, if creation is successful -+ * -+ * Returns: -+ * BCME_OK Pool created ok. -+ * other Pool not created due to indicated error. newpoolp set to NULL. -+ * -+ * -+ */ -+int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, -+ unsigned int obj_sz, -+ int nobj, -+ void *memstart, -+ unsigned int memsize, -+ char poolname[BCM_MP_NAMELEN], -+ bcm_mp_pool_h *newp); -+ -+ -+/* -+ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after -+ * all memory objects have been freed back to the pool. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * pool: INPUT The handle of the pool to delete -+ * -+ * Returns: -+ * BCME_OK Pool deleted ok. -+ * other Pool not deleted due to indicated error. -+ * -+ */ -+int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); -+ -+/* -+ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory -+ * pool allocator uses the heap (malloc/free) for memory. -+ * In this case, the pool allocator is just providing -+ * statistics and instrumentation on top of the heap, -+ * without modifying the heap allocation implementation. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pool manager -+ * obj_sz: INPUT Size of objects that will be allocated by the new pool -+ * poolname INPUT For instrumentation, the name of the pool -+ * newp: OUTPUT The handle for the new pool, if creation is successful -+ * -+ * Returns: -+ * BCME_OK Pool created ok. -+ * other Pool not created due to indicated error. newpoolp set to NULL. -+ * -+ * -+ */ -+int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, -+ char poolname[BCM_MP_NAMELEN], -+ bcm_mp_pool_h *newp); -+ -+ -+/* -+ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after -+ * all memory objects have been freed back to the pool. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * pool: INPUT The handle of the pool to delete -+ * -+ * Returns: -+ * BCME_OK Pool deleted ok. -+ * other Pool not deleted due to indicated error. -+ * -+ */ -+int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); -+ -+ -+/* -+ * bcm_mpm_stats() - Return stats for all pools -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * stats: OUTPUT Array of pool statistics. -+ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number -+ * of array elements copied to 'stats' on OUTPUT. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error getting stats. -+ * -+ */ -+int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); -+ -+ -+/* -+ * bcm_mpm_dump() - Display statistics on all pools -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * b: OUTPUT Output buffer. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during dump. -+ * -+ */ -+int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); -+ -+ -+/* -+ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to -+ * compensate for alignment requirements of the objects. -+ * This function provides the padded object size. If clients -+ * pre-allocate a memory slab for a memory pool, the -+ * padded object size should be used by the client to allocate -+ * the memory slab (in order to provide sufficent space for -+ * the maximum number of objects). -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager. -+ * obj_sz: INPUT Input object size. -+ * padded_obj_sz: OUTPUT Padded object size. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * BCME_BADARG Bad arguments. -+ * -+ */ -+int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); -+ -+ -+/* -+*************************************************************************** -+* -+* API Routines on a specific pool. -+* -+*************************************************************************** -+*/ -+ -+ -+/* -+ * bcm_mp_alloc() - Allocate a memory pool object. -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool. -+ * -+ * Returns: -+ * A pointer to the new object. NULL on error. -+ * -+ */ -+void* bcm_mp_alloc(bcm_mp_pool_h pool); -+ -+/* -+ * bcm_mp_free() - Free a memory pool object. -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool. -+ * objp: INPUT A pointer to the object to free. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during free. -+ * -+ */ -+int bcm_mp_free(bcm_mp_pool_h pool, void *objp); -+ -+/* -+ * bcm_mp_stats() - Return stats for this pool -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool -+ * stats: OUTPUT Pool statistics -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error getting statistics. -+ * -+ */ -+int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); -+ -+ -+/* -+ * bcm_mp_dump() - Dump a pool -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool -+ * b OUTPUT Output buffer -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during dump. -+ * -+ */ -+int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); -+ -+ -+#endif /* _BCM_MPOOL_PUB_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmcdc.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmcdc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmcdc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmcdc.h 2017-11-09 17:53:43.917296000 +0800 -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * CDC network driver ioctl/indication encoding -+ * Broadcom 802.11abg Networking Device Driver -+ * -+ * Definitions subject to change without notice. -+ * -+ * $Id: bcmcdc.h 291086 2011-10-21 01:17:24Z $ -+ */ -+#ifndef _bcmcdc_h_ -+#define _bcmcdc_h_ -+#include -+ -+typedef struct cdc_ioctl { -+ uint32 cmd; /* ioctl command value */ -+ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ -+ uint32 flags; /* flag defns given below */ -+ uint32 status; /* status code returned from the device */ -+} cdc_ioctl_t; -+ -+/* Max valid buffer size that can be sent to the dongle */ -+#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN -+ -+/* len field is divided into input and output buffer lengths */ -+#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ -+ /* excluding IOCTL header */ -+#define CDCL_IOC_OUTLEN_SHIFT 0 -+#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ -+#define CDCL_IOC_INLEN_SHIFT 16 -+ -+/* CDC flag definitions */ -+#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ -+#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ -+#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */ -+#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */ -+#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */ -+#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */ -+#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */ -+#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ -+#define CDCF_IOC_IF_SHIFT 12 -+#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ -+#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ -+ -+#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) -+#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) -+ -+#define CDC_GET_IF_IDX(hdr) \ -+ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) -+#define CDC_SET_IF_IDX(hdr, idx) \ -+ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) -+ -+/* -+ * BDC header -+ * -+ * The BDC header is used on data packets to convey priority across USB. -+ */ -+ -+#define BDC_HEADER_LEN 4 -+ -+#define BDC_PROTO_VER_1 1 /* Old Protocol version */ -+#define BDC_PROTO_VER 2 /* Protocol version */ -+ -+#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ -+#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ -+ -+#define BDC_FLAG__UNUSED 0x03 /* Unassigned */ -+#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ -+#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ -+ -+#define BDC_PRIORITY_MASK 0x7 -+ -+#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ -+ /* FLOW CONTROL info only */ -+#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ -+ -+#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the packet was received */ -+#define BDC_FLAG2_IF_SHIFT 0 -+#define BDC_FLAG2_PAD_MASK 0xf0 -+#define BDC_FLAG_PAD_MASK 0x03 -+#define BDC_FLAG2_PAD_SHIFT 2 -+#define BDC_FLAG_PAD_SHIFT 0 -+#define BDC_FLAG2_PAD_IDX 0x3c -+#define BDC_FLAG_PAD_IDX 0x03 -+#define BDC_GET_PAD_LEN(hdr) \ -+ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ -+ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) -+#define BDC_SET_PAD_LEN(hdr, idx) \ -+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ -+ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ -+ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ -+ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) -+ -+#define BDC_GET_IF_IDX(hdr) \ -+ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) -+#define BDC_SET_IF_IDX(hdr, idx) \ -+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) -+ -+struct bdc_header { -+ uint8 flags; /* Flags */ -+ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */ -+ uint8 flags2; -+ uint8 dataOffset; /* Offset from end of BDC header to packet data, in -+ * 4-byte words. Leaves room for optional headers. -+ */ -+}; -+ -+#define BDC_PROTO_VER_1 1 /* Old Protocol version */ -+ -+#endif /* _bcmcdc_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmdefs.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmdefs.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmdefs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmdefs.h 2017-11-09 17:53:43.918300000 +0800 -@@ -0,0 +1,332 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc system wide definitions -+ * -+ * $Id: bcmdefs.h 316696 2012-02-23 03:29:35Z $ -+ */ -+ -+#ifndef _bcmdefs_h_ -+#define _bcmdefs_h_ -+ -+/* -+ * One doesn't need to include this file explicitly, gets included automatically if -+ * typedefs.h is included. -+ */ -+ -+/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function -+ * arguments or local variables. -+ */ -+#define BCM_REFERENCE(data) ((void)(data)) -+ -+/* Compile-time assert can be used in place of ASSERT if the expression evaluates -+ * to a constant at compile time. -+ */ -+#define STATIC_ASSERT(expr) { \ -+ /* Make sure the expression is constant. */ \ -+ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ -+ /* Make sure the expression is true. */ \ -+ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ -+} -+ -+/* Reclaiming text and data : -+ * The following macros specify special linker sections that can be reclaimed -+ * after a system is considered 'up'. -+ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, -+ * as in most cases, the attach function calls the detach function to clean up on error). -+ */ -+#ifdef DONGLEBUILD -+ -+extern bool bcmreclaimed; -+extern bool attach_part_reclaimed; -+ -+#define BCMATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data -+#define BCMATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn -+ -+#ifndef PREATTACH_NORECLAIM -+#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini3." #_data))) _data -+#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini3." #_fn), noinline)) _fn -+#else -+#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data -+#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn -+#endif -+ -+#if defined(BCMRECLAIM) -+#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini1." #_data))) _data -+#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn -+#define CONST -+#else -+#define BCMINITDATA(_data) _data -+#define BCMINITFN(_fn) _fn -+#define CONST const -+#endif -+ -+/* Non-manufacture or internal attach function/dat */ -+#if !defined(WLTEST) -+#define BCMNMIATTACHFN(_fn) BCMATTACHFN(_fn) -+#define BCMNMIATTACHDATA(_data) BCMATTACHDATA(_data) -+#else -+#define BCMNMIATTACHFN(_fn) _fn -+#define BCMNMIATTACHDATA(_data) _data -+#endif -+ -+#define BCMUNINITFN(_fn) _fn -+ -+#define BCMFASTPATH -+#else /* DONGLEBUILD */ -+ -+#define bcmreclaimed 0 -+#define BCMATTACHDATA(_data) _data -+#define BCMATTACHFN(_fn) _fn -+#define BCMPREATTACHDATA(_data) _data -+#define BCMPREATTACHFN(_fn) _fn -+#define BCMINITDATA(_data) _data -+#define BCMINITFN(_fn) _fn -+#define BCMUNINITFN(_fn) _fn -+#define BCMNMIATTACHFN(_fn) _fn -+#define BCMNMIATTACHDATA(_data) _data -+#define CONST const -+#if defined(__ARM_ARCH_7A__) -+#define BCM47XX_CA9 -+#else -+#undef BCM47XX_CA9 -+#endif -+#ifndef BCMFASTPATH -+#if defined(mips) || defined(BCM47XX_CA9) -+#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) -+#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) -+#else -+#define BCMFASTPATH -+#define BCMFASTPATH_HOST -+#endif -+#endif /* BCMFASTPATH */ -+ -+#endif /* DONGLEBUILD */ -+ -+#if defined(BCMROMBUILD) -+typedef struct { -+ uint16 esiz; -+ uint16 cnt; -+ void *addr; -+} bcmromdat_patch_t; -+#endif -+ -+/* Put some library data/code into ROM to reduce RAM requirements */ -+#if defined(BCMROMBUILD) && !defined(BCMROMSYMGEN_BUILD) && !defined(BCMJMPTBL_TCAM) -+#include -+#define STATIC static -+#else /* !BCMROMBUILD */ -+#define BCMROMDATA(_data) _data -+#define BCMROMDAT_NAME(_data) _data -+#define BCMROMFN(_fn) _fn -+#define BCMROMFN_NAME(_fn) _fn -+#define STATIC static -+#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) -+#define BCMROMDAT_SIZEOF(data) sizeof(data) -+#define BCMROMDAT_APATCH(data) -+#define BCMROMDAT_SPATCH(data) -+#endif /* !BCMROMBUILD */ -+ -+/* Bus types */ -+#define SI_BUS 0 /* SOC Interconnect */ -+#define PCI_BUS 1 /* PCI target */ -+#define PCMCIA_BUS 2 /* PCMCIA target */ -+#define SDIO_BUS 3 /* SDIO target */ -+#define JTAG_BUS 4 /* JTAG */ -+#define USB_BUS 5 /* USB (does not support R/W REG) */ -+#define SPI_BUS 6 /* gSPI target */ -+#define RPC_BUS 7 /* RPC target */ -+ -+/* Allows size optimization for single-bus image */ -+#ifdef BCMBUSTYPE -+#define BUSTYPE(bus) (BCMBUSTYPE) -+#else -+#define BUSTYPE(bus) (bus) -+#endif -+ -+/* Allows size optimization for single-backplane image */ -+#ifdef BCMCHIPTYPE -+#define CHIPTYPE(bus) (BCMCHIPTYPE) -+#else -+#define CHIPTYPE(bus) (bus) -+#endif -+ -+ -+/* Allows size optimization for SPROM support */ -+#if defined(BCMSPROMBUS) -+#define SPROMBUS (BCMSPROMBUS) -+#elif defined(SI_PCMCIA_SROM) -+#define SPROMBUS (PCMCIA_BUS) -+#else -+#define SPROMBUS (PCI_BUS) -+#endif -+ -+/* Allows size optimization for single-chip image */ -+#ifdef BCMCHIPID -+#define CHIPID(chip) (BCMCHIPID) -+#else -+#define CHIPID(chip) (chip) -+#endif -+ -+#ifdef BCMCHIPREV -+#define CHIPREV(rev) (BCMCHIPREV) -+#else -+#define CHIPREV(rev) (rev) -+#endif -+ -+/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ -+#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ -+#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ -+#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ -+ -+#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ -+#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ -+#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ -+#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ -+ -+#ifdef BCMDMA64OSL -+typedef struct { -+ uint32 loaddr; -+ uint32 hiaddr; -+} dma64addr_t; -+ -+typedef dma64addr_t dmaaddr_t; -+#define PHYSADDRHI(_pa) ((_pa).hiaddr) -+#define PHYSADDRHISET(_pa, _val) \ -+ do { \ -+ (_pa).hiaddr = (_val); \ -+ } while (0) -+#define PHYSADDRLO(_pa) ((_pa).loaddr) -+#define PHYSADDRLOSET(_pa, _val) \ -+ do { \ -+ (_pa).loaddr = (_val); \ -+ } while (0) -+ -+#else -+typedef unsigned long dmaaddr_t; -+#define PHYSADDRHI(_pa) (0) -+#define PHYSADDRHISET(_pa, _val) -+#define PHYSADDRLO(_pa) ((_pa)) -+#define PHYSADDRLOSET(_pa, _val) \ -+ do { \ -+ (_pa) = (_val); \ -+ } while (0) -+#endif /* BCMDMA64OSL */ -+ -+/* One physical DMA segment */ -+typedef struct { -+ dmaaddr_t addr; -+ uint32 length; -+} hnddma_seg_t; -+ -+#if defined(MACOSX) -+/* In MacOS, the OS API may return large number of segments. Setting this number lower -+ * will result in failure of dma map -+ */ -+#define MAX_DMA_SEGS 8 -+#elif defined(__NetBSD__) -+/* In NetBSD we also want more segments because the lower level mbuf mapping api might -+ * allocate a large number of segments -+ */ -+#define MAX_DMA_SEGS 16 -+#else -+#define MAX_DMA_SEGS 4 -+#endif -+ -+ -+typedef struct { -+ void *oshdmah; /* Opaque handle for OSL to store its information */ -+ uint origsize; /* Size of the virtual packet */ -+ uint nsegs; -+ hnddma_seg_t segs[MAX_DMA_SEGS]; -+} hnddma_seg_map_t; -+ -+ -+/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). -+ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. -+ * There is a compile time check in wlc.c which ensure that this value is at least as big -+ * as TXOFF. This value is used in dma_rxfill (hnddma.c). -+ */ -+ -+#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) -+/* add 40 bytes to allow for extra RPC header and info */ -+#define BCMEXTRAHDROOM 260 -+#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ -+#define BCMEXTRAHDROOM 204 -+#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ -+ -+/* Packet alignment for most efficient SDIO (can change based on platform) */ -+#ifndef SDALIGN -+#define SDALIGN 32 -+#endif -+ -+/* Headroom required for dongle-to-host communication. Packets allocated -+ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should -+ * leave this much room in front for low-level message headers which may -+ * be needed to get across the dongle bus to the host. (These messages -+ * don't go over the network, so room for the full WL header above would -+ * be a waste.). -+*/ -+#define BCMDONGLEHDRSZ 12 -+#define BCMDONGLEPADSZ 16 -+ -+#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) -+ -+#ifdef BCMDBG -+ -+#ifndef BCMDBG_ERR -+#define BCMDBG_ERR -+#endif /* BCMDBG_ERR */ -+ -+#define BCMDBG_ASSERT -+ -+#endif /* BCMDBG */ -+ -+ -+/* Macros for doing definition and get/set of bitfields -+ * Usage example, e.g. a three-bit field (bits 4-6): -+ * #define _M BITFIELD_MASK(3) -+ * #define _S 4 -+ * ... -+ * regval = R_REG(osh, ®s->regfoo); -+ * field = GFIELD(regval, ); -+ * regval = SFIELD(regval, , 1); -+ * W_REG(osh, ®s->regfoo, regval); -+ */ -+#define BITFIELD_MASK(width) \ -+ (((unsigned)1 << (width)) - 1) -+#define GFIELD(val, field) \ -+ (((val) >> field ## _S) & field ## _M) -+#define SFIELD(val, field, bits) \ -+ (((val) & (~(field ## _M << field ## _S))) | \ -+ ((unsigned)(bits) << field ## _S)) -+ -+/* define BCMSMALL to remove misc features for memory-constrained environments */ -+#ifdef BCMSMALL -+#undef BCMSPACE -+#define bcmspace FALSE /* if (bcmspace) code is discarded */ -+#else -+#define BCMSPACE -+#define bcmspace TRUE /* if (bcmspace) code is retained */ -+#endif -+ -+/* Max. nvram variable table size */ -+#define MAXSZ_NVRAM_VARS 4096 -+ -+#ifdef EFI -+#define __attribute__(x) /* CSTYLED */ -+#endif -+ -+#endif /* _bcmdefs_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmdevs.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmdevs.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmdevs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmdevs.h 2017-11-09 17:53:43.920291000 +0800 -@@ -0,0 +1,870 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom device-specific manifest constants. -+ * -+ * $Id: bcmdevs.h 328955 2012-04-23 09:06:12Z $ -+ */ -+ -+#ifndef _BCMDEVS_H -+#define _BCMDEVS_H -+ -+/* PCI vendor IDs */ -+#define VENDOR_EPIGRAM 0xfeda -+#define VENDOR_BROADCOM 0x14e4 -+#define VENDOR_3COM 0x10b7 -+#define VENDOR_NETGEAR 0x1385 -+#define VENDOR_DIAMOND 0x1092 -+#define VENDOR_INTEL 0x8086 -+#define VENDOR_DELL 0x1028 -+#define VENDOR_HP 0x103c -+#define VENDOR_HP_COMPAQ 0x0e11 -+#define VENDOR_APPLE 0x106b -+#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ -+#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ -+#define VENDOR_TI 0x104c /* Texas Instruments */ -+#define VENDOR_RICOH 0x1180 /* Ricoh */ -+#define VENDOR_JMICRON 0x197b -+ -+ -+/* PCMCIA vendor IDs */ -+#define VENDOR_BROADCOM_PCMCIA 0x02d0 -+ -+/* SDIO vendor IDs */ -+#define VENDOR_BROADCOM_SDIO 0x00BF -+ -+/* DONGLE VID/PIDs */ -+#define BCM_DNGL_VID 0x0a5c -+#define BCM_DNGL_BL_PID_4328 0xbd12 -+#define BCM_DNGL_BL_PID_4322 0xbd13 -+#define BCM_DNGL_BL_PID_4319 0xbd16 -+#define BCM_DNGL_BL_PID_43236 0xbd17 -+#define BCM_DNGL_BL_PID_4332 0xbd18 -+#define BCM_DNGL_BL_PID_4330 0xbd19 -+#define BCM_DNGL_BL_PID_4334 0xbd1a -+#define BCM_DNGL_BL_PID_43239 0xbd1b -+#define BCM_DNGL_BL_PID_4324 0xbd1c -+#define BCM_DNGL_BL_PID_4360 0xbd1d -+#define BCM_DNGL_BL_PID_4335 0xbd20 -+ -+#define BCM_DNGL_BDC_PID 0x0bdc -+#define BCM_DNGL_JTAG_PID 0x4a44 -+ -+/* HW USB BLOCK [CPULESS USB] PIDs */ -+#define BCM_HWUSB_PID_43239 43239 -+ -+/* PCI Device IDs */ -+#define BCM4210_DEVICE_ID 0x1072 /* never used */ -+#define BCM4230_DEVICE_ID 0x1086 /* never used */ -+#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ -+#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ -+#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ -+#define BCM4211_DEVICE_ID 0x4211 -+#define BCM4231_DEVICE_ID 0x4231 -+#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ -+#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ -+#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ -+#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ -+#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */ -+#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */ -+#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */ -+#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ -+#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ -+#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ -+#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ -+#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */ -+#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */ -+#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ -+#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ -+#define BCM4306_UART_ID 0x4322 /* 4306 uart */ -+#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ -+#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ -+#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */ -+#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ -+#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ -+#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ -+#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */ -+#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */ -+#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */ -+#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ -+#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ -+#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ -+#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ -+#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ -+#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ -+#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ -+#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ -+#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ -+#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ -+#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ -+#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ -+#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ -+#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ -+#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ -+#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ -+#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ -+#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ -+#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ -+#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ -+#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ -+#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ -+#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ -+#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ -+#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ -+#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ -+#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ -+#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ -+#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ -+#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ -+#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ -+#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ -+#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ -+#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ -+#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ -+#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ -+#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ -+#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ -+#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ -+#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ -+#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ -+#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ -+#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ -+#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ -+#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ -+#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ -+#define BCM4360_D11AC_ID 0x43a0 -+#define BCM4360_D11AC2G_ID 0x43a1 -+#define BCM4360_D11AC5G_ID 0x43a2 -+#define BCM4335_D11AC_ID 0x43ae -+#define BCM4335_D11AC2G_ID 0x43af -+#define BCM4335_D11AC5G_ID 0x43b0 -+#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ -+#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ -+#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ -+ -+/* PCI Subsystem ID */ -+#define BCM943228HMB_SSID_VEN1 0x0607 -+#define BCM94313HMGBL_SSID_VEN1 0x0608 -+#define BCM94313HMG_SSID_VEN1 0x0609 -+ -+ -+#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ -+#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ -+#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ -+#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ -+#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ -+#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ -+#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ -+#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ -+#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */ -+#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ -+#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */ -+#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */ -+#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ -+#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ -+#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ -+#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ -+#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ -+#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ -+#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ -+#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ -+#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */ -+#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ -+#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ -+#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ -+#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */ -+#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ -+#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ -+#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ -+#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ -+#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ -+#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ -+#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ -+#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ -+#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ -+#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ -+#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ -+#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ -+#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ -+#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ -+#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ -+#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ -+#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ -+#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ -+#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ -+#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ -+#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */ -+ -+/* Chip IDs */ -+#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ -+#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ -+#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ -+#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ -+#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ -+#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ -+#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ -+#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ -+#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ -+#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ -+#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */ -+#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */ -+#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ -+#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ -+#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ -+#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ -+#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ -+#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ -+#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ -+#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ -+#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ -+#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ -+#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ -+#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ -+#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ -+#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ -+#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ -+#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ -+#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ -+#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ -+#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ -+#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ -+#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ -+#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ -+#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ -+#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ -+#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ -+#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ -+#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ -+#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ -+#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ -+#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ -+#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ -+#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ -+#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ -+#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ -+#define BCM4335_CHIP_ID 0x4335 -+#define BCM4360_CHIP_ID 0x4360 -+#define BCM43526_CHIP_ID 0xAA06 -+#define BCM4352_CHIP_ID 0x4352 -+ -+#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ -+#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ -+#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ -+#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ -+#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ -+#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ -+#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ -+#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ -+#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ -+#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ -+#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ -+#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ -+#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ -+#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ -+#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ -+#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ -+#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ -+#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ -+#define BCM53010_CHIP_ID 53010 /* NS chipcommon chipid */ -+#define BCM56150_CHIP_ID 56150 /* HR2 chipcommon chipid */ -+#define BCM56340_CHIP_ID 56340 /* HX4 chipcommon chipid */ -+#define BCM53020_CHIP_ID 53020 /* NSP chipcommon chipid */ -+#define BCM56450_CHIP_ID 56450 /* KT2 chipcommon chipid */ -+#define BCM54016_CHIP_ID 54016 /* CYGNUS chipcommon chipid */ -+#define BCM53400_CHIP_ID 0x8416 /* GH chipcommon chipid */ -+#define BCM56260_CHIP_ID 0xb260 /* SB2 chipcommon chipid */ -+#define BCM56160_CHIP_ID 0xb160 /* HR3 chipcommon chipid */ -+#define BCM56170_CHIP_ID 0xb170 /* GH2 chipcommon chipid */ -+#define BCM53540_CHIP_ID 0x8540 /* WF2 chipcommon chipid */ -+ -+#if defined(CONFIG_MACH_HX4) -+#define BCMIPROC_CHIP_ID BCM56340_CHIP_ID -+#elif defined(CONFIG_MACH_HR2) -+#define BCMIPROC_CHIP_ID BCM56150_CHIP_ID -+#elif defined(CONFIG_MACH_KT2) -+#define BCMIPROC_CHIP_ID BCM56450_CHIP_ID -+#elif defined(CONFIG_MACH_GH) -+#define BCMIPROC_CHIP_ID BCM53400_CHIP_ID -+#elif defined(CONFIG_MACH_SB2) -+#define BCMIPROC_CHIP_ID BCM56260_CHIP_ID -+#elif defined(CONFIG_MACH_HR3) -+ -+#if defined(CONFIG_MACH_WH2) -+#define BCMIPROC_CHIP_ID BCM53540_CHIP_ID -+#else -+#define BCMIPROC_CHIP_ID BCM56160_CHIP_ID -+#endif -+ -+#elif defined(CONFIG_MACH_GH2) -+#define BCMIPROC_CHIP_ID BCM56170_CHIP_ID -+#endif -+ -+/* Package IDs */ -+#define BCM4303_PKG_ID 2 /* 4303 package id */ -+#define BCM4309_PKG_ID 1 /* 4309 package id */ -+#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ -+#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ -+#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ -+#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ -+#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ -+#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ -+#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ -+#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */ -+#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */ -+#define BCM5354E_PKG_ID 1 /* 5354E package id */ -+#define BCM4716_PKG_ID 8 /* 4716 package id */ -+#define BCM4717_PKG_ID 9 /* 4717 package id */ -+#define BCM4718_PKG_ID 10 /* 4718 package id */ -+#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ -+#define BCM5358U_PKG_ID 8 /* 5358U package id */ -+#define BCM5358_PKG_ID 9 /* 5358 package id */ -+#define BCM47186_PKG_ID 10 /* 47186 package id */ -+#define BCM5357_PKG_ID 11 /* 5357 package id */ -+#define BCM5356U_PKG_ID 12 /* 5356U package id */ -+#define BCM53572_PKG_ID 8 /* 53572 package id */ -+#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ -+#define BCM47188_PKG_ID 9 /* 47188 package id */ -+#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ -+#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ -+#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ -+#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ -+#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ -+#define BCM4706L_PKG_ID 1 /* 4706L package id */ -+ -+#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ -+#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ -+#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ -+#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ -+#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ -+#define BCM4336_WLBGA_PKG_ID 0x8 -+#define BCM4330_WLBGA_PKG_ID 0x0 -+#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ -+#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ -+#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ -+#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ -+#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ -+#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ -+ -+#define BCM4707_PKG_ID 1 /* 4707 package id */ -+#define BCM4708_PKG_ID 2 /* 4708 package id */ -+#define BCM4709_PKG_ID 0 /* 4709 package id */ -+ -+#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ -+#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ -+ -+#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ -+#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */ -+#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ -+#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */ -+#define BCM4335_PKG_MASK (0x3) -+ -+/* boardflags */ -+#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ -+#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ -+#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ -+#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ -+#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ -+#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ -+#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ -+#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ -+#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ -+#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ -+#define BFL_UNUSED 0x00000200 -+#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ -+#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ -+#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ -+#define BFL_HGPA 0x00002000 /* Board has a high gain PA */ -+#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ -+#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ -+#define BFL_NOPA 0x00010000 /* Board has no PA */ -+#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ -+#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ -+#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ -+#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ -+#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ -+#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ -+#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ -+#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ -+#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ -+#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ -+#define BFL_FASTPWR 0x08000000 -+#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ -+#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ -+#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ -+#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ -+#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field -+ * when this flag is set -+ */ -+#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ -+ -+/* boardflags2 */ -+#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ -+#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ -+#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ -+#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ -+#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ -+#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ -+#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ -+#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ -+#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace -+ * BFL2_BTC3WIRE -+ */ -+#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ -+#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ -+#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ -+#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ -+#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ -+#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ -+#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ -+#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ -+#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ -+#define BFL2_IPALVLSHIFT_3P3 0x00020000 -+#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ -+#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ -+ /* Most drivers will turn it off without this flag */ -+ /* to save power. */ -+ -+#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ -+#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ -+#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ -+#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ -+#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value -+ * than programmed. The exact delta is decided by -+ * driver per chip/boardtype. This can be used -+ * when tempsense qualification happens after shipment -+ */ -+#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ -+#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ -+#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ -+ /* ucode control of eLNA during Tx */ -+#define BFL2_4313_RADIOREG 0x10000000 -+ /* board rework */ -+#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ -+ -+/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ -+#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ -+#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ -+#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ -+#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ -+#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ -+#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ -+#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ -+#define BOARD_GPIO_12 0x1000 /* gpio 12 */ -+#define BOARD_GPIO_13 0x2000 /* gpio 13 */ -+#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ -+#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ -+#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ -+#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ -+#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ -+#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ -+#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ -+ -+#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ -+#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ -+#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ -+#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ -+#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ -+#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ -+#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ -+ -+#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ -+#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ -+#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ -+#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ -+ -+/* power control defines */ -+#define PLL_DELAY 150 /* us pll on delay */ -+#define FREF_DELAY 200 /* us fref change delay */ -+#define MIN_SLOW_CLK 32 /* us Slow clock period */ -+#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* Reference Board Types */ -+#define BU4710_BOARD 0x0400 -+#define VSIM4710_BOARD 0x0401 -+#define QT4710_BOARD 0x0402 -+ -+#define BU4309_BOARD 0x040a -+#define BCM94309CB_BOARD 0x040b -+#define BCM94309MP_BOARD 0x040c -+#define BCM4309AP_BOARD 0x040d -+ -+#define BCM94302MP_BOARD 0x040e -+ -+#define BU4306_BOARD 0x0416 -+#define BCM94306CB_BOARD 0x0417 -+#define BCM94306MP_BOARD 0x0418 -+ -+#define BCM94710D_BOARD 0x041a -+#define BCM94710R1_BOARD 0x041b -+#define BCM94710R4_BOARD 0x041c -+#define BCM94710AP_BOARD 0x041d -+ -+#define BU2050_BOARD 0x041f -+ -+#define BCM94306P50_BOARD 0x0420 -+ -+#define BCM94309G_BOARD 0x0421 -+ -+#define BU4704_BOARD 0x0423 -+#define BU4702_BOARD 0x0424 -+ -+#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ -+ -+#define MPSG4306_BOARD 0x0427 -+ -+#define BCM94702MN_BOARD 0x0428 -+ -+/* BCM4702 1U CompactPCI Board */ -+#define BCM94702CPCI_BOARD 0x0429 -+ -+/* BCM4702 with BCM95380 VLAN Router */ -+#define BCM95380RR_BOARD 0x042a -+ -+/* cb4306 with SiGe PA */ -+#define BCM94306CBSG_BOARD 0x042b -+ -+/* cb4306 with SiGe PA */ -+#define PCSG94306_BOARD 0x042d -+ -+/* bu4704 with sdram */ -+#define BU4704SD_BOARD 0x042e -+ -+/* Dual 11a/11g Router */ -+#define BCM94704AGR_BOARD 0x042f -+ -+/* 11a-only minipci */ -+#define BCM94308MP_BOARD 0x0430 -+ -+/* 4306/gprs combo */ -+#define BCM94306GPRS_BOARD 0x0432 -+ -+/* BCM5365/BCM4704 FPGA Bringup Board */ -+#define BU5365_FPGA_BOARD 0x0433 -+ -+#define BU4712_BOARD 0x0444 -+#define BU4712SD_BOARD 0x045d -+#define BU4712L_BOARD 0x045f -+ -+/* BCM4712 boards */ -+#define BCM94712AP_BOARD 0x0445 -+#define BCM94712P_BOARD 0x0446 -+ -+/* BCM4318 boards */ -+#define BU4318_BOARD 0x0447 -+#define CB4318_BOARD 0x0448 -+#define MPG4318_BOARD 0x0449 -+#define MP4318_BOARD 0x044a -+#define SD4318_BOARD 0x044b -+ -+/* BCM4313 boards */ -+#define BCM94313BU_BOARD 0x050f -+#define BCM94313HM_BOARD 0x0510 -+#define BCM94313EPA_BOARD 0x0511 -+#define BCM94313HMG_BOARD 0x051C -+ -+/* BCM63XX boards */ -+#define BCM96338_BOARD 0x6338 -+#define BCM96348_BOARD 0x6348 -+#define BCM96358_BOARD 0x6358 -+#define BCM96368_BOARD 0x6368 -+ -+/* Another mp4306 with SiGe */ -+#define BCM94306P_BOARD 0x044c -+ -+/* mp4303 */ -+#define BCM94303MP_BOARD 0x044e -+ -+/* mpsgh4306 */ -+#define BCM94306MPSGH_BOARD 0x044f -+ -+/* BRCM 4306 w/ Front End Modules */ -+#define BCM94306MPM 0x0450 -+#define BCM94306MPL 0x0453 -+ -+/* 4712agr */ -+#define BCM94712AGR_BOARD 0x0451 -+ -+/* pcmcia 4303 */ -+#define PC4303_BOARD 0x0454 -+ -+/* 5350K */ -+#define BCM95350K_BOARD 0x0455 -+ -+/* 5350R */ -+#define BCM95350R_BOARD 0x0456 -+ -+/* 4306mplna */ -+#define BCM94306MPLNA_BOARD 0x0457 -+ -+/* 4320 boards */ -+#define BU4320_BOARD 0x0458 -+#define BU4320S_BOARD 0x0459 -+#define BCM94320PH_BOARD 0x045a -+ -+/* 4306mph */ -+#define BCM94306MPH_BOARD 0x045b -+ -+/* 4306pciv */ -+#define BCM94306PCIV_BOARD 0x045c -+ -+#define BU4712SD_BOARD 0x045d -+ -+#define BCM94320PFLSH_BOARD 0x045e -+ -+#define BU4712L_BOARD 0x045f -+#define BCM94712LGR_BOARD 0x0460 -+#define BCM94320R_BOARD 0x0461 -+ -+#define BU5352_BOARD 0x0462 -+ -+#define BCM94318MPGH_BOARD 0x0463 -+ -+#define BU4311_BOARD 0x0464 -+#define BCM94311MC_BOARD 0x0465 -+#define BCM94311MCAG_BOARD 0x0466 -+ -+#define BCM95352GR_BOARD 0x0467 -+ -+/* bcm95351agr */ -+#define BCM95351AGR_BOARD 0x0470 -+ -+/* bcm94704mpcb */ -+#define BCM94704MPCB_BOARD 0x0472 -+ -+/* 4785 boards */ -+#define BU4785_BOARD 0x0478 -+ -+/* 4321 boards */ -+#define BU4321_BOARD 0x046b -+#define BU4321E_BOARD 0x047c -+#define MP4321_BOARD 0x046c -+#define CB2_4321_BOARD 0x046d -+#define CB2_4321_AG_BOARD 0x0066 -+#define MC4321_BOARD 0x046e -+ -+/* 4328 boards */ -+#define BU4328_BOARD 0x0481 -+#define BCM4328SDG_BOARD 0x0482 -+#define BCM4328SDAG_BOARD 0x0483 -+#define BCM4328UG_BOARD 0x0484 -+#define BCM4328UAG_BOARD 0x0485 -+#define BCM4328PC_BOARD 0x0486 -+#define BCM4328CF_BOARD 0x0487 -+ -+/* 4325 boards */ -+#define BCM94325DEVBU_BOARD 0x0490 -+#define BCM94325BGABU_BOARD 0x0491 -+ -+#define BCM94325SDGWB_BOARD 0x0492 -+ -+#define BCM94325SDGMDL_BOARD 0x04aa -+#define BCM94325SDGMDL2_BOARD 0x04c6 -+#define BCM94325SDGMDL3_BOARD 0x04c9 -+ -+#define BCM94325SDABGWBA_BOARD 0x04e1 -+ -+/* 4322 boards */ -+#define BCM94322MC_SSID 0x04a4 -+#define BCM94322USB_SSID 0x04a8 /* dualband */ -+#define BCM94322HM_SSID 0x04b0 -+#define BCM94322USB2D_SSID 0x04bf /* single band discrete front end */ -+ -+/* 4312 boards */ -+#define BCM4312MCGSG_BOARD 0x04b5 -+ -+/* 4315 boards */ -+#define BCM94315DEVBU_SSID 0x04c2 -+#define BCM94315USBGP_SSID 0x04c7 -+#define BCM94315BGABU_SSID 0x04ca -+#define BCM94315USBGP41_SSID 0x04cb -+ -+/* 4319 boards */ -+#define BCM94319DEVBU_SSID 0X04e5 -+#define BCM94319USB_SSID 0X04e6 -+#define BCM94319SD_SSID 0X04e7 -+ -+/* 4716 boards */ -+#define BCM94716NR2_SSID 0x04cd -+ -+/* 4319 boards */ -+#define BCM94319DEVBU_SSID 0X04e5 -+#define BCM94319USBNP4L_SSID 0X04e6 -+#define BCM94319WLUSBN4L_SSID 0X04e7 -+#define BCM94319SDG_SSID 0X04ea -+#define BCM94319LCUSBSDN4L_SSID 0X04eb -+#define BCM94319USBB_SSID 0x04ee -+#define BCM94319LCSDN4L_SSID 0X0507 -+#define BCM94319LSUSBN4L_SSID 0X0508 -+#define BCM94319SDNA4L_SSID 0X0517 -+#define BCM94319SDELNA4L_SSID 0X0518 -+#define BCM94319SDELNA6L_SSID 0X0539 -+#define BCM94319ARCADYAN_SSID 0X0546 -+#define BCM94319WINDSOR_SSID 0x0561 -+#define BCM94319MLAP_SSID 0x0562 -+#define BCM94319SDNA_SSID 0x058b -+#define BCM94319BHEMU3_SSID 0x0563 -+#define BCM94319SDHMB_SSID 0x058c -+#define BCM94319SDBREF_SSID 0x05a1 -+#define BCM94319USBSDB_SSID 0x05a2 -+ -+ -+/* 4329 boards */ -+#define BCM94329AGB_SSID 0X04b9 -+#define BCM94329TDKMDL1_SSID 0X04ba -+#define BCM94329TDKMDL11_SSID 0X04fc -+#define BCM94329OLYMPICN18_SSID 0X04fd -+#define BCM94329OLYMPICN90_SSID 0X04fe -+#define BCM94329OLYMPICN90U_SSID 0X050c -+#define BCM94329OLYMPICN90M_SSID 0X050b -+#define BCM94329AGBF_SSID 0X04ff -+#define BCM94329OLYMPICX17_SSID 0X0504 -+#define BCM94329OLYMPICX17M_SSID 0X050a -+#define BCM94329OLYMPICX17U_SSID 0X0509 -+#define BCM94329OLYMPICUNO_SSID 0X0564 -+#define BCM94329MOTOROLA_SSID 0X0565 -+#define BCM94329OLYMPICLOCO_SSID 0X0568 -+/* 4336 SDIO board types */ -+#define BCM94336SD_WLBGABU_SSID 0x0511 -+#define BCM94336SD_WLBGAREF_SSID 0x0519 -+#define BCM94336SDGP_SSID 0x0538 -+#define BCM94336SDG_SSID 0x0519 -+#define BCM94336SDGN_SSID 0x0538 -+#define BCM94336SDGFC_SSID 0x056B -+ -+/* 4330 SDIO board types */ -+#define BCM94330SDG_SSID 0x0528 -+#define BCM94330SD_FCBGABU_SSID 0x052e -+#define BCM94330SD_WLBGABU_SSID 0x052f -+#define BCM94330SD_FCBGA_SSID 0x0530 -+#define BCM94330FCSDAGB_SSID 0x0532 -+#define BCM94330OLYMPICAMG_SSID 0x0549 -+#define BCM94330OLYMPICAMGEPA_SSID 0x054F -+#define BCM94330OLYMPICUNO3_SSID 0x0551 -+#define BCM94330WLSDAGB_SSID 0x0547 -+#define BCM94330CSPSDAGBB_SSID 0x054A -+ -+/* 43224 boards */ -+#define BCM943224X21 0x056e -+#define BCM943224X21_FCC 0x00d1 -+#define BCM943224X21B 0x00e9 -+#define BCM943224M93 0x008b -+#define BCM943224M93A 0x0090 -+#define BCM943224X16 0x0093 -+#define BCM94322X9 0x008d -+#define BCM94322M35e 0x008e -+ -+/* 43228 Boards */ -+#define BCM943228BU8_SSID 0x0540 -+#define BCM943228BU9_SSID 0x0541 -+#define BCM943228BU_SSID 0x0542 -+#define BCM943227HM4L_SSID 0x0543 -+#define BCM943227HMB_SSID 0x0544 -+#define BCM943228HM4L_SSID 0x0545 -+#define BCM943228SD_SSID 0x0573 -+ -+/* 43239 Boards */ -+#define BCM943239MOD_SSID 0x05ac -+#define BCM943239REF_SSID 0x05aa -+ -+/* 4331 boards */ -+#define BCM94331X19 0x00D6 /* X19B */ -+#define BCM94331X28 0x00E4 /* X28 */ -+#define BCM94331X28B 0x010E /* X28B */ -+#define BCM94331PCIEBT3Ax_SSID BCM94331X28 -+#define BCM94331X12_2G_SSID 0x00EC /* X12 2G */ -+#define BCM94331X12_5G_SSID 0x00ED /* X12 5G */ -+#define BCM94331X29B 0x00EF /* X29B */ -+#define BCM94331CSAX_SSID BCM94331X29B -+#define BCM94331X19C 0x00F5 /* X19C */ -+#define BCM94331X33 0x00F4 /* X33 */ -+#define BCM94331BU_SSID 0x0523 -+#define BCM94331S9BU_SSID 0x0524 -+#define BCM94331MC_SSID 0x0525 -+#define BCM94331MCI_SSID 0x0526 -+#define BCM94331PCIEBT4_SSID 0x0527 -+#define BCM94331HM_SSID 0x0574 -+#define BCM94331PCIEDUAL_SSID 0x059B -+#define BCM94331MCH5_SSID 0x05A9 -+#define BCM94331CS_SSID 0x05C6 -+#define BCM94331CD_SSID 0x05DA -+ -+/* 4314 Boards */ -+#define BCM94314BU_SSID 0x05b1 -+ -+/* 53572 Boards */ -+#define BCM953572BU_SSID 0x058D -+#define BCM953572NR2_SSID 0x058E -+#define BCM947188NR2_SSID 0x058F -+#define BCM953572SDRNR2_SSID 0x0590 -+ -+/* 43236 boards */ -+#define BCM943236OLYMPICSULLEY_SSID 0x594 -+#define BCM943236PREPROTOBLU2O3_SSID 0x5b9 -+#define BCM943236USBELNA_SSID 0x5f8 -+ -+/* 4314 Boards */ -+#define BCM94314BUSDIO_SSID 0x05c8 -+#define BCM94314BGABU_SSID 0x05c9 -+#define BCM94314HMEPA_SSID 0x05ca -+#define BCM94314HMEPABK_SSID 0x05cb -+#define BCM94314SUHMEPA_SSID 0x05cc -+#define BCM94314SUHM_SSID 0x05cd -+#define BCM94314HM_SSID 0x05d1 -+ -+/* 4334 Boards */ -+#define BCM94334FCAGBI_SSID 0x05df -+#define BCM94334WLAGBI_SSID 0x05dd -+ -+/* 43217 Boards */ -+#define BCM943217BU_SSID 0x05d5 -+#define BCM943217HM2L_SSID 0x05d6 -+#define BCM943217HMITR2L_SSID 0x05d7 -+ -+/* 43142 Boards */ -+#define BCM943142HM_SSID 0x05e0 -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+/* # of GPIO pins */ -+#define GPIO_NUMPINS 32 -+ -+/* These values are used by dhd host driver. */ -+#define RDL_RAM_BASE_4319 0x60000000 -+#define RDL_RAM_BASE_4329 0x60000000 -+#define RDL_RAM_SIZE_4319 0x48000 -+#define RDL_RAM_SIZE_4329 0x48000 -+#define RDL_RAM_SIZE_43236 0x70000 -+#define RDL_RAM_BASE_43236 0x60000000 -+#define RDL_RAM_SIZE_4328 0x60000 -+#define RDL_RAM_BASE_4328 0x80000000 -+#define RDL_RAM_SIZE_4322 0x60000 -+#define RDL_RAM_BASE_4322 0x60000000 -+#define RDL_RAM_SIZE_4360 0xE0000 -+#define RDL_RAM_BASE_4360 0x60000000 -+ -+/* generic defs for nvram "muxenab" bits -+* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. -+*/ -+#define MUXENAB_UART 0x00000001 -+#define MUXENAB_GPIO 0x00000002 -+#define MUXENAB_ERCX 0x00000004 -+#define MUXENAB_JTAG 0x00000008 -+#define MUXENAB_HOST_WAKE 0x00000010 -+ -+/* Boot flags */ -+#define FLASH_KERNEL_NFLASH 0x00000001 -+#define FLASH_BOOT_NFLASH 0x00000002 -+ -+#endif /* _BCMDEVS_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmendian.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmendian.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmendian.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmendian.h 2017-11-09 17:53:43.921293000 +0800 -@@ -0,0 +1,324 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Byte order utilities -+ * -+ * $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $ -+ * -+ * This file by default provides proper behavior on little-endian architectures. -+ * On big-endian architectures, IL_BIGENDIAN should be defined. -+ */ -+ -+#ifndef _BCMENDIAN_H_ -+#define _BCMENDIAN_H_ -+ -+#include -+ -+/* Reverse the bytes in a 16-bit value */ -+#define BCMSWAP16(val) \ -+ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ -+ (((uint16)(val) & (uint16)0xff00U) >> 8))) -+ -+/* Reverse the bytes in a 32-bit value */ -+#define BCMSWAP32(val) \ -+ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ -+ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ -+ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ -+ (((uint32)(val) & (uint32)0xff000000U) >> 24))) -+ -+/* Reverse the two 16-bit halves of a 32-bit value */ -+#define BCMSWAP32BY16(val) \ -+ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ -+ (((uint32)(val) & (uint32)0xffff0000U) >> 16))) -+ -+/* Byte swapping macros -+ * Host <=> Network (Big Endian) for 16- and 32-bit values -+ * Host <=> Little-Endian for 16- and 32-bit values -+ */ -+#ifndef hton16 -+#ifndef IL_BIGENDIAN -+#define HTON16(i) BCMSWAP16(i) -+#define hton16(i) bcmswap16(i) -+#define HTON32(i) BCMSWAP32(i) -+#define hton32(i) bcmswap32(i) -+#define NTOH16(i) BCMSWAP16(i) -+#define ntoh16(i) bcmswap16(i) -+#define NTOH32(i) BCMSWAP32(i) -+#define ntoh32(i) bcmswap32(i) -+#define LTOH16(i) (i) -+#define ltoh16(i) (i) -+#define LTOH32(i) (i) -+#define ltoh32(i) (i) -+#define HTOL16(i) (i) -+#define htol16(i) (i) -+#define HTOL32(i) (i) -+#define htol32(i) (i) -+#else /* IL_BIGENDIAN */ -+#define HTON16(i) (i) -+#define hton16(i) (i) -+#define HTON32(i) (i) -+#define hton32(i) (i) -+#define NTOH16(i) (i) -+#define ntoh16(i) (i) -+#define NTOH32(i) (i) -+#define ntoh32(i) (i) -+#define LTOH16(i) BCMSWAP16(i) -+#define ltoh16(i) bcmswap16(i) -+#define LTOH32(i) BCMSWAP32(i) -+#define ltoh32(i) bcmswap32(i) -+#define HTOL16(i) BCMSWAP16(i) -+#define htol16(i) bcmswap16(i) -+#define HTOL32(i) BCMSWAP32(i) -+#define htol32(i) bcmswap32(i) -+#endif /* IL_BIGENDIAN */ -+#endif /* hton16 */ -+ -+#ifndef IL_BIGENDIAN -+#define ltoh16_buf(buf, i) -+#define htol16_buf(buf, i) -+#else -+#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) -+#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) -+#endif /* IL_BIGENDIAN */ -+ -+/* Unaligned loads and stores in host byte order */ -+#ifndef IL_BIGENDIAN -+#define load32_ua(a) ltoh32_ua(a) -+#define store32_ua(a, v) htol32_ua_store(v, a) -+#define load16_ua(a) ltoh16_ua(a) -+#define store16_ua(a, v) htol16_ua_store(v, a) -+#else -+#define load32_ua(a) ntoh32_ua(a) -+#define store32_ua(a, v) hton32_ua_store(v, a) -+#define load16_ua(a) ntoh16_ua(a) -+#define store16_ua(a, v) hton16_ua_store(v, a) -+#endif /* IL_BIGENDIAN */ -+ -+#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) -+#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) -+#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) -+#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) -+ -+#define ltoh_ua(ptr) \ -+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ -+ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ -+ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ -+ *(uint8 *)0) -+ -+#define ntoh_ua(ptr) \ -+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ -+ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ -+ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ -+ *(uint8 *)0) -+ -+#ifdef __GNUC__ -+ -+/* GNU macro versions avoid referencing the argument multiple times, while also -+ * avoiding the -fno-inline used in ROM builds. -+ */ -+ -+#define bcmswap16(val) ({ \ -+ uint16 _val = (val); \ -+ BCMSWAP16(_val); \ -+}) -+ -+#define bcmswap32(val) ({ \ -+ uint32 _val = (val); \ -+ BCMSWAP32(_val); \ -+}) -+ -+#define bcmswap32by16(val) ({ \ -+ uint32 _val = (val); \ -+ BCMSWAP32BY16(_val); \ -+}) -+ -+#define bcmswap16_buf(buf, len) ({ \ -+ uint16 *_buf = (uint16 *)(buf); \ -+ uint _wds = (len) / 2; \ -+ while (_wds--) { \ -+ *_buf = bcmswap16(*_buf); \ -+ _buf++; \ -+ } \ -+}) -+ -+#define htol16_ua_store(val, bytes) ({ \ -+ uint16 _val = (val); \ -+ uint8 *_bytes = (uint8 *)(bytes); \ -+ _bytes[0] = _val & 0xff; \ -+ _bytes[1] = _val >> 8; \ -+}) -+ -+#define htol32_ua_store(val, bytes) ({ \ -+ uint32 _val = (val); \ -+ uint8 *_bytes = (uint8 *)(bytes); \ -+ _bytes[0] = _val & 0xff; \ -+ _bytes[1] = (_val >> 8) & 0xff; \ -+ _bytes[2] = (_val >> 16) & 0xff; \ -+ _bytes[3] = _val >> 24; \ -+}) -+ -+#define hton16_ua_store(val, bytes) ({ \ -+ uint16 _val = (val); \ -+ uint8 *_bytes = (uint8 *)(bytes); \ -+ _bytes[0] = _val >> 8; \ -+ _bytes[1] = _val & 0xff; \ -+}) -+ -+#define hton32_ua_store(val, bytes) ({ \ -+ uint32 _val = (val); \ -+ uint8 *_bytes = (uint8 *)(bytes); \ -+ _bytes[0] = _val >> 24; \ -+ _bytes[1] = (_val >> 16) & 0xff; \ -+ _bytes[2] = (_val >> 8) & 0xff; \ -+ _bytes[3] = _val & 0xff; \ -+}) -+ -+#define ltoh16_ua(bytes) ({ \ -+ const uint8 *_bytes = (const uint8 *)(bytes); \ -+ _LTOH16_UA(_bytes); \ -+}) -+ -+#define ltoh32_ua(bytes) ({ \ -+ const uint8 *_bytes = (const uint8 *)(bytes); \ -+ _LTOH32_UA(_bytes); \ -+}) -+ -+#define ntoh16_ua(bytes) ({ \ -+ const uint8 *_bytes = (const uint8 *)(bytes); \ -+ _NTOH16_UA(_bytes); \ -+}) -+ -+#define ntoh32_ua(bytes) ({ \ -+ const uint8 *_bytes = (const uint8 *)(bytes); \ -+ _NTOH32_UA(_bytes); \ -+}) -+ -+#else /* !__GNUC__ */ -+ -+/* Inline versions avoid referencing the argument multiple times */ -+static INLINE uint16 -+bcmswap16(uint16 val) -+{ -+ return BCMSWAP16(val); -+} -+ -+static INLINE uint32 -+bcmswap32(uint32 val) -+{ -+ return BCMSWAP32(val); -+} -+ -+static INLINE uint32 -+bcmswap32by16(uint32 val) -+{ -+ return BCMSWAP32BY16(val); -+} -+ -+/* Reverse pairs of bytes in a buffer (not for high-performance use) */ -+/* buf - start of buffer of shorts to swap */ -+/* len - byte length of buffer */ -+static INLINE void -+bcmswap16_buf(uint16 *buf, uint len) -+{ -+ len = len / 2; -+ -+ while (len--) { -+ *buf = bcmswap16(*buf); -+ buf++; -+ } -+} -+ -+/* -+ * Store 16-bit value to unaligned little-endian byte array. -+ */ -+static INLINE void -+htol16_ua_store(uint16 val, uint8 *bytes) -+{ -+ bytes[0] = val & 0xff; -+ bytes[1] = val >> 8; -+} -+ -+/* -+ * Store 32-bit value to unaligned little-endian byte array. -+ */ -+static INLINE void -+htol32_ua_store(uint32 val, uint8 *bytes) -+{ -+ bytes[0] = val & 0xff; -+ bytes[1] = (val >> 8) & 0xff; -+ bytes[2] = (val >> 16) & 0xff; -+ bytes[3] = val >> 24; -+} -+ -+/* -+ * Store 16-bit value to unaligned network-(big-)endian byte array. -+ */ -+static INLINE void -+hton16_ua_store(uint16 val, uint8 *bytes) -+{ -+ bytes[0] = val >> 8; -+ bytes[1] = val & 0xff; -+} -+ -+/* -+ * Store 32-bit value to unaligned network-(big-)endian byte array. -+ */ -+static INLINE void -+hton32_ua_store(uint32 val, uint8 *bytes) -+{ -+ bytes[0] = val >> 24; -+ bytes[1] = (val >> 16) & 0xff; -+ bytes[2] = (val >> 8) & 0xff; -+ bytes[3] = val & 0xff; -+} -+ -+/* -+ * Load 16-bit value from unaligned little-endian byte array. -+ */ -+static INLINE uint16 -+ltoh16_ua(const void *bytes) -+{ -+ return _LTOH16_UA((const uint8 *)bytes); -+} -+ -+/* -+ * Load 32-bit value from unaligned little-endian byte array. -+ */ -+static INLINE uint32 -+ltoh32_ua(const void *bytes) -+{ -+ return _LTOH32_UA((const uint8 *)bytes); -+} -+ -+/* -+ * Load 16-bit value from unaligned big-(network-)endian byte array. -+ */ -+static INLINE uint16 -+ntoh16_ua(const void *bytes) -+{ -+ return _NTOH16_UA((const uint8 *)bytes); -+} -+ -+/* -+ * Load 32-bit value from unaligned big-(network-)endian byte array. -+ */ -+static INLINE uint32 -+ntoh32_ua(const void *bytes) -+{ -+ return _NTOH32_UA((const uint8 *)bytes); -+} -+ -+#endif /* !__GNUC__ */ -+#endif /* !_BCMENDIAN_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetmib.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetmib.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetmib.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetmib.h 2017-11-09 17:53:43.922294000 +0800 -@@ -0,0 +1,88 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Hardware-specific MIB definition for -+ * Broadcom Home Networking Division -+ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. -+ * -+ * $Id: bcmenetmib.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmenetmib_h_ -+#define _bcmenetmib_h_ -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+/* -+ * EMAC MIB Registers -+ */ -+typedef volatile struct { -+ uint32 tx_good_octets; -+ uint32 tx_good_pkts; -+ uint32 tx_octets; -+ uint32 tx_pkts; -+ uint32 tx_broadcast_pkts; -+ uint32 tx_multicast_pkts; -+ uint32 tx_len_64; -+ uint32 tx_len_65_to_127; -+ uint32 tx_len_128_to_255; -+ uint32 tx_len_256_to_511; -+ uint32 tx_len_512_to_1023; -+ uint32 tx_len_1024_to_max; -+ uint32 tx_jabber_pkts; -+ uint32 tx_oversize_pkts; -+ uint32 tx_fragment_pkts; -+ uint32 tx_underruns; -+ uint32 tx_total_cols; -+ uint32 tx_single_cols; -+ uint32 tx_multiple_cols; -+ uint32 tx_excessive_cols; -+ uint32 tx_late_cols; -+ uint32 tx_defered; -+ uint32 tx_carrier_lost; -+ uint32 tx_pause_pkts; -+ uint32 PAD[8]; -+ -+ uint32 rx_good_octets; -+ uint32 rx_good_pkts; -+ uint32 rx_octets; -+ uint32 rx_pkts; -+ uint32 rx_broadcast_pkts; -+ uint32 rx_multicast_pkts; -+ uint32 rx_len_64; -+ uint32 rx_len_65_to_127; -+ uint32 rx_len_128_to_255; -+ uint32 rx_len_256_to_511; -+ uint32 rx_len_512_to_1023; -+ uint32 rx_len_1024_to_max; -+ uint32 rx_jabber_pkts; -+ uint32 rx_oversize_pkts; -+ uint32 rx_fragment_pkts; -+ uint32 rx_missed_pkts; -+ uint32 rx_crc_align_errs; -+ uint32 rx_undersize; -+ uint32 rx_crc_errs; -+ uint32 rx_align_errs; -+ uint32 rx_symbol_errs; -+ uint32 rx_pause_pkts; -+ uint32 rx_nonpause_pkts; -+} bcmenetmib_t; -+ -+#endif /* _bcmenetmib_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetphy.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetphy.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetphy.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetphy.h 2017-11-09 17:53:43.923292000 +0800 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc Broadcom BCM47XX MDC/MDIO enet phy definitions. -+ * -+ * $Id: bcmenetphy.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmenetphy_h_ -+#define _bcmenetphy_h_ -+ -+/* phy address */ -+#define MAXEPHY 32 /* mdio phy addresses are 5bit quantities */ -+#define EPHY_MASK 0x1f /* phy mask */ -+#define EPHY_NONE 31 /* nvram: no phy present at all */ -+#define EPHY_NOREG 30 /* nvram: no local phy regs */ -+ -+#define MAXPHYREG 32 /* max 32 registers per phy */ -+ -+/* just a few phy registers */ -+#define CTL_RESET (1 << 15) /* reset */ -+#define CTL_LOOP (1 << 14) /* loopback */ -+#define CTL_SPEED (1 << 13) /* speed selection lsb 0=10, 1=100 */ -+#define CTL_ANENAB (1 << 12) /* autonegotiation enable */ -+#define CTL_RESTART (1 << 9) /* restart autonegotiation */ -+#define CTL_DUPLEX (1 << 8) /* duplex mode 0=half, 1=full */ -+#define CTL_SPEED_MSB (1 << 6) /* speed selection msb */ -+ -+#define CTL_SPEED_10 ((0 << 6) | (0 << 13)) /* speed selection CTL.6=0, CTL.13=0 */ -+#define CTL_SPEED_100 ((0 << 6) | (1 << 13)) /* speed selection CTL.6=0, CTL.13=1 */ -+#define CTL_SPEED_1000 ((1 << 6) | (0 << 13)) /* speed selection CTL.6=1, CTL.13=0 */ -+ -+#define ADV_10FULL (1 << 6) /* autonegotiate advertise 10full */ -+#define ADV_10HALF (1 << 5) /* autonegotiate advertise 10half */ -+#define ADV_100FULL (1 << 8) /* autonegotiate advertise 100full */ -+#define ADV_100HALF (1 << 7) /* autonegotiate advertise 100half */ -+#define ADV_PAUSE (1 << 10) /* autonegotiate advertise pause */ -+ -+/* link partner ability register */ -+#define LPA_SLCT 0x001f /* same as advertise selector */ -+#define LPA_10HALF 0x0020 /* can do 10mbps half-duplex */ -+#define LPA_10FULL 0x0040 /* can do 10mbps full-duplex */ -+#define LPA_100HALF 0x0080 /* can do 100mbps half-duplex */ -+#define LPA_100FULL 0x0100 /* can do 100mbps full-duplex */ -+#define LPA_100BASE4 0x0200 /* can do 100mbps 4k packets */ -+#define LPA_RFAULT 0x2000 /* link partner faulted */ -+#define LPA_LPACK 0x4000 /* link partner acked us */ -+#define LPA_NPAGE 0x8000 /* next page bit */ -+ -+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) -+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) -+ -+/* 1000BASE-T control register */ -+#define ADV_1000HALF 0x0100 /* advertise 1000BASE-T half duplex */ -+#define ADV_1000FULL 0x0200 /* advertise 1000BASE-T full duplex */ -+ -+/* 1000BASE-T status register */ -+#define LPA_1000HALF 0x0400 /* link partner 1000BASE-T half duplex */ -+#define LPA_1000FULL 0x0800 /* link partner 1000BASE-T full duplex */ -+ -+/* 1000BASE-T extended status register */ -+#define EST_1000THALF 0x1000 /* 1000BASE-T half duplex capable */ -+#define EST_1000TFULL 0x2000 /* 1000BASE-T full duplex capable */ -+#define EST_1000XHALF 0x4000 /* 1000BASE-X half duplex capable */ -+#define EST_1000XFULL 0x8000 /* 1000BASE-X full duplex capable */ -+ -+#define STAT_REMFAULT (1 << 4) /* remote fault */ -+#define STAT_LINK (1 << 2) /* link status */ -+#define STAT_JAB (1 << 1) /* jabber detected */ -+#define AUX_FORCED (1 << 2) /* forced 10/100 */ -+#define AUX_SPEED (1 << 1) /* speed 0=10mbps 1=100mbps */ -+#define AUX_DUPLEX (1 << 0) /* duplex 0=half 1=full */ -+ -+#endif /* _bcmenetphy_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetrxh.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetrxh.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetrxh.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmenetrxh.h 2017-11-09 17:53:43.927297000 +0800 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Hardware-specific Receive Data Header for the -+ * Broadcom Home Networking Division -+ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. -+ * -+ * $Id: bcmenetrxh.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmenetrxh_h_ -+#define _bcmenetrxh_h_ -+ -+/* -+ * The Ethernet MAC core returns an 8-byte Receive Frame Data Header -+ * with every frame consisting of -+ * 16bits of frame length, followed by -+ * 16bits of EMAC rx descriptor info, followed by 32bits of undefined. -+ */ -+typedef volatile struct { -+ uint16 len; -+ uint16 flags; -+ uint16 pad[12]; -+} bcmenetrxh_t; -+ -+#define RXHDR_LEN 28 /* Header length */ -+ -+#define RXF_L ((uint16)1 << 11) /* last buffer in a frame */ -+#define RXF_MISS ((uint16)1 << 7) /* received due to promisc mode */ -+#define RXF_BRDCAST ((uint16)1 << 6) /* dest is broadcast address */ -+#define RXF_MULT ((uint16)1 << 5) /* dest is multicast address */ -+#define RXF_LG ((uint16)1 << 4) /* frame length > rxmaxlength */ -+#define RXF_NO ((uint16)1 << 3) /* odd number of nibbles */ -+#define RXF_RXER ((uint16)1 << 2) /* receive symbol error */ -+#define RXF_CRC ((uint16)1 << 1) /* crc error */ -+#define RXF_OV ((uint16)1 << 0) /* fifo overflow */ -+ -+#endif /* _bcmenetrxh_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacmib.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacmib.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacmib.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacmib.h 2017-11-09 17:53:43.928296000 +0800 -@@ -0,0 +1,117 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Hardware-specific MIB definition for -+ * Broadcom Home Networking Division -+ * GbE Unimac core -+ * -+ * $Id: bcmgmacmib.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmgmacmib_h_ -+#define _bcmgmacmib_h_ -+ -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+/* GMAC MIB structure */ -+ -+typedef struct _gmacmib { -+ uint32 tx_good_octets; /* 0x300 */ -+ uint32 tx_good_octets_high; /* 0x304 */ -+ uint32 tx_good_pkts; /* 0x308 */ -+ uint32 tx_octets; /* 0x30c */ -+ uint32 tx_octets_high; /* 0x310 */ -+ uint32 tx_pkts; /* 0x314 */ -+ uint32 tx_broadcast_pkts; /* 0x318 */ -+ uint32 tx_multicast_pkts; /* 0x31c */ -+ uint32 tx_len_64; /* 0x320 */ -+ uint32 tx_len_65_to_127; /* 0x324 */ -+ uint32 tx_len_128_to_255; /* 0x328 */ -+ uint32 tx_len_256_to_511; /* 0x32c */ -+ uint32 tx_len_512_to_1023; /* 0x330 */ -+ uint32 tx_len_1024_to_1522; /* 0x334 */ -+ uint32 tx_len_1523_to_2047; /* 0x338 */ -+ uint32 tx_len_2048_to_4095; /* 0x33c */ -+ uint32 tx_len_4095_to_8191; /* 0x340 */ -+ uint32 tx_len_8192_to_max; /* 0x344 */ -+ uint32 tx_jabber_pkts; /* 0x348 */ -+ uint32 tx_oversize_pkts; /* 0x34c */ -+ uint32 tx_fragment_pkts; /* 0x350 */ -+ uint32 tx_underruns; /* 0x354 */ -+ uint32 tx_total_cols; /* 0x358 */ -+ uint32 tx_single_cols; /* 0x35c */ -+ uint32 tx_multiple_cols; /* 0x360 */ -+ uint32 tx_excessive_cols; /* 0x364 */ -+ uint32 tx_late_cols; /* 0x368 */ -+ uint32 tx_defered; /* 0x36c */ -+ uint32 tx_carrier_lost; /* 0x370 */ -+ uint32 tx_pause_pkts; /* 0x374 */ -+ uint32 tx_uni_pkts; /* 0x378 */ -+ uint32 tx_q0_pkts; /* 0x37c */ -+ uint32 tx_q0_octets; /* 0x380 */ -+ uint32 tx_q0_octets_high; /* 0x384 */ -+ uint32 tx_q1_pkts; /* 0x388 */ -+ uint32 tx_q1_octets; /* 0x38c */ -+ uint32 tx_q1_octets_high; /* 0x390 */ -+ uint32 tx_q2_pkts; /* 0x394 */ -+ uint32 tx_q2_octets; /* 0x398 */ -+ uint32 tx_q2_octets_high; /* 0x39c */ -+ uint32 tx_q3_pkts; /* 0x3a0 */ -+ uint32 tx_q3_octets; /* 0x3a4 */ -+ uint32 tx_q3_octets_high; /* 0x3a8 */ -+ uint32 PAD; -+ uint32 rx_good_octets; /* 0x3b0 */ -+ uint32 rx_good_octets_high; /* 0x3b4 */ -+ uint32 rx_good_pkts; /* 0x3b8 */ -+ uint32 rx_octets; /* 0x3bc */ -+ uint32 rx_octets_high; /* 0x3c0 */ -+ uint32 rx_pkts; /* 0x3c4 */ -+ uint32 rx_broadcast_pkts; /* 0x3c8 */ -+ uint32 rx_multicast_pkts; /* 0x3cc */ -+ uint32 rx_len_64; /* 0x3d0 */ -+ uint32 rx_len_65_to_127; /* 0x3d4 */ -+ uint32 rx_len_128_to_255; /* 0x3d8 */ -+ uint32 rx_len_256_to_511; /* 0x3dc */ -+ uint32 rx_len_512_to_1023; /* 0x3e0 */ -+ uint32 rx_len_1024_to_1522; /* 0x3e4 */ -+ uint32 rx_len_1523_to_2047; /* 0x3e8 */ -+ uint32 rx_len_2048_to_4095; /* 0x3ec */ -+ uint32 rx_len_4095_to_8191; /* 0x3f0 */ -+ uint32 rx_len_8192_to_max; /* 0x3f4 */ -+ uint32 rx_jabber_pkts; /* 0x3f8 */ -+ uint32 rx_oversize_pkts; /* 0x3fc */ -+ uint32 rx_fragment_pkts; /* 0x400 */ -+ uint32 rx_missed_pkts; /* 0x404 */ -+ uint32 rx_crc_align_errs; /* 0x408 */ -+ uint32 rx_undersize; /* 0x40c */ -+ uint32 rx_crc_errs; /* 0x410 */ -+ uint32 rx_align_errs; /* 0x414 */ -+ uint32 rx_symbol_errs; /* 0x418 */ -+ uint32 rx_pause_pkts; /* 0x41c */ -+ uint32 rx_nonpause_pkts; /* 0x420 */ -+ uint32 rx_sachanges; /* 0x424 */ -+ uint32 rx_uni_pkts; /* 0x428 */ -+} gmacmib_t; -+ -+#define GM_MIB_BASE 0x300 -+#define GM_MIB_LIMIT 0x800 -+ -+#endif /* _bcmgmacmib_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacrxh.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacrxh.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacrxh.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmgmacrxh.h 2017-11-09 17:53:43.929307000 +0800 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Hardware-specific Receive Data Header for the -+ * Broadcom Home Networking Division -+ * BCM47XX GbE cores. -+ * -+ * $Id: bcmgmacrxh.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmgmacrxh_h_ -+#define _bcmgmacrxh_h_ -+ -+/* -+ * The Ethernet GMAC core returns an 8-byte Receive Frame Data Header -+ * with every frame consisting of -+ * 16 bits of frame length, followed by -+ * 16 bits of GMAC rx descriptor info, followed by 32bits of undefined. -+ */ -+typedef volatile struct { -+ uint16 len; -+ uint16 flags; -+ uint16 pad[12]; -+} bcmgmacrxh_t; -+ -+#define RXHDR_LEN 28 /* Header length */ -+ -+#define GRXF_DT_MASK ((uint16)0xf) /* data type */ -+#define GRXF_DT_SHIFT 12 -+#define GRXF_DC_MASK ((uint16)0xf) /* (num descr to xfer the frame) - 1 */ -+#define GRXF_DC_SHIFT 8 -+#define GRXF_OVF ((uint16)1 << 7) /* overflow error occured */ -+#define GRXF_CTFERR ((uint16)1 << 6) /* overflow error occured */ -+#define GRXF_OVERSIZE ((uint16)1 << 4) /* frame size > rxmaxlength */ -+#define GRXF_CRC ((uint16)1 << 3) /* crc error */ -+#define GRXF_VLAN ((uint16)1 << 2) /* vlan tag detected */ -+#define GRXF_PT_MASK ((uint16)3) /* packet type 0 - Unicast, -+ * 1 - Multicast, 2 - Broadcast -+ */ -+ -+#endif /* _bcmgmacrxh_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_egphy28.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_egphy28.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_egphy28.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_egphy28.h 2017-11-09 17:53:43.930299000 +0800 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _EGPHY28_H_ -+#define _EGPHY28_H_ -+ -+#define EGPHY28_REG_RDB_ADDR 0x1e -+#define EGPHY28_REG_RDB_DATA 0x1f -+ -+#define EGPHY28_RDB_ACCESS_ADDR_1 0x17 -+#define EGPHY28_RDB_ACCESS_DATA_1 0x0f7e -+#define EGPHY28_RDB_ACCESS_ADDR_2 0x15 -+#define EGPHY28_RDB_ACCESS_DATA_2 0x0000 -+ -+/* Generic MII registers */ -+#define EGPHY28_COPPER_MII_CTRL 0x00 -+#define EGPHY28_PHY_ID_MSB 0x02 /* PHY ID MSB */ -+#define EGPHY28_PHY_ID_LSB 0x03 /* PHY ID LSB */ -+#define EGPHY28_MII_ADVERTISE 0x04 /* Advertisement control reg */ -+#define EGPHY28_MII_CTRL1000 0x09 /* 1000BASE-T control */ -+#define EGPGY28_MII_ECONTROL 0x10 /* Extended Control */ -+#define EGPHY28_COPPER_MISC_CTRL 0x2f /* COPPER MISC CONTROL */ -+ -+/* For EGPHY28_COPPER_MII_CTRL(0x00) */ -+#define BMCR_FULLDPLX 0x0100 /* Full duplex */ -+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ -+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ -+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ -+#define BMCR_PDOWN 0x0800 /* Powerdown EGPHY28 */ -+#define BMCR_RESET 0x8000 /* Reset EGPHY28 */ -+ -+/* For EGPHY28_MII_ADVERTISE(0x04) */ -+#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ -+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ -+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ -+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ -+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ -+ -+/* For EGPHY28_MII_CTRL1000(0x09) */ -+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ -+#define REPEATER_DTE 0x0400 /* Repeater/switch or DTE port type */ -+ -+/* For EGPHY28_COPPER_MISC_CTRL(0x2f) */ -+#define BMCR_FORCE_AUTO_MDIX 0x0200 -+ -+extern int egphy28_enable_set(u32 phy_addr, int enable); -+extern int egphy28_init(void __iomem *base, u32 phy_addr); -+extern int egphy28_enable_set(u32 phy_addr, int enable); -+extern int egphy28_force_auto_mdix(u32 phy_addr, int enable); -+ -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy.h 2017-11-09 17:53:43.931300000 +0800 -@@ -0,0 +1,290 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _bcm_iproc_phy_h_ -+#define _bcm_iproc_phy_h_ -+ -+ -+#define PHY_ADDR_MASK 0x00001F -+#define PHY_BUS_MASK 0x000020 -+#define PHY_BANK_MASK 0x001F00 -+#define PHY_FLAG_MASK 0xFF0000 -+#define PHY_ADDR(_flag, _bank, _bus, _addr) \ -+ (((_flag << 16) & PHY_FLAG_MASK) | ((_bank << 8) & PHY_BANK_MASK) | \ -+ ((_bus << 5) & PHY_BUS_MASK) | ((_addr << 0) & PHY_ADDR_MASK)) -+ -+#define PHY_REG_ADDR(_addr) ((_addr & PHY_ADDR_MASK) >> 0) -+#define PHY_REG_BUS(_addr) ((_addr & PHY_BUS_MASK) >> 5) -+#define PHY_REG_BANK(_addr) ((_addr & PHY_BANK_MASK) >> 8) -+#define PHY_REG_FLAGS(_addr) ((_addr & PHY_FLAG_MASK) >> 16) -+ -+/* Flags for phy register */ -+#define PHY_REG_FLAGS_NONE (0) -+#define PHY_REG_FLAGS_1000X (1 << 0) -+#define PHY_REG_FLAGS_PRI_SERDES (1 << 1) -+#define PHY_REG_FLAGS_RDB (1 << 2) -+#define PHY_REG_FLAGS_QSGMII (1 << 3) -+#define PHY_REG_FLAGS_FIBER (PHY_REG_FLAGS_1000X | \ -+ PHY_REG_FLAGS_PRI_SERDES) -+ -+typedef enum { -+ SOC_E_NONE = 0, -+ SOC_E_INTERNAL = -1, -+ SOC_E_MEMORY = -2, -+ SOC_E_UNIT = -3, -+ SOC_E_PARAM = -4, -+ SOC_E_EMPTY = -5, -+ SOC_E_FULL = -6, -+ SOC_E_NOT_FOUND = -7, -+ SOC_E_EXISTS = -8, -+ SOC_E_TIMEOUT = -9, -+ SOC_E_BUSY = -10, -+ SOC_E_FAIL = -11, -+ SOC_E_DISABLED = -12, -+ SOC_E_BADID = -13, -+ SOC_E_RESOURCE = -14, -+ SOC_E_CONFIG = -15, -+ SOC_E_UNAVAIL = -16, -+ SOC_E_INIT = -17, -+ SOC_E_PORT = -18, -+ -+ SOC_E_LIMIT = -19 /* Must come last */ -+} soc_error_t; -+ -+#define SOC_SUCCESS(rv) ((rv) >= 0) -+#define SOC_FAILURE(rv) ((rv) < 0) -+ -+typedef enum _soc_port_if_e { -+ SOC_PORT_IF_NOCXN, /* No physical connection */ -+ SOC_PORT_IF_NULL, /* Pass-through connection without PHY */ -+ SOC_PORT_IF_MII, -+ SOC_PORT_IF_GMII, -+ SOC_PORT_IF_SGMII, -+ SOC_PORT_IF_TBI, -+ SOC_PORT_IF_XGMII, -+ SOC_PORT_IF_RGMII, -+ SOC_PORT_IF_RvMII, -+ SOC_PORT_IF_SFI, -+ SOC_PORT_IF_XFI, -+ SOC_PORT_IF_KR, -+ SOC_PORT_IF_KR4, -+ SOC_PORT_IF_CR, -+ SOC_PORT_IF_CR4, -+ SOC_PORT_IF_XLAUI, -+ SOC_PORT_IF_SR, -+ SOC_PORT_IF_RXAUI, -+ SOC_PORT_IF_XAUI, -+ SOC_PORT_IF_SPAUI, -+ SOC_PORT_IF_QSGMII, -+ SOC_PORT_IF_ILKN, -+ SOC_PORT_IF_RCY, -+ SOC_PORT_IF_FAT_PIPE, -+ SOC_PORT_IF_CGMII, -+ SOC_PORT_IF_CAUI, -+ SOC_PORT_IF_LR, -+ SOC_PORT_IF_LR4, -+ SOC_PORT_IF_SR4, -+ SOC_PORT_IF_KX, -+ SOC_PORT_IF_CPU, -+ SOC_PORT_IF_OLP, -+ SOC_PORT_IF_OAMP, -+ SOC_PORT_IF_ERP, -+ SOC_PORT_IF_COUNT /* last, please */ -+} _soc_port_if_t; -+typedef _soc_port_if_t soc_port_if_t; -+ -+ -+/* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register (Addr 00h) */ -+#define PHY_MII_CTRLr_FLAGS 0x00 -+#define PHY_MII_CTRLr_BANK 0x0000 -+#define PHY_MII_CTRLr_ADDR 0x00 -+/* 1000BASE-T/100BASE-TX/10BASE-T MII Status Register (ADDR 01h) */ -+#define PHY_MII_STATr_FLAGS 0x00 -+#define PHY_MII_STATr_BANK 0x0000 -+#define PHY_MII_STATr_ADDR 0x01 -+/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 02h) */ -+#define PHY_MII_PHY_ID0r_FLAGS _SOC_PHY_REG_DIRECT -+#define PHY_MII_PHY_ID0r_BANK 0x0000 -+#define PHY_MII_PHY_ID0r_ADDR 0x02 -+/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 03h) */ -+#define PHY_MII_PHY_ID1r_FLAGS _SOC_PHY_REG_DIRECT -+#define PHY_MII_PHY_ID1r_BANK 0x0000 -+#define PHY_MII_PHY_ID1r_ADDR 0x03 -+/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Advertisment Register (ADDR 04h) */ -+#define PHY_MII_ANAr_FLAGS 0x00 -+#define PHY_MII_ANAr_BANK 0x0000 -+#define PHY_MII_ANAr_ADDR 0x04 -+/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Link Partner Ability (ADDR 05h) */ -+#define PHY_MII_ANPr_FLAGS 0x00 -+#define PHY_MII_ANPr_BANK 0x0000 -+#define PHY_MII_ANPr_ADDR 0x05 -+/* 1000BASE-T Control Register (ADDR 09h) */ -+#define PHY_MII_GB_CTRLr_FLAGS 0x00 -+#define PHY_MII_GB_CTRLr_BANK 0x0000 -+#define PHY_MII_GB_CTRLr_ADDR 0x09 -+/* 1000BASE-T Status Register (ADDR 0ah) */ -+#define PHY_MII_GB_STATr_FLAGS 0x00 -+#define PHY_MII_GB_STATr_BANK 0x0000 -+#define PHY_MII_GB_STATr_ADDR 0x0a -+/* 1000BASE-T/100BASE-TX/10BASE-T IEEE Extended Status Register (ADDR 0fh) */ -+#define PHY_MII_ESRr_FLAGS 0x00 -+#define PHY_MII_ESRr_BANK 0x0000 -+#define PHY_MII_ESRr_ADDR 0x0f -+/* 1000BASE-T/100BASE-TX/10BASE-T PHY Extended Control Register (ADDR 10h) */ -+#define PHY_MII_ECRr_FLAGS 0x00 -+#define PHY_MII_ECRr_BANK 0x0000 -+#define PHY_MII_ECRr_ADDR 0x10 -+/* 1000BASE-T/100BASE-TX/10BASE-T Auxiliary Control Reg (ADDR 18h Shadow 000)*/ -+#define PHY_MII_AUX_CTRLr_FLAGS 0x00 -+#define PHY_MII_AUX_CTRLr_BANK 0x0000 -+#define PHY_MII_AUX_CTRLr_ADDR 0x18 -+/* 1000BASE-T/100BASE-TX/10BASE-T Power/MII Control Reg (ADDR 18h Shadow 010)*/ -+#define PHY_MII_POWER_CTRLr_FLAGS 0x00 -+#define PHY_MII_POWER_CTRLr_BANK 0x0002 -+#define PHY_MII_POWER_CTRLr_ADDR 0x18 -+/* 1000BASE-T/100BASE-TX/10BASE-T Misc Control Reg (ADDR 18h Shadow 111)*/ -+#define PHY_MII_MISC_CTRLr_FLAGS 0x00 -+#define PHY_MII_MISC_CTRLr_BANK 0x0007 -+#define PHY_MII_MISC_CTRLr_ADDR 0x18 -+/* Auxiliary 1000BASE-X Control Reg (ADDR 1ch shadow 11011) */ -+#define PHY_AUX_1000X_CTRLr_FLAGS 0x00 -+#define PHY_AUX_1000X_CTRLr_BANK 0x001B -+#define PHY_AUX_1000X_CTRLr_ADDRS 0x1c -+/* Mode Control Reg (ADDR 1ch shadow 11111) */ -+#define PHY_MODE_CTRLr_FLAGS 0x00 -+#define PHY_MODE_CTRLr_BANK 0x001F -+#define PHY_MODE_CTRLr_ADDR 0x1c -+ -+/* -+ * Primary SerDes Registers -+ */ -+/* 1000BASE-X MII Control Register (Addr 00h) */ -+#define PHY_1000X_MII_CTRLr_FLAGS SOC_PHY_REG_1000X -+#define PHY_1000X_MII_CTRLr_BANK 0x0000 -+#define PHY_1000X_MII_CTRLr_ADDR 0x00 -+ -+ -+/* MII Control Register: bit definitions */ -+#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ -+#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ -+#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ -+#define MII_CTRL_FD (1 << 8) /* Full Duplex */ -+#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ -+#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ -+#define MII_CTRL_PD (1 << 11) /* Power Down */ -+#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ -+#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ -+#define MII_CTRL_LE (1 << 14) /* Loopback enable */ -+#define MII_CTRL_RESET (1 << 15) /* PHY reset */ -+ -+#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) -+#define MII_CTRL_SS_10 0 -+#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) -+#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) -+#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) -+#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) -+ -+/* -+ * MII Status Register: See 802.3, 1998 pg 544 -+ */ -+#define MII_STAT_EXT (1 << 0) /* Extended Registers */ -+#define MII_STAT_JBBR (1 << 1) /* Jabber Detected */ -+#define MII_STAT_LA (1 << 2) /* Link Active */ -+#define MII_STAT_AN_CAP (1 << 3) /* Autoneg capable */ -+#define MII_STAT_RF (1 << 4) /* Remote Fault */ -+#define MII_STAT_AN_DONE (1 << 5) /* Autoneg complete */ -+#define MII_STAT_MF_PS (1 << 6) /* Preamble suppression */ -+#define MII_STAT_ES (1 << 8) /* Extended status (R15) */ -+#define MII_STAT_HD_100_T2 (1 << 9) /* Half duplex 100Mb/s supported */ -+#define MII_STAT_FD_100_T2 (1 << 10)/* Full duplex 100Mb/s supported */ -+#define MII_STAT_HD_10 (1 << 11)/* Half duplex 100Mb/s supported */ -+#define MII_STAT_FD_10 (1 << 12)/* Full duplex 100Mb/s supported */ -+#define MII_STAT_HD_100 (1 << 13)/* Half duplex 100Mb/s supported */ -+#define MII_STAT_FD_100 (1 << 14)/* Full duplex 100Mb/s supported */ -+#define MII_STAT_100_T4 (1 << 15)/* Full duplex 100Mb/s supported */ -+ -+/* -+ * MII Link Advertisment -+ */ -+#define MII_ANA_ASF (1 << 0)/* Advertise Selector Field */ -+#define MII_ANA_HD_10 (1 << 5)/* Half duplex 10Mb/s supported */ -+#define MII_ANA_FD_1000X (1 << 5)/* Full duplex for 1000BASE-X */ -+#define MII_ANA_FD_10 (1 << 6)/* Full duplex 10Mb/s supported */ -+#define MII_ANA_HD_1000X (1 << 6)/* Half duplex for 1000BASE-X */ -+#define MII_ANA_HD_100 (1 << 7)/* Half duplex 100Mb/s supported */ -+#define MII_ANA_1000X_PAUSE (1 << 7)/* Pause supported for 1000BASE-X */ -+#define MII_ANA_FD_100 (1 << 8)/* Full duplex 100Mb/s supported */ -+#define MII_ANA_1000X_ASYM_PAUSE (1 << 8)/* Asymmetric pause supported for 1000BASE-X */ -+#define MII_ANA_T4 (1 << 9)/* T4 */ -+#define MII_ANA_PAUSE (1 << 10)/* Pause supported */ -+#define MII_ANA_ASYM_PAUSE (1 << 11)/* Asymmetric pause supported */ -+#define MII_ANA_RF (1 << 13)/* Remote fault */ -+#define MII_ANA_NP (1 << 15)/* Next Page */ -+ -+#define MII_ANA_ASF_802_3 (1) /* 802.3 PHY */ -+ -+/* -+ * 1000Base-T Control Register -+ */ -+#define MII_GB_CTRL_MS_MAN (1 << 12) /* Manual Master/Slave mode */ -+#define MII_GB_CTRL_MS (1 << 11) /* Master/Slave negotiation mode */ -+#define MII_GB_CTRL_PT (1 << 10) /* Port type */ -+#define MII_GB_CTRL_ADV_1000FD (1 << 9) /* Advertise 1000Base-T FD */ -+#define MII_GB_CTRL_ADV_1000HD (1 << 8) /* Advertise 1000Base-T HD */ -+ -+/* -+ * 1000Base-T Status Register -+ */ -+#define MII_GB_STAT_MS_FAULT (1 << 15) /* Master/Slave Fault */ -+#define MII_GB_STAT_MS (1 << 14) /* Master/Slave, 1 == Master */ -+#define MII_GB_STAT_LRS (1 << 13) /* Local receiver status */ -+#define MII_GB_STAT_RRS (1 << 12) /* Remote receiver status */ -+#define MII_GB_STAT_LP_1000FD (1 << 11) /* Link partner 1000FD capable */ -+#define MII_GB_STAT_LP_1000HD (1 << 10) /* Link partner 1000HD capable */ -+#define MII_GB_STAT_IDE (0xff << 0) /* Idle error count */ -+ -+/* -+ * IEEE Extended Status Register -+ */ -+#define MII_ESR_1000_X_FD (1 << 15) /* 1000Base-T FD capable */ -+#define MII_ESR_1000_X_HD (1 << 14) /* 1000Base-T HD capable */ -+#define MII_ESR_1000_T_FD (1 << 13) /* 1000Base-T FD capable */ -+#define MII_ESR_1000_T_HD (1 << 12) /* 1000Base-T FD capable */ -+ -+/* MII Extended Control Register (BROADCOM) */ -+#define MII_ECR_FE (1 << 0) /* FIFO Elasticity */ -+#define MII_ECR_TLLM (1 << 1) /* Three link LED mode */ -+#define MII_ECR_ET_IPG (1 << 2) /* Extended XMIT IPG mode */ -+#define MII_ECR_FLED_OFF (1 << 3) /* Force LED off */ -+#define MII_ECR_FLED_ON (1 << 4) /* Force LED on */ -+#define MII_ECR_ELT (1 << 5) /* Enable LED traffic */ -+#define MII_ECR_RS (1 << 6) /* Reset Scrambler */ -+#define MII_ECR_BRSA (1 << 7) /* Bypass Receive Sym. align */ -+#define MII_ECR_BMLT3 (1 << 8) /* Bypass MLT3 Encoder/Decoder */ -+#define MII_ECR_BSD (1 << 9) /* Bypass Scramble/Descramble */ -+#define MII_ECR_B4B5B (1 << 10) /* Bypass 4B/5B Encode/Decode */ -+#define MII_ECR_FI (1 << 11) /* Force Interrupt */ -+#define MII_ECR_ID (1 << 12) /* Interrupt Disable */ -+#define MII_ECR_TD (1 << 13) /* XMIT Disable */ -+#define MII_ECR_DAMC (1 << 14) /* DIsable Auto-MDI Crossover */ -+#define MII_ECR_10B (1 << 15) /* 1 == 10B, 0 == GMII */ -+ -+/* MISC Control Register (Addr 18h, Shadow Value 111) */ -+#define MII_FORCED_AUTO_MDIX (1 << 9) /* 1 == AUTO-MDIX enabled when AN disabled */ -+#endif /* _bcm_iproc_phy_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5221.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5221.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5221.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5221.h 2017-11-09 17:53:43.932294000 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _bcm_iproc_phy5221_h_ -+#define _bcm_iproc_phy5221_h_ -+ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+ -+#define PHY_AUX_MULTIPLE_PHYr_BANK 0x0000 -+#define PHY_AUX_MULTIPLE_PHYr_ADDR 0x1e -+ -+#define PHY522X_SUPER_ISOLATE_MODE (1<<3) -+ -+/* ---- External Function Prototypes ------------------------------------- */ -+ -+extern int phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask); -+extern int phy5221_init(uint eth_num, uint phyaddr); -+extern int phy5221_link_get(uint eth_num, uint phyaddr, int *link); -+extern int phy5221_enable_set(uint eth_num, uint phyaddr, int enable); -+extern int phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); -+ -+#endif /* _bcm_iproc_phy5221_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5461s.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5461s.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5461s.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5461s.h 2017-11-09 17:53:43.933291000 +0800 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _bcm_iproc_phy5461s_h_ -+#define _bcm_iproc_phy5461s_h_ -+ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+ -+/* Indirect PHY register address flags */ -+#define SOC_PHY_REG_RESERVE_ACCESS 0x20000000 -+#define SOC_PHY_REG_1000X 0x40000000 -+#define SOC_PHY_REG_INDIRECT 0x80000000 -+#define _SOC_PHY_REG_DIRECT ((SOC_PHY_REG_1000X << 1) | (SOC_PHY_REG_1000X >> 1)) -+ -+/* ---- External Function Prototypes ------------------------------------- */ -+ -+extern int phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask); -+extern int phy5461_init(uint eth_num, uint phyaddr); -+extern int phy5461_link_get(uint eth_num, uint phyaddr, int *link); -+extern int phy5461_enable_set(uint eth_num, uint phyaddr, int enable); -+extern int phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); -+ -+#endif /* _bcm_iproc_phy5461s_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5481.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5481.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5481.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_phy5481.h 2017-11-09 17:53:43.933313000 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _bcm_iproc_phy5481_h_ -+#define _bcm_iproc_phy5481_h_ -+ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+ -+// #define PHY_AUX_MULTIPLE_PHYr_BANK 0x0000 -+// #define PHY_AUX_MULTIPLE_PHYr_ADDR 0x1e -+ -+#define PHY5481_SUPER_ISOLATE_MODE (1U<<5) -+ -+/* ---- External Function Prototypes ------------------------------------- */ -+ -+extern int phy5481_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5481_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data); -+extern int phy5481_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask); -+extern int phy5481_init(uint eth_num, uint phyaddr); -+extern int phy5481_link_get(uint eth_num, uint phyaddr, int *link); -+extern int phy5481_enable_set(uint eth_num, uint phyaddr, int enable); -+extern int phy5481_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); -+ -+#endif /* _bcm_iproc_phy5481_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes.h 2017-11-09 17:53:43.934297000 +0800 -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the serdes -+ * -+ */ -+ -+#ifndef _bcm_iproc_serdes_h_ -+#define _bcm_iproc_serdes_h_ -+ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+ -+#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ -+ -+/* -+ * MII Link Advertisment (Clause 37) -+ */ -+#define MII_ANA_C37_NP (1 << 15) /* Next Page */ -+#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ -+#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ -+#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ -+#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ -+#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ -+#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ -+#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ -+#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ -+ -+/* MII Control Register: bit definitions */ -+ -+#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ -+#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ -+#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ -+#define MII_CTRL_FD (1 << 8) /* Full Duplex */ -+#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ -+#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ -+#define MII_CTRL_PD (1 << 11) /* Power Down */ -+#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ -+#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ -+#define MII_CTRL_LE (1 << 14) /* Loopback enable */ -+#define MII_CTRL_RESET (1 << 15) /* PHY reset */ -+ -+#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) -+#define MII_CTRL_SS_10 0 -+#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) -+#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) -+#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) -+#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) -+ -+/* ---- External Function Prototypes ------------------------------------- */ -+ -+extern void serdes_set_blk(uint eth_num, uint phyaddr, uint blk); -+extern void serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data); -+extern uint16 serdes_rd_reg(uint eth_num, uint phyaddr, uint reg); -+extern uint16 serdes_get_id(uint eth_num, uint phyaddr, uint off); -+extern void serdes_reset(uint eth_num, uint phyaddr); -+extern int serdes_reset_core(uint eth_num, uint phyaddr); -+extern int serdes_start_pll(uint eth_num, uint phyaddr); -+extern int serdes_init(uint eth_num, uint phyaddr); -+#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) -+extern int serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx); -+extern int serdes_set_asym_mode(uint eth_num, uint phyaddr); -+#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ -+ -+#endif /* _bcm_iproc_serdes_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes_def.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes_def.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes_def.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmiproc_serdes_def.h 2017-11-09 17:53:43.935301000 +0800 -@@ -0,0 +1,328 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These are serdes defines -+ * -+ */ -+ -+#ifndef _PHY_XGXS16G_H_ -+#define _PHY_XGXS16G_H_ -+ -+/* macros */ -+ -+/* Macros ONLY used after initialization */ -+#define XGXS16G_2p5G_ID(id2) ((id2 & 0xff) == 0xf) -+ -+ -+/****************************************************************************/ -+/***** Starting below is auto-generated register macros from RDB files *****/ -+/****************************************************************************/ -+ -+/**************************************************************************** -+ * Core Enums. -+ ***************************************************************************/ -+ -+#define XGXS16G_IEEE0BLK_IEEECONTROL0r 0x00000000 -+#define XGXS16G_XGXSBLK0_XGXSCONTROLr 0x00008000 -+#define XGXS16G_XGXSBLK0_XGXSSTATUSr 0x00008001 -+#define XGXS16G_XGXSBLK0_MMDSELECTr 0x0000800d -+#define XGXS16G_XGXSBLK0_MISCCONTROL1r 0x0000800e -+#define XGXS16G_XGXSBLK1_LANECTRL0r 0x00008015 -+#define XGXS16G_XGXSBLK1_LANECTRL1r 0x00008016 -+#define XGXS16G_XGXSBLK1_LANECTRL3r 0x00008018 -+#define XGXS16G_TX0_TX_ACONTROL0r 0x00008061 -+#define XGXS16G_RX0_RX_CONTROLr 0x000080b1 -+#define XGXS16G_AN73_PDET_PARDET10GCONTROLr 0x00008131 -+#define XGXS16G_XGXSBLK7_EEECONTROLr 0x00008150 -+#define XGXS16G_TX_LN_SWAP1r 0x00008169 -+#define XGXS16G_SERDESDIGITAL_CONTROL1000X1r 0x00008300 -+#define XGXS16G_SERDESDIGITAL_CONTROL1000X2r 0x00008301 -+#define XGXS16G_SERDESDIGITAL_CONTROL1000X3r 0x00008302 -+#define XGXS16G_SERDESDIGITAL_STATUS1000X1r 0x00008304 -+#define XGXS16G_SERDESDIGITAL_MISC1r 0x00008308 -+#define XGXS16G_SERDESID_SERDESID0r 0x00008310 -+#define XGXS16G_SERDESID_SERDESID1r 0x00008311 -+#define XGXS16G_SERDESID_SERDESID2r 0x00008312 -+#define XGXS16G_SERDESID_SERDESID3r 0x00008313 -+#define XGXS16G_REMOTEPHY_MISC3r 0x0000833c -+#define XGXS16G_REMOTEPHY_MISC5r 0x0000833e -+#define XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr 0x00008350 -+#define XGXS16G_BAM_NEXTPAGE_UD_FIELDr 0x00008357 -+#define XGXS16G_COMBO_IEEE0_MIICNTLr 0x0000ffe0 -+#define XGXS16G_COMBO_IEEE0_AUTONEGADVr 0x0000ffe4 -+ -+#define WC40_DIGITAL4_MISC3r 0x0000833c -+ -+/* Digital4 :: Misc3 :: laneDisable [06:06] */ -+#define DIGITAL4_MISC3_LANEDISABLE_MASK 0x0040 -+#define DIGITAL4_MISC3_LANEDISABLE_ALIGN 0 -+#define DIGITAL4_MISC3_LANEDISABLE_BITS 1 -+#define DIGITAL4_MISC3_LANEDISABLE_SHIFT 6 -+ -+ -+/**************************************************************************** -+ * XGXS16G_IEEE_ieee0Blk -+ ***************************************************************************/ -+/**************************************************************************** -+ * ieee0Blk :: ieeeControl0 -+ ***************************************************************************/ -+/* ieee0Blk :: ieeeControl0 :: rst_hw [15:15] */ -+#define IEEE0BLK_IEEECONTROL0_RST_HW_MASK 0x8000 -+#define IEEE0BLK_IEEECONTROL0_RST_HW_ALIGN 0 -+#define IEEE0BLK_IEEECONTROL0_RST_HW_BITS 1 -+#define IEEE0BLK_IEEECONTROL0_RST_HW_SHIFT 15 -+ -+/* ieee0Blk :: ieeeControl0 :: gloopback [14:14] */ -+#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK 0x4000 -+#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_ALIGN 0 -+#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_BITS 1 -+#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_SHIFT 14 -+ -+ -+/**************************************************************************** -+ * XGXS16G_USER_XgxsBlk0 -+ ***************************************************************************/ -+/**************************************************************************** -+ * XgxsBlk0 :: xgxsControl -+ ***************************************************************************/ -+/* XgxsBlk0 :: xgxsControl :: start_sequencer [13:13] */ -+#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK 0x2000 -+#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_SHIFT 13 -+ -+/* XgxsBlk0 :: xgxsControl :: mode_10g [11:08] */ -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_MASK 0x0f00 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_BITS 4 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT 8 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS 0 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noCC 1 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane 6 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss 8 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss_noCC 9 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass 10 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass_noDsk 11 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode 12 -+#define XGXSBLK0_XGXSCONTROL_MODE_10G_ClocksOff 15 -+ -+/* XgxsBlk0 :: xgxsControl :: hstl [05:05] */ -+#define XGXSBLK0_XGXSCONTROL_HSTL_MASK 0x0020 -+#define XGXSBLK0_XGXSCONTROL_HSTL_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_HSTL_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_HSTL_SHIFT 5 -+ -+/* XgxsBlk0 :: xgxsControl :: cdet_en [03:03] */ -+#define XGXSBLK0_XGXSCONTROL_CDET_EN_MASK 0x0008 -+#define XGXSBLK0_XGXSCONTROL_CDET_EN_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_CDET_EN_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_CDET_EN_SHIFT 3 -+ -+/* XgxsBlk0 :: xgxsControl :: eden [02:02] */ -+#define XGXSBLK0_XGXSCONTROL_EDEN_MASK 0x0004 -+#define XGXSBLK0_XGXSCONTROL_EDEN_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_EDEN_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_EDEN_SHIFT 2 -+ -+/* XgxsBlk0 :: xgxsControl :: afrst_en [01:01] */ -+#define XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK 0x0002 -+#define XGXSBLK0_XGXSCONTROL_AFRST_EN_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_AFRST_EN_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_AFRST_EN_SHIFT 1 -+ -+/* XgxsBlk0 :: xgxsControl :: txcko_div [00:00] */ -+#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK 0x0001 -+#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_ALIGN 0 -+#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_BITS 1 -+#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_SHIFT 0 -+ -+ -+/**************************************************************************** -+ * XgxsBlk0 :: xgxsStatus -+ ***************************************************************************/ -+/* XgxsBlk0 :: xgxsStatus :: txpll_lock [11:11] */ -+#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK 0x0800 -+#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_ALIGN 0 -+#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_BITS 1 -+#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_SHIFT 11 -+ -+ -+/**************************************************************************** -+ * XgxsBlk0 :: miscControl1 -+ ***************************************************************************/ -+/* XgxsBlk0 :: miscControl1 :: PCS_dev_en_override [10:10] */ -+#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK 0x0400 -+#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_ALIGN 0 -+#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_BITS 1 -+#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_SHIFT 10 -+ -+/* XgxsBlk0 :: miscControl1 :: PMD_dev_en_override [09:09] */ -+#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK 0x0200 -+#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_ALIGN 0 -+#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_BITS 1 -+#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_SHIFT 9 -+ -+/* XgxsBlk0 :: miscControl1 :: ieee_blksel_autodet [01:01] */ -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK 0x0002 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_ALIGN 0 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_BITS 1 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_SHIFT 1 -+ -+/* XgxsBlk0 :: miscControl1 :: ieee_blksel_val [00:00] */ -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK 0x0001 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_ALIGN 0 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_BITS 1 -+#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_SHIFT 0 -+ -+ -+/**************************************************************************** -+ * XGXS16G_USER_XgxsBlk1 -+ ***************************************************************************/ -+/**************************************************************************** -+ * XgxsBlk1 :: laneCtrl0 -+ ***************************************************************************/ -+/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_rx [07:04] */ -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK 0x00f0 -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_ALIGN 0 -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_BITS 4 -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_SHIFT 4 -+ -+/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_tx [03:00] */ -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK 0x000f -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_ALIGN 0 -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_BITS 4 -+#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_SHIFT 0 -+ -+ -+/**************************************************************************** -+ * XGXS16G_USER_TX0 -+ ***************************************************************************/ -+/**************************************************************************** -+ * TX0 :: Tx_AControl0 -+ ***************************************************************************/ -+/* TX0 :: Tx_AControl0 :: txpol_flip [05:05] */ -+#define TX0_TX_ACONTROL0_TXPOL_FLIP_MASK 0x0020 -+#define TX0_TX_ACONTROL0_TXPOL_FLIP_ALIGN 0 -+#define TX0_TX_ACONTROL0_TXPOL_FLIP_BITS 1 -+#define TX0_TX_ACONTROL0_TXPOL_FLIP_SHIFT 5 -+ -+ -+/**************************************************************************** -+ * XGXS16G_USER_dsc_2_0 -+ ***************************************************************************/ -+/**************************************************************************** -+ * dsc_2_0 :: dsc_ctrl0 -+ ***************************************************************************/ -+/* dsc_2_0 :: dsc_ctrl0 :: rxSeqStart [15:15] */ -+#define DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK 0x8000 -+#define DSC_2_0_DSC_CTRL0_RXSEQSTART_ALIGN 0 -+#define DSC_2_0_DSC_CTRL0_RXSEQSTART_BITS 1 -+#define DSC_2_0_DSC_CTRL0_RXSEQSTART_SHIFT 15 -+ -+ -+/**************************************************************************** -+ * XGXS16G_USER_SerdesDigital -+ ***************************************************************************/ -+/**************************************************************************** -+ * SerdesDigital :: Control1000X1 -+ ***************************************************************************/ -+/* SerdesDigital :: Control1000X1 :: crc_checker_disable [07:07] */ -+#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK 0x0080 -+#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_ALIGN 0 -+#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_BITS 1 -+#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_SHIFT 7 -+ -+/* SerdesDigital :: Control1000X1 :: disable_pll_pwrdwn [06:06] */ -+#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK 0x0040 -+#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_ALIGN 0 -+#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_BITS 1 -+#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_SHIFT 6 -+ -+/* SerdesDigital :: Control1000X1 :: fiber_mode_1000X [00:00] */ -+#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK 0x0001 -+#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_ALIGN 0 -+#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_BITS 1 -+#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_SHIFT 0 -+ -+/**************************************************************************** -+ * SerdesDigital :: Control1000X3 -+ ***************************************************************************/ -+/* SerdesDigital :: Control1000X3 :: fifo_elasicity_tx_rx [02:01] */ -+#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK 0x0006 -+#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_ALIGN 0 -+#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_BITS 2 -+#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_SHIFT 1 -+ -+/* SerdesDigital :: Control1000X3 :: tx_fifo_rst [00:00] */ -+#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK 0x0001 -+#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_ALIGN 0 -+#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_BITS 1 -+#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_SHIFT 0 -+ -+/**************************************************************************** -+ * SerdesDigital :: Status1000X1 -+ ***************************************************************************/ -+/* SerdesDigital :: Status1000X1 :: speed_status [04:03] */ -+#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK 0x0018 -+#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_ALIGN 0 -+#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS 2 -+#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT 3 -+ -+/**************************************************************************** -+ * SerdesDigital :: Misc1 -+ ***************************************************************************/ -+/* SerdesDigital :: Misc1 :: refclk_sel [15:13] */ -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_MASK 0xe000 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_ALIGN 0 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_BITS 3 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_SHIFT 13 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_25MHz 0 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_100MHz 1 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_125MHz 2 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_156p25MHz 3 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_187p5MHz 4 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_161p25Mhz 5 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_50Mhz 6 -+#define SERDESDIGITAL_MISC1_REFCLK_SEL_clk_106p25Mhz 7 -+ -+/* SerdesDigital :: Misc1 :: force_speed_sel [04:04] */ -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK 0x0010 -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_ALIGN 0 -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_BITS 1 -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_SHIFT 4 -+ -+/* SerdesDigital :: Misc1 :: force_speed [03:00] */ -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_MASK 0x000f -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_ALIGN 0 -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_BITS 4 -+#define SERDESDIGITAL_MISC1_FORCE_SPEED_SHIFT 0 -+ -+ -+/**************************************************************************** -+ * CL73_UserB0 :: CL73_BAMCtrl1 -+ ***************************************************************************/ -+/* CL73_UserB0 :: CL73_BAMCtrl1 :: CL73_bamEn [15:15] */ -+#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK 0x8000 -+#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_ALIGN 0 -+#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_BITS 1 -+#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_SHIFT 15 -+ -+ -+/**************************************************************************** -+ * Datatype Definitions. -+ ***************************************************************************/ -+#endif /* _PHY_XGXS16G_H_ */ -+ -+/* End of File */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmnvram.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmnvram.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmnvram.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmnvram.h 2017-11-09 17:53:43.936309000 +0800 -@@ -0,0 +1,290 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * NVRAM variable manipulation -+ * -+ * $Id: bcmnvram.h 325984 2012-04-05 08:51:37Z $ -+ */ -+ -+#ifndef _bcmnvram_h_ -+#define _bcmnvram_h_ -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+#include -+#include -+#include -+ -+struct nvram_header { -+ uint32 magic; -+ uint32 len; -+ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ -+ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ -+ uint32 config_ncdl; /* ncdl values for memc */ -+}; -+ -+struct nvram_otphdr { -+ struct nvram_header nvh; -+ uint16 flags_swmacm_gpio_phya; /* otp flags, switch/gmac mode, gpio, phyaddr */ -+ struct ether_addr mac; -+ uint32 clkfreq; -+}; -+ -+struct nvram_tuple { -+ char *name; -+ char *value; -+ struct nvram_tuple *next; -+}; -+ -+/* -+ * Get default value for an NVRAM variable -+ */ -+extern char *nvram_default_get(const char *name); -+ -+/* -+ * Initialize NVRAM access. May be unnecessary or undefined on certain -+ * platforms. -+ */ -+extern int nvram_init(void *sih); -+ -+/* -+ * Append a chunk of nvram variables to the global list -+ */ -+extern int nvram_append(void *si, char *vars, uint varsz); -+ -+extern void nvram_get_global_vars(char **varlst, uint *varsz); -+ -+ -+/* -+ * Check for reset button press for restoring factory defaults. -+ */ -+extern int nvram_reset(void *sih); -+ -+/* -+ * Disable NVRAM access. May be unnecessary or undefined on certain -+ * platforms. -+ */ -+extern void nvram_exit(void *sih); -+ -+/* -+ * Get the value of an NVRAM variable. The pointer returned may be -+ * invalid after a set. -+ * @param name name of variable to get -+ * @return value of variable or NULL if undefined -+ */ -+extern char * nvram_get(const char *name); -+ -+/* -+ * Read the reset GPIO value from the nvram and set the GPIO -+ * as input -+ */ -+extern int BCMINITFN(nvram_resetgpio_init)(void *sih); -+ -+/* -+ * Get the value of an NVRAM variable. -+ * @param name name of variable to get -+ * @return value of variable or NUL if undefined -+ */ -+static INLINE char * -+nvram_safe_get(const char *name) -+{ -+ char *p = nvram_get(name); -+ return p ? p : ""; -+} -+ -+/* -+ * Match an NVRAM variable. -+ * @param name name of variable to match -+ * @param match value to compare against value of variable -+ * @return TRUE if variable is defined and its value is string equal -+ * to match or FALSE otherwise -+ */ -+static INLINE int -+nvram_match(char *name, char *match) -+{ -+ const char *value = nvram_get(name); -+ return (value && !strcmp(value, match)); -+} -+ -+/* -+ * Inversely match an NVRAM variable. -+ * @param name name of variable to match -+ * @param match value to compare against value of variable -+ * @return TRUE if variable is defined and its value is not string -+ * equal to invmatch or FALSE otherwise -+ */ -+static INLINE int -+nvram_invmatch(char *name, char *invmatch) -+{ -+ const char *value = nvram_get(name); -+ return (value && strcmp(value, invmatch)); -+} -+ -+/* -+ * Set the value of an NVRAM variable. The name and value strings are -+ * copied into private storage. Pointers to previously set values -+ * may become invalid. The new value may be immediately -+ * retrieved but will not be permanently stored until a commit. -+ * @param name name of variable to set -+ * @param value value of variable -+ * @return 0 on success and errno on failure -+ */ -+extern int nvram_set(const char *name, const char *value); -+ -+/* -+ * Unset an NVRAM variable. Pointers to previously set values -+ * remain valid until a set. -+ * @param name name of variable to unset -+ * @return 0 on success and errno on failure -+ * NOTE: use nvram_commit to commit this change to flash. -+ */ -+extern int nvram_unset(const char *name); -+ -+/* -+ * NVRAM is based of FLASH or OTP. -+ * @return From FLASH: TRUE -+ * From OTP: FALSE -+ */ -+extern bool nvram_inotp(void); -+ -+/* -+ * Commit NVRAM header to OTP. All pointers to values -+ * may be invalid after a commit. -+ * NVRAM values are undefined after a commit. -+ * @return 0 on success and errno on failure -+ */ -+extern int nvram_otpcommit(void *sih); -+ -+/* -+ * Commit NVRAM variables to permanent storage. All pointers to values -+ * may be invalid after a commit. -+ * NVRAM values are undefined after a commit. -+ * @return 0 on success and errno on failure -+ */ -+extern int nvram_commit(void); -+ -+/* -+ * Get all NVRAM variables (format name=value\0 ... \0\0). -+ * @param buf buffer to store variables -+ * @param count size of buffer in bytes -+ * @return 0 on success and errno on failure -+ */ -+extern int nvram_getall(char *nvram_buf, int count); -+ -+/* -+ * returns the crc value of the nvram -+ * @param nvh nvram header pointer -+ */ -+uint8 nvram_calc_crc(struct nvram_header * nvh); -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+/* The NVRAM version number stored as an NVRAM variable */ -+#define NVRAM_SOFTWARE_VERSION "1" -+ -+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ -+#define NVRAM_CLEAR_MAGIC 0x0 -+#define NVRAM_INVALID_MAGIC 0xFFFFFFFF -+#define NVRAM_VERSION 1 -+#define NVRAM_HEADER_SIZE 20 -+#define NVRAM_SPACE 0x8000 -+#define ENVRAM_SPACE 0x1000 -+ -+#define NVRAM_MAX_VALUE_LEN 255 -+#define NVRAM_MAX_PARAM_LEN 64 -+ -+#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ -+#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */ -+ -+/* Incase of nvram header(in OTP), we save 16bit after nvram header -+ * o 0:0 Switch Present -+ * o 1:4 Switch and gmac mode -+ * o 5:10 robo reset GPIO pin number -+ * o 11:15 phyaddr -+ */ -+#define OTPNVRAM_SWITCH_PRESENT 0x1 -+ -+#define OTPNVRAM_FLAGS_MASK 0x1 -+#define OTPNVRAM_SMACMODE_MASK 0x1e -+#define OTPNVRAM_GPIO_MASK 0x7e0 -+#define OTPNVRAM_PHYADDR_MASK 0xf800 -+ -+#define OTPNVRAM_SMACMODE_SHIFT 1 -+#define OTPNVRAM_GPIO_SHIFT 5 -+#define OTPNVRAM_PHYADDR_SHIFT 11 -+ -+/* clkfreq is saved in following format in OTP nvram data -+ * 9:0 pci clock -+ * 20:10 si clock -+ * 31:21 mips clock -+ */ -+ -+#define NVRAM_PCI_CLKMASK 0x3ff -+#define NVRAM_SI_CLKMASK 0x1ffc00 -+#define NVRAM_SI_CLKSHIFT 10 -+#define NVRAM_CPUCLK_SHIFT 21 -+ -+/* Offsets to embedded nvram area */ -+#define NVRAM_START_COMPRESSED 0x400 -+#define NVRAM_START 0x1000 -+ -+#define BCM_JUMBO_NVRAM_DELIMIT '\n' -+#define BCM_JUMBO_START "Broadcom Jumbo Nvram file" -+ -+#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \ -+ defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__)) -+#define IMAGE_SIZE "image_size" -+#define BOOTPARTITION "bootpartition" -+#define IMAGE_BOOT BOOTPARTITION -+#define PARTIALBOOTS "partialboots" -+#define MAXPARTIALBOOTS "maxpartialboots" -+#define IMAGE_1ST_FLASH_TRX "flash0.trx" -+#define IMAGE_1ST_FLASH_OS "flash0.os" -+#define IMAGE_2ND_FLASH_TRX "flash0.trx2" -+#define IMAGE_2ND_FLASH_OS "flash0.os2" -+#define IMAGE_FIRST_OFFSET "image_first_offset" -+#define IMAGE_SECOND_OFFSET "image_second_offset" -+#define LINUX_FIRST "linux" -+#define LINUX_SECOND "linux2" -+#endif -+ -+#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \ -+ defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__)) -+/* Shared by all: CFE, Linux Kernel, and Ap */ -+#define IMAGE_BOOT "image_boot" -+#define BOOTPARTITION IMAGE_BOOT -+/* CFE variables */ -+#define IMAGE_1ST_FLASH_TRX "flash0.trx" -+#define IMAGE_1ST_FLASH_OS "flash0.os" -+#define IMAGE_2ND_FLASH_TRX "flash0.trx2" -+#define IMAGE_2ND_FLASH_OS "flash0.os2" -+#define IMAGE_SIZE "image_size" -+ -+/* CFE and Linux Kernel shared variables */ -+#define IMAGE_FIRST_OFFSET "image_first_offset" -+#define IMAGE_SECOND_OFFSET "image_second_offset" -+ -+/* Linux application variables */ -+#define LINUX_FIRST "linux" -+#define LINUX_SECOND "linux2" -+#define POLICY_TOGGLE "toggle" -+#define LINUX_PART_TO_FLASH "linux_to_flash" -+#define LINUX_FLASH_POLICY "linux_flash_policy" -+ -+#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */ -+ -+int nvram_env_gmac_name(int gmac, char *name); -+ -+#endif /* _bcmnvram_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmparams.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmparams.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmparams.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmparams.h 2017-11-09 17:53:43.937301000 +0800 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc system wide parameters. -+ * -+ * $Id: bcmparams.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _bcmparams_h_ -+#define _bcmparams_h_ -+ -+#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */ -+ -+#define VLAN_NUMPRIS 8 /* # of prio, start from 0 */ -+ -+#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */ -+ -+#define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */ -+ -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmperf.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmperf.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmperf.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmperf.h 2017-11-09 17:53:43.938295000 +0800 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Performance counters software interface. -+ * -+ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $ -+ */ -+/* essai */ -+#ifndef _BCMPERF_H_ -+#define _BCMPERF_H_ -+/* get cache hits and misses */ -+#if defined(BCMMIPS) && defined(BCMPERFSTATS) -+#include -+#define BCMPERF_ENABLE_INSTRCOUNT() hndmips_perf_instrcount_enable() -+#define BCMPERF_ENABLE_ICACHE_MISS() hndmips_perf_icache_miss_enable() -+#define BCMPERF_ENABLE_ICACHE_HIT() hndmips_perf_icache_hit_enable() -+#define BCMPERF_GETICACHE_MISS(x) ((x) = hndmips_perf_read_cache_miss()) -+#define BCMPERF_GETICACHE_HIT(x) ((x) = hndmips_perf_read_cache_hit()) -+#define BCMPERF_GETINSTRCOUNT(x) ((x) = hndmips_perf_read_instrcount()) -+#else -+#define BCMPERF_ENABLE_INSTRCOUNT() -+#define BCMPERF_ENABLE_ICACHE_MISS() -+#define BCMPERF_ENABLE_ICACHE_HIT() -+#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) -+#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) -+#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) -+#endif /* defined(mips) */ -+#endif /* _BCMPERF_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmsdpcm.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmsdpcm.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmsdpcm.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmsdpcm.h 2017-11-09 17:53:43.939297000 +0800 -@@ -0,0 +1,268 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom SDIO/PCMCIA -+ * Software-specific definitions shared between device and host side -+ * -+ * $Id: bcmsdpcm.h 314495 2012-02-12 07:56:39Z $ -+ */ -+ -+#ifndef _bcmsdpcm_h_ -+#define _bcmsdpcm_h_ -+ -+/* -+ * Software allocation of To SB Mailbox resources -+ */ -+ -+/* intstatus bits */ -+#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ -+#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ -+#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ -+#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ -+ -+#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT) -+ -+/* tosbmailbox bits corresponding to intstatus bits */ -+#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ -+#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ -+#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ -+#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ -+#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ -+ -+/* tosbmailboxdata */ -+#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ -+#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ -+ -+/* -+ * Software allocation of To Host Mailbox resources -+ */ -+ -+/* intstatus bits */ -+#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ -+#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ -+#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ -+#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ -+ -+#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT) -+ -+/* tohostmailbox bits corresponding to intstatus bits */ -+#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ -+#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ -+#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ -+#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ -+#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ -+ -+/* tohostmailboxdata */ -+#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */ -+#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */ -+#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */ -+#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */ -+#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */ -+ -+#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ -+#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ -+ -+#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ -+#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ -+ -+/* -+ * Software-defined protocol header -+ */ -+ -+/* Current protocol version */ -+#define SDPCM_PROT_VERSION 4 -+ -+/* SW frame header */ -+#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ -+#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ -+ -+#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ -+#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ -+#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ -+ -+#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ -+#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ -+#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ -+ -+/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ -+#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ -+#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ -+#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ -+#define SDPCM_NEXTLEN_OFFSET 2 -+ -+/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ -+#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ -+#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) -+#define SDPCM_DOFFSET_MASK 0xff000000 -+#define SDPCM_DOFFSET_SHIFT 24 -+ -+#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ -+#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) -+#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ -+#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) -+#define SDPCM_VERSION_OFFSET 6 /* Version # */ -+#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) -+#define SDPCM_UNUSED_OFFSET 7 /* Spare */ -+#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) -+ -+#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ -+ -+/* logical channel numbers */ -+#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ -+#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ -+#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ -+#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ -+#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ -+#define SDPCM_MAX_CHANNEL 15 -+ -+#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ -+ -+#define SDPCM_FLAG_RESVD0 0x01 -+#define SDPCM_FLAG_RESVD1 0x02 -+#define SDPCM_FLAG_GSPI_TXENAB 0x04 -+#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ -+ -+/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ -+#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) -+ -+#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) -+ -+/* For TEST_CHANNEL packets, define another 4-byte header */ -+#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); -+ * Semantics of Ext byte depend on command. -+ * Len is current or requested frame length, not -+ * including test header; sent little-endian. -+ */ -+#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ -+#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ -+#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ -+#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ -+#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ -+ -+/* Handy macro for filling in datagen packets with a pattern */ -+#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) -+ -+/* -+ * Software counters (first part matches hardware counters) -+ */ -+ -+typedef volatile struct { -+ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ -+ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ -+ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ -+ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ -+ uint32 abort; /* AbortCount, SDIO: aborts */ -+ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ -+ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ -+ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ -+ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ -+ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ -+ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ -+ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ -+ uint32 rxdescuflo; /* receive descriptor underflows */ -+ uint32 rxfifooflo; /* receive fifo overflows */ -+ uint32 txfifouflo; /* transmit fifo underflows */ -+ uint32 runt; /* runt (too short) frames recv'd from bus */ -+ uint32 badlen; /* frame's rxh len does not match its hw tag len */ -+ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ -+ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ -+ uint32 rxfcrc; /* frame rx header indicates crc error */ -+ uint32 rxfwoos; /* frame rx header indicates write out of sync */ -+ uint32 rxfwft; /* frame rx header indicates write frame termination */ -+ uint32 rxfabort; /* frame rx header indicates frame aborted */ -+ uint32 woosint; /* write out of sync interrupt */ -+ uint32 roosint; /* read out of sync interrupt */ -+ uint32 rftermint; /* read frame terminate interrupt */ -+ uint32 wftermint; /* write frame terminate interrupt */ -+} sdpcmd_cnt_t; -+ -+/* -+ * Register Access Macros -+ */ -+ -+#define SDIODREV_IS(var, val) ((var) == (val)) -+#define SDIODREV_GE(var, val) ((var) >= (val)) -+#define SDIODREV_GT(var, val) ((var) > (val)) -+#define SDIODREV_LT(var, val) ((var) < (val)) -+#define SDIODREV_LE(var, val) ((var) <= (val)) -+ -+#define SDIODDMAREG32(h, dir, chnl) \ -+ ((dir) == DMA_TX ? \ -+ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ -+ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) -+ -+#define SDIODDMAREG64(h, dir, chnl) \ -+ ((dir) == DMA_TX ? \ -+ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ -+ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) -+ -+#define SDIODDMAREG(h, dir, chnl) \ -+ (SDIODREV_LT((h)->corerev, 1) ? \ -+ SDIODDMAREG32((h), (dir), (chnl)) : \ -+ SDIODDMAREG64((h), (dir), (chnl))) -+ -+#define PCMDDMAREG(h, dir, chnl) \ -+ ((dir) == DMA_TX ? \ -+ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ -+ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) -+ -+#define SDPCMDMAREG(h, dir, chnl, coreid) \ -+ ((coreid) == SDIOD_CORE_ID ? \ -+ SDIODDMAREG(h, dir, chnl) : \ -+ PCMDDMAREG(h, dir, chnl)) -+ -+#define SDIODFIFOREG(h, corerev) \ -+ (SDIODREV_LT((corerev), 1) ? \ -+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ -+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) -+ -+#define PCMDFIFOREG(h) \ -+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) -+ -+#define SDPCMFIFOREG(h, coreid, corerev) \ -+ ((coreid) == SDIOD_CORE_ID ? \ -+ SDIODFIFOREG(h, corerev) : \ -+ PCMDFIFOREG(h)) -+ -+/* -+ * Shared structure between dongle and the host. -+ * The structure contains pointers to trap or assert information. -+ */ -+#define SDPCM_SHARED_VERSION 0x0001 -+#define SDPCM_SHARED_VERSION_MASK 0x00FF -+#define SDPCM_SHARED_ASSERT_BUILT 0x0100 -+#define SDPCM_SHARED_ASSERT 0x0200 -+#define SDPCM_SHARED_TRAP 0x0400 -+#define SDPCM_SHARED_IN_BRPT 0x0800 -+#define SDPCM_SHARED_SET_BRPT 0x1000 -+#define SDPCM_SHARED_PENDING_BRPT 0x2000 -+ -+typedef struct { -+ uint32 flags; -+ uint32 trap_addr; -+ uint32 assert_exp_addr; -+ uint32 assert_file_addr; -+ uint32 assert_line; -+ uint32 console_addr; /* Address of hndrte_cons_t */ -+ uint32 msgtrace_addr; -+ uint32 fwid; -+} sdpcm_shared_t; -+ -+extern sdpcm_shared_t sdpcm_shared; -+ -+/* Function can be used to notify host of FW halt */ -+extern void sdpcmd_fwhalt(void); -+ -+#endif /* _bcmsdpcm_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmstdlib.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmstdlib.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmstdlib.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmstdlib.h 2017-11-09 17:53:43.940291000 +0800 -@@ -0,0 +1,128 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * prototypes for functions defined in bcmstdlib.c -+ * -+ * $Id: bcmstdlib.h 289936 2011-10-14 21:06:33Z $: -+ */ -+ -+/* -+ * bcmstdlib.h file should be used only to construct an OSL or alone without any OSL -+ * It should not be used with any orbitarary OSL's as there could be a conflict -+ * with some of the routines defined here. -+*/ -+ -+#ifndef _BCMSTDLIB_H -+#define _BCMSTDLIB_H -+ -+#include -+#include -+#include -+ -+#ifndef INT_MAX -+#define INT_MAX 2147483647 /* from limits.h */ -+#endif -+ -+ -+/* For backwards compatibility, define "BWL_NO_INTERNAL_STDLIB_SUPPORT" to -+ * exclude support for the BRCM stdlib APIs. This should be cleaned-up such -+ * that platforms that require the BRCM stdlib API should simply define -+ * "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate the need for the -+ * following #ifndef check. -+ */ -+#ifndef BWL_NO_INTERNAL_STDLIB_SUPPORT -+#define BWL_INTERNAL_STDLIB_SUPPORT -+#endif -+ -+#ifdef BWL_INTERNAL_STDLIB_SUPPORT -+/* This should be cleaned-up such that platforms that require the BRCM stdlib -+ * API should simply define "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate -+ * the need for the following #ifdef check. -+ */ -+#if !defined(_WIN32) && !defined(_CFE_) && !defined(EFI) -+ -+typedef int FILE; -+#define stdout ((FILE *)1) -+#define stderr ((FILE *)2) -+ -+/* i/o functions */ -+extern int fputc(int c, FILE *stream); -+extern void putc(int c); -+/* extern int putc(int c, FILE *stream); */ -+#define putchar(c) putc(c) -+extern int fputs(const char *s, FILE *stream); -+extern int puts(const char *s); -+extern int getc(void); -+extern bool keypressed(void); -+ -+/* bcopy, bcmp, and bzero */ -+#define bcopy(src, dst, len) memcpy((dst), (src), (len)) -+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -+#define bzero(b, len) memset((b), '\0', (len)) -+ -+extern unsigned long rand(void); -+ -+#define atoi(s) ((int)(strtoul((s), NULL, 10))) -+ -+#endif -+ -+#if !defined(_WIN32) || defined(EFI) -+/* string functions */ -+#define PRINTF_BUFLEN 512 -+extern int printf(const char *fmt, ...) -+ __attribute__ ((format (__printf__, 1, 2))); -+extern int BCMROMFN(sprintf)(char *buf, const char *fmt, ...) -+ __attribute__ ((format (__printf__, 2, 3))); -+ -+extern int BCMROMFN(strcmp)(const char *s1, const char *s2); -+extern size_t BCMROMFN(strlen)(const char *s); -+extern char *BCMROMFN(strcpy)(char *dest, const char *src); -+extern char *BCMROMFN(strstr)(const char *s, const char *find); -+extern char *BCMROMFN(strncpy)(char *dest, const char *src, size_t n); -+extern char *BCMROMFN(strcat)(char *d, const char *s); -+ -+extern int BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n); -+extern char *BCMROMFN(strchr)(const char *str, int c); -+extern char *BCMROMFN(strrchr)(const char *str, int c); -+extern size_t BCMROMFN(strspn)(const char *s1, const char *s2); -+extern size_t BCMROMFN(strcspn)(const char *s1, const char *s2); -+extern unsigned long BCMROMFN(strtoul)(const char *cp, char **endp, int base); -+#define strtol(nptr, endptr, base) ((long)strtoul((nptr), (endptr), (base))) -+ -+extern void *BCMROMFN(memmove)(void *dest, const void *src, size_t n); -+extern void *BCMROMFN(memchr)(const void *s, int c, size_t n); -+ -+extern int BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap); -+/* mem functions */ -+/* For EFI, using EFIDriverLib versions */ -+/* Cannot use memmem in ROM because of character array initialization wiht "" in gcc */ -+extern void *memset(void *dest, int c, size_t n); -+/* Cannot use memcpy in ROM because of structure assignmnets in gcc */ -+extern void *memcpy(void *dest, const void *src, size_t n); -+extern int BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n); -+ -+#endif /* !_WIN32 || EFI */ -+#endif /* BWL_INTERNAL_STDLIB_SUPPORT */ -+ -+#if !defined(_WIN32) || defined(EFI) -+extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...) -+ __attribute__ ((format (__printf__, 3, 4))); -+#else -+extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...); -+#endif -+ -+extern int BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap); -+ -+#endif /* _BCMSTDLIB_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmutils.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmutils.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmutils.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmutils.h 2017-11-09 17:53:43.941299000 +0800 -@@ -0,0 +1,864 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc useful os-independent macros and functions. -+ * -+ * $Id: bcmutils.h 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#ifndef _bcmutils_h_ -+#define _bcmutils_h_ -+ -+#if defined(UNDER_CE) -+#include -+#else -+#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) -+#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) -+#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) -+#endif -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#ifdef PKTQ_LOG -+#include -+#endif -+ -+/* ctype replacement */ -+#define _BCM_U 0x01 /* upper */ -+#define _BCM_L 0x02 /* lower */ -+#define _BCM_D 0x04 /* digit */ -+#define _BCM_C 0x08 /* cntrl */ -+#define _BCM_P 0x10 /* punct */ -+#define _BCM_S 0x20 /* white space (space/lf/tab) */ -+#define _BCM_X 0x40 /* hex digit */ -+#define _BCM_SP 0x80 /* hard space (0x20) */ -+ -+#if defined(BCMROMBUILD) -+extern const unsigned char BCMROMDATA(bcm_ctype)[]; -+#else -+extern const unsigned char bcm_ctype[]; -+#endif -+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) -+ -+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) -+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) -+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) -+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) -+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) -+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) -+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) -+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) -+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) -+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) -+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) -+#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) -+#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) -+ -+/* Buffer structure for collecting string-formatted data -+* using bcm_bprintf() API. -+* Use bcm_binit() to initialize before use -+*/ -+ -+struct bcmstrbuf { -+ char *buf; /* pointer to current position in origbuf */ -+ unsigned int size; /* current (residual) size in bytes */ -+ char *origbuf; /* unmodified pointer to orignal buffer */ -+ unsigned int origsize; /* unmodified orignal buffer size in bytes */ -+}; -+ -+/* ** driver-only section ** */ -+#ifdef BCMDRIVER -+#ifdef EFI -+/* forward declare structyre type */ -+struct spktq; -+#endif -+#include -+ -+#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ -+ -+/* -+ * Spin at most 'us' microseconds while 'exp' is true. -+ * Caller should explicitly test 'exp' when this completes -+ * and take appropriate error action if 'exp' is still true. -+ */ -+#define SPINWAIT(exp, us) { \ -+ uint countdown = (us) + 9; \ -+ while ((exp) && (countdown >= 10)) {\ -+ OSL_DELAY(10); \ -+ countdown -= 10; \ -+ } \ -+} -+ -+/* osl multi-precedence packet queue */ -+#ifndef PKTQ_LEN_DEFAULT -+#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ -+#endif -+#ifndef PKTQ_MAX_PREC -+#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ -+#endif -+ -+typedef struct pktq_prec { -+ void *head; /* first packet to dequeue */ -+ void *tail; /* last packet to dequeue */ -+ uint16 len; /* number of queued packets */ -+ uint16 max; /* maximum number of queued packets */ -+} pktq_prec_t; -+ -+#ifdef PKTQ_LOG -+typedef struct { -+ uint32 requested; /* packets requested to be stored */ -+ uint32 stored; /* packets stored */ -+ uint32 saved; /* packets saved, -+ because a lowest priority queue has given away one packet -+ */ -+ uint32 selfsaved; /* packets saved, -+ because an older packet from the same queue has been dropped -+ */ -+ uint32 full_dropped; /* packets dropped, -+ because pktq is full with higher precedence packets -+ */ -+ uint32 dropped; /* packets dropped because pktq per that precedence is full */ -+ uint32 sacrificed; /* packets dropped, -+ in order to save one from a queue of a highest priority -+ */ -+ uint32 busy; /* packets droped because of hardware/transmission error */ -+ uint32 retry; /* packets re-sent because they were not received */ -+ uint32 ps_retry; /* packets retried again prior to moving power save mode */ -+ uint32 retry_drop; /* packets finally dropped after retry limit */ -+ uint32 max_avail; /* the high-water mark of the queue capacity for packets - -+ goes to zero as queue fills -+ */ -+ uint32 max_used; /* the high-water mark of the queue utilisation for packets - -+ increases with use ('inverse' of max_avail) -+ */ -+ uint32 queue_capacity; /* the maximum capacity of the queue */ -+} pktq_counters_t; -+#endif /* PKTQ_LOG */ -+ -+ -+#define PKTQ_COMMON \ -+ uint16 num_prec; /* number of precedences in use */ \ -+ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ -+ uint16 max; /* total max packets */ \ -+ uint16 len; /* total number of packets */ -+ -+/* multi-priority pkt queue */ -+struct pktq { -+ PKTQ_COMMON -+ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ -+ struct pktq_prec q[PKTQ_MAX_PREC]; -+#ifdef PKTQ_LOG -+ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ -+#endif -+}; -+ -+/* simple, non-priority pkt queue */ -+struct spktq { -+ PKTQ_COMMON -+ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ -+ struct pktq_prec q[1]; -+}; -+ -+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) -+ -+/* fn(pkt, arg). return true if pkt belongs to if */ -+typedef bool (*ifpkt_cb_t)(void*, int); -+ -+#ifdef BCMPKTPOOL -+#define POOL_ENAB(pool) ((pool) && (pool)->inited) -+#if defined(BCM4329C0) -+#define SHARED_POOL (pktpool_shared_ptr) -+#else -+#define SHARED_POOL (pktpool_shared) -+#endif /* BCM4329C0 */ -+#else /* BCMPKTPOOL */ -+#define POOL_ENAB(bus) 0 -+#define SHARED_POOL ((struct pktpool *)NULL) -+#endif /* BCMPKTPOOL */ -+ -+#ifndef PKTPOOL_LEN_MAX -+#define PKTPOOL_LEN_MAX 40 -+#endif /* PKTPOOL_LEN_MAX */ -+#define PKTPOOL_CB_MAX 3 -+ -+struct pktpool; -+typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); -+typedef struct { -+ pktpool_cb_t cb; -+ void *arg; -+} pktpool_cbinfo_t; -+ -+#ifdef BCMDBG_POOL -+/* pkt pool debug states */ -+#define POOL_IDLE 0 -+#define POOL_RXFILL 1 -+#define POOL_RXDH 2 -+#define POOL_RXD11 3 -+#define POOL_TXDH 4 -+#define POOL_TXD11 5 -+#define POOL_AMPDU 6 -+#define POOL_TXENQ 7 -+ -+typedef struct { -+ void *p; -+ uint32 cycles; -+ uint32 dur; -+} pktpool_dbg_t; -+ -+typedef struct { -+ uint8 txdh; /* tx to host */ -+ uint8 txd11; /* tx to d11 */ -+ uint8 enq; /* waiting in q */ -+ uint8 rxdh; /* rx from host */ -+ uint8 rxd11; /* rx from d11 */ -+ uint8 rxfill; /* dma_rxfill */ -+ uint8 idle; /* avail in pool */ -+} pktpool_stats_t; -+#endif /* BCMDBG_POOL */ -+ -+typedef struct pktpool { -+ bool inited; -+ uint16 r; -+ uint16 w; -+ uint16 len; -+ uint16 maxlen; -+ uint16 plen; -+ bool istx; -+ bool empty; -+ uint8 cbtoggle; -+ uint8 cbcnt; -+ uint8 ecbcnt; -+ bool emptycb_disable; -+ pktpool_cbinfo_t *availcb_excl; -+ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; -+ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; -+ void *q[PKTPOOL_LEN_MAX + 1]; -+ -+#ifdef BCMDBG_POOL -+ uint8 dbg_cbcnt; -+ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; -+ uint16 dbg_qlen; -+ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; -+#endif -+} pktpool_t; -+ -+#if defined(BCM4329C0) -+extern pktpool_t *pktpool_shared_ptr; -+#else -+extern pktpool_t *pktpool_shared; -+#endif /* BCM4329C0 */ -+ -+extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); -+extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); -+extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); -+extern void* pktpool_get(pktpool_t *pktp); -+extern void pktpool_free(pktpool_t *pktp, void *p); -+extern int pktpool_add(pktpool_t *pktp, void *p); -+extern uint16 pktpool_avail(pktpool_t *pktp); -+extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); -+extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); -+extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); -+extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); -+extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); -+extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); -+extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); -+extern bool pktpool_emptycb_disabled(pktpool_t *pktp); -+ -+#define POOLPTR(pp) ((pktpool_t *)(pp)) -+#define pktpool_len(pp) (POOLPTR(pp)->len - 1) -+#define pktpool_plen(pp) (POOLPTR(pp)->plen) -+#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) -+ -+#ifdef BCMDBG_POOL -+extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); -+extern int pktpool_start_trigger(pktpool_t *pktp, void *p); -+extern int pktpool_dbg_dump(pktpool_t *pktp); -+extern int pktpool_dbg_notify(pktpool_t *pktp); -+extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); -+#endif /* BCMDBG_POOL */ -+ -+/* forward definition of ether_addr structure used by some function prototypes */ -+ -+struct ether_addr; -+ -+extern int ether_isbcast(const void *ea); -+extern int ether_isnulladdr(const void *ea); -+ -+/* operations on a specific precedence in packet queue */ -+ -+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) -+#define pktq_pmax(pq, prec) ((pq)->q[prec].max) -+#define pktq_plen(pq, prec) ((pq)->q[prec].len) -+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) -+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) -+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) -+ -+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) -+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) -+ -+extern void *pktq_penq(struct pktq *pq, int prec, void *p); -+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); -+extern void *pktq_pdeq(struct pktq *pq, int prec); -+extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); -+extern void *pktq_pdeq_tail(struct pktq *pq, int prec); -+/* Empty the queue at particular precedence level */ -+extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, -+ ifpkt_cb_t fn, int arg); -+/* Remove a specified packet from its queue */ -+extern bool pktq_pdel(struct pktq *pq, void *p, int prec); -+ -+/* operations on a set of precedences in packet queue */ -+ -+extern int pktq_mlen(struct pktq *pq, uint prec_bmp); -+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); -+extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); -+ -+/* operations on packet queue as a whole */ -+ -+#define pktq_len(pq) ((int)(pq)->len) -+#define pktq_max(pq) ((int)(pq)->max) -+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) -+#define pktq_full(pq) ((pq)->len >= (pq)->max) -+#define pktq_empty(pq) ((pq)->len == 0) -+ -+/* operations for single precedence queues */ -+#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) -+#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) -+#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) -+#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) -+#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) -+ -+extern void pktq_init(struct pktq *pq, int num_prec, int max_len); -+extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); -+ -+/* prec_out may be NULL if caller is not interested in return value */ -+extern void *pktq_deq(struct pktq *pq, int *prec_out); -+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); -+extern void *pktq_peek(struct pktq *pq, int *prec_out); -+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); -+extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); -+ -+/* externs */ -+/* packet */ -+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); -+extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); -+extern uint pkttotlen(osl_t *osh, void *p); -+extern void *pktlast(osl_t *osh, void *p); -+extern uint pktsegcnt(osl_t *osh, void *p); -+extern uint pktsegcnt_war(osl_t *osh, void *p); -+extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); -+extern void *pktoffset(osl_t *osh, void *p, uint offset); -+ -+/* Get priority from a packet and pass it back in scb (or equiv) */ -+#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ -+#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ -+#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ -+#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ -+ -+extern uint pktsetprio(void *pkt, bool update_vtag); -+ -+/* string */ -+extern int BCMROMFN(bcm_atoi)(const char *s); -+extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base); -+extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle); -+extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src); -+extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size); -+extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); -+char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); -+int bcmstricmp(const char *s1, const char *s2); -+int bcmstrnicmp(const char* s1, const char* s2, int cnt); -+ -+ -+/* ethernet address */ -+extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); -+extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea); -+ -+/* ip address */ -+struct ipv4_addr; -+extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); -+ -+/* delay */ -+extern void bcm_mdelay(uint ms); -+/* variable access */ -+#if defined(DONGLEBUILD) && !defined(WLTEST) -+#ifdef BCMDBG -+#define NVRAM_RECLAIM_CHECK(name) \ -+ if (attach_part_reclaimed == TRUE) { \ -+ printf("%s: NVRAM already reclaimed, %s\n", __FUNCTION__, (name)); \ -+ *(char*) 0 = 0; /* TRAP */ \ -+ return NULL; \ -+ } -+#else /* BCMDBG */ -+#define NVRAM_RECLAIM_CHECK(name) \ -+ if (attach_part_reclaimed == TRUE) { \ -+ *(char*) 0 = 0; /* TRAP */ \ -+ return NULL; \ -+ } -+#endif /* BCMDBG */ -+#else /* DONGLEBUILD && !WLTEST && !BCMINTERNAL && !BCMDBG_DUMP */ -+#define NVRAM_RECLAIM_CHECK(name) -+#endif -+ -+extern char *getvar(char *vars, const char *name); -+extern int getintvar(char *vars, const char *name); -+extern int getintvararray(char *vars, const char *name, int index); -+extern int getintvararraysize(char *vars, const char *name); -+extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); -+extern int getwanport(void); -+extern int getbrcmtag(void); -+#ifdef BCMDBG -+extern void prpkt(const char *msg, osl_t *osh, void *p0); -+#endif /* BCMDBG */ -+#ifdef BCMPERFSTATS -+extern void bcm_perf_enable(void); -+extern void bcmstats(char *fmt); -+extern void bcmlog(char *fmt, uint a1, uint a2); -+extern void bcmdumplog(char *buf, int size); -+extern int bcmdumplogent(char *buf, uint idx); -+#else -+#define bcm_perf_enable() -+#define bcmstats(fmt) -+#define bcmlog(fmt, a1, a2) -+#define bcmdumplog(buf, size) *buf = '\0' -+#define bcmdumplogent(buf, idx) -1 -+#endif /* BCMPERFSTATS */ -+ -+#if defined(BCMTSTAMPEDLOGS) -+#define TSF_TICKS_PER_MS 1024 -+/* Store a TSF timestamp and a log line in the log buffer */ -+extern void bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2); -+/* Print out the log buffer with timestamps */ -+extern void bcmprinttslogs(void); -+/* Print out a microsecond timestamp as "sec.ms.us " */ -+extern void bcmprinttstamp(uint32 us); -+/* Dump to buffer a microsecond timestamp as "sec.ms.us " */ -+extern void bcmdumptslog(char *buf, int size); -+#else -+#define bcmtslog(tstamp, fmt, a1, a2) -+#define bcmprinttslogs() -+#define bcmprinttstamp(us) -+#define bcmdumptslog(buf, size) -+#endif /* BCMTSTAMPEDLOGS */ -+ -+extern char *bcm_nvram_vars(uint *length); -+extern int bcm_nvram_cache(void *sih); -+ -+/* Support for sharing code across in-driver iovar implementations. -+ * The intent is that a driver use this structure to map iovar names -+ * to its (private) iovar identifiers, and the lookup function to -+ * find the entry. Macros are provided to map ids and get/set actions -+ * into a single number space for a switch statement. -+ */ -+ -+/* iovar structure */ -+typedef struct bcm_iovar { -+ const char *name; /* name for lookup and display */ -+ uint16 varid; /* id for switch */ -+ uint16 flags; /* driver-specific flag bits */ -+ uint16 type; /* base type of argument */ -+ uint16 minlen; /* min length for buffer vars */ -+} bcm_iovar_t; -+ -+/* varid definitions are per-driver, may use these get/set bits */ -+ -+/* IOVar action bits for id mapping */ -+#define IOV_GET 0 /* Get an iovar */ -+#define IOV_SET 1 /* Set an iovar */ -+ -+/* Varid to actionid mapping */ -+#define IOV_GVAL(id) ((id) * 2) -+#define IOV_SVAL(id) ((id) * 2 + IOV_SET) -+#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) -+#define IOV_ID(actionid) (actionid >> 1) -+ -+/* flags are per-driver based on driver attributes */ -+ -+extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); -+extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); -+#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ -+ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) -+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); -+#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ -+#endif /* BCMDRIVER */ -+ -+/* Base type definitions */ -+#define IOVT_VOID 0 /* no value (implictly set only) */ -+#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ -+#define IOVT_INT8 2 /* integer values are range-checked */ -+#define IOVT_UINT8 3 /* unsigned int 8 bits */ -+#define IOVT_INT16 4 /* int 16 bits */ -+#define IOVT_UINT16 5 /* unsigned int 16 bits */ -+#define IOVT_INT32 6 /* int 32 bits */ -+#define IOVT_UINT32 7 /* unsigned int 32 bits */ -+#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ -+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) -+ -+/* Initializer for IOV type strings */ -+#define BCM_IOV_TYPE_INIT { \ -+ "void", \ -+ "bool", \ -+ "int8", \ -+ "uint8", \ -+ "int16", \ -+ "uint16", \ -+ "int32", \ -+ "uint32", \ -+ "buffer", \ -+ "" } -+ -+#define BCM_IOVT_IS_INT(type) (\ -+ (type == IOVT_BOOL) || \ -+ (type == IOVT_INT8) || \ -+ (type == IOVT_UINT8) || \ -+ (type == IOVT_INT16) || \ -+ (type == IOVT_UINT16) || \ -+ (type == IOVT_INT32) || \ -+ (type == IOVT_UINT32)) -+ -+/* ** driver/apps-shared section ** */ -+ -+#define BCME_STRLEN 64 /* Max string length for BCM errors */ -+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) -+ -+ -+/* -+ * error codes could be added but the defined ones shouldn't be changed/deleted -+ * these error codes are exposed to the user code -+ * when ever a new error code is added to this list -+ * please update errorstring table with the related error string and -+ * update osl files with os specific errorcode map -+*/ -+ -+#define BCME_OK 0 /* Success */ -+#define BCME_ERROR -1 /* Error generic */ -+#define BCME_BADARG -2 /* Bad Argument */ -+#define BCME_BADOPTION -3 /* Bad option */ -+#define BCME_NOTUP -4 /* Not up */ -+#define BCME_NOTDOWN -5 /* Not down */ -+#define BCME_NOTAP -6 /* Not AP */ -+#define BCME_NOTSTA -7 /* Not STA */ -+#define BCME_BADKEYIDX -8 /* BAD Key Index */ -+#define BCME_RADIOOFF -9 /* Radio Off */ -+#define BCME_NOTBANDLOCKED -10 /* Not band locked */ -+#define BCME_NOCLK -11 /* No Clock */ -+#define BCME_BADRATESET -12 /* BAD Rate valueset */ -+#define BCME_BADBAND -13 /* BAD Band */ -+#define BCME_BUFTOOSHORT -14 /* Buffer too short */ -+#define BCME_BUFTOOLONG -15 /* Buffer too long */ -+#define BCME_BUSY -16 /* Busy */ -+#define BCME_NOTASSOCIATED -17 /* Not Associated */ -+#define BCME_BADSSIDLEN -18 /* Bad SSID len */ -+#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ -+#define BCME_BADCHAN -20 /* Bad Channel */ -+#define BCME_BADADDR -21 /* Bad Address */ -+#define BCME_NORESOURCE -22 /* Not Enough Resources */ -+#define BCME_UNSUPPORTED -23 /* Unsupported */ -+#define BCME_BADLEN -24 /* Bad length */ -+#define BCME_NOTREADY -25 /* Not Ready */ -+#define BCME_EPERM -26 /* Not Permitted */ -+#define BCME_NOMEM -27 /* No Memory */ -+#define BCME_ASSOCIATED -28 /* Associated */ -+#define BCME_RANGE -29 /* Not In Range */ -+#define BCME_NOTFOUND -30 /* Not Found */ -+#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ -+#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ -+#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ -+#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ -+#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ -+#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ -+#define BCME_VERSION -37 /* Incorrect version */ -+#define BCME_TXFAIL -38 /* TX failure */ -+#define BCME_RXFAIL -39 /* RX failure */ -+#define BCME_NODEVICE -40 /* Device not present */ -+#define BCME_NMODE_DISABLED -41 /* NMODE disabled */ -+#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ -+#define BCME_LAST BCME_NONRESIDENT -+ -+/* These are collection of BCME Error strings */ -+#define BCMERRSTRINGTABLE { \ -+ "OK", \ -+ "Undefined error", \ -+ "Bad Argument", \ -+ "Bad Option", \ -+ "Not up", \ -+ "Not down", \ -+ "Not AP", \ -+ "Not STA", \ -+ "Bad Key Index", \ -+ "Radio Off", \ -+ "Not band locked", \ -+ "No clock", \ -+ "Bad Rate valueset", \ -+ "Bad Band", \ -+ "Buffer too short", \ -+ "Buffer too long", \ -+ "Busy", \ -+ "Not Associated", \ -+ "Bad SSID len", \ -+ "Out of Range Channel", \ -+ "Bad Channel", \ -+ "Bad Address", \ -+ "Not Enough Resources", \ -+ "Unsupported", \ -+ "Bad length", \ -+ "Not Ready", \ -+ "Not Permitted", \ -+ "No Memory", \ -+ "Associated", \ -+ "Not In Range", \ -+ "Not Found", \ -+ "WME Not Enabled", \ -+ "TSPEC Not Found", \ -+ "ACM Not Supported", \ -+ "Not WME Association", \ -+ "SDIO Bus Error", \ -+ "Dongle Not Accessible", \ -+ "Incorrect version", \ -+ "TX Failure", \ -+ "RX Failure", \ -+ "Device Not Present", \ -+ "NMODE Disabled", \ -+ "Nonresident overlay access", \ -+} -+ -+#ifndef ABS -+#define ABS(a) (((a) < 0) ? -(a) : (a)) -+#endif /* ABS */ -+ -+#ifndef MIN -+#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -+#endif /* MIN */ -+ -+#ifndef MAX -+#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -+#endif /* MAX */ -+ -+#define CEIL(x, y) (((x) + ((y) - 1)) / (y)) -+#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) -+#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) -+#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ -+ & ~((boundary) - 1)) -+#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ -+ & ~((boundary) - 1)) -+#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) -+#define VALID_MASK(mask) !((mask) & ((mask) + 1)) -+ -+#ifndef OFFSETOF -+#ifdef __ARMCC_VERSION -+/* -+ * The ARM RVCT compiler complains when using OFFSETOF where a constant -+ * expression is expected, such as an initializer for a static object. -+ * offsetof from the runtime library doesn't have that problem. -+ */ -+#include -+#define OFFSETOF(type, member) offsetof(type, member) -+#else -+#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) -+#endif /* __ARMCC_VERSION */ -+#endif /* OFFSETOF */ -+ -+#ifndef ARRAYSIZE -+#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) -+#endif -+ -+/* Reference a function; used to prevent a static function from being optimized out */ -+extern void *_bcmutils_dummy_fn; -+#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) -+ -+/* bit map related macros */ -+#ifndef setbit -+#ifndef NBBY /* the BSD family defines NBBY */ -+#define NBBY 8 /* 8 bits per byte */ -+#endif /* #ifndef NBBY */ -+#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) -+#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) -+#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) -+#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) -+#endif /* setbit */ -+ -+#define NBITS(type) (sizeof(type) * 8) -+#define NBITVAL(nbits) (1 << (nbits)) -+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) -+#define NBITMASK(nbits) MAXBITVAL(nbits) -+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) -+ -+/* basic mux operation - can be optimized on several architectures */ -+#define MUX(pred, true, false) ((pred) ? (true) : (false)) -+ -+/* modulo inc/dec - assumes x E [0, bound - 1] */ -+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) -+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) -+ -+/* modulo inc/dec, bound = 2^k */ -+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) -+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) -+ -+/* modulo add/sub - assumes x, y E [0, bound - 1] */ -+#define MODADD(x, y, bound) \ -+ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) -+#define MODSUB(x, y, bound) \ -+ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) -+ -+/* module add/sub, bound = 2^k */ -+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) -+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) -+ -+/* crc defines */ -+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ -+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ -+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ -+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ -+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ -+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ -+ -+/* use for direct output of MAC address in printf etc */ -+#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" -+#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ -+ ((struct ether_addr *) (ea))->octet[1], \ -+ ((struct ether_addr *) (ea))->octet[2], \ -+ ((struct ether_addr *) (ea))->octet[3], \ -+ ((struct ether_addr *) (ea))->octet[4], \ -+ ((struct ether_addr *) (ea))->octet[5] -+ -+#define ETHER_TO_MACF(ea) (ea).octet[0], \ -+ (ea).octet[1], \ -+ (ea).octet[2], \ -+ (ea).octet[3], \ -+ (ea).octet[4], \ -+ (ea).octet[5] -+ -+/* bcm_format_flags() bit description structure */ -+typedef struct bcm_bit_desc { -+ uint32 bit; -+ const char* name; -+} bcm_bit_desc_t; -+ -+/* tag_ID/length/value_buffer tuple */ -+typedef struct bcm_tlv { -+ uint8 id; -+ uint8 len; -+ uint8 data[1]; -+} bcm_tlv_t; -+ -+/* Check that bcm_tlv_t fits into the given buflen */ -+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) -+ -+/* buffer length for ethernet address from bcm_ether_ntoa() */ -+#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ -+ -+/* crypto utility function */ -+/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ -+static INLINE void -+xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) -+{ -+ if ( -+#ifdef __i386__ -+ 1 || -+#endif -+ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { -+ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ -+ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ -+ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; -+ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; -+ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; -+ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; -+ } else { -+ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ -+ int k; -+ for (k = 0; k < 16; k++) -+ dst[k] = src1[k] ^ src2[k]; -+ } -+} -+ -+/* externs */ -+/* crc */ -+extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc); -+extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc); -+extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc); -+ -+/* format/print */ -+#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ -+ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) -+extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); -+#endif -+ -+#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ -+ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ -+ defined(WLMEDIA_PEAKRATE) -+extern int bcm_format_hex(char *str, const void *bytes, int len); -+#endif -+ -+#ifdef BCMDBG -+extern void deadbeef(void *p, size_t len); -+#endif -+extern const char *bcm_crypto_algo_name(uint algo); -+extern char *bcm_chipname(uint chipid, char *buf, uint len); -+extern char *bcm_brev_str(uint32 brev, char *buf); -+extern void printbig(char *buf); -+extern void prhex(const char *msg, uchar *buf, uint len); -+ -+/* IE parsing */ -+extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); -+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); -+extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); -+ -+/* bcmerror */ -+extern const char *bcmerrorstr(int bcmerror); -+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); -+ -+/* multi-bool data type: set of bools, mbool is true if any is set */ -+typedef uint32 mbool; -+#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ -+#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ -+#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ -+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) -+ -+/* generic datastruct to help dump routines */ -+struct fielddesc { -+ const char *nameandfmt; -+ uint32 offset; -+ uint32 len; -+}; -+ -+extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); -+extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); -+ -+extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); -+extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); -+extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); -+ -+typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); -+extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, -+ char *buf, uint32 bufsize); -+extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength); -+ -+extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); -+ -+/* power conversion */ -+extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm); -+extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw); -+ -+extern int32 exthdr_validate(char *ptr, uint size); -+extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); -+ -+unsigned int process_nvram_vars(char *varbuf, unsigned int len); -+ -+#ifdef __cplusplus -+ } -+#endif -+ -+#endif /* _bcmutils_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/bcmwifi.h b/drivers/net/ethernet/broadcom/gmac/src/include/bcmwifi.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/bcmwifi.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/bcmwifi.h 2017-11-09 17:53:43.942304000 +0800 -@@ -0,0 +1,456 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc utility routines for WL and Apps -+ * This header file housing the define and function prototype use by -+ * both the wl driver, tools & Apps. -+ * -+ * $Id: bcmwifi.h 293848 2011-11-03 12:31:04Z $ -+ */ -+ -+#ifndef _bcmwifi_h_ -+#define _bcmwifi_h_ -+ -+ -+/* A chanspec holds the channel number, band, bandwidth and control sideband */ -+typedef uint16 chanspec_t; -+ -+/* channel defines */ -+#define CH_UPPER_SB 0x01 -+#define CH_LOWER_SB 0x02 -+#define CH_EWA_VALID 0x04 -+#define CH_80MHZ_APART 16 -+#define CH_40MHZ_APART 8 -+#define CH_20MHZ_APART 4 -+#define CH_10MHZ_APART 2 -+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ -+#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ -+#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, -+ * this is that + 1 rounded up to a multiple of NBBY (8). -+ * DO NOT MAKE it > 255: channels are uint8's all over -+ */ -+#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) -+ -+#ifndef D11AC_IOTYPES -+ -+#define WL_CHANSPEC_CHAN_MASK 0x00ff -+#define WL_CHANSPEC_CHAN_SHIFT 0 -+ -+#define WL_CHANSPEC_CTL_SB_MASK 0x0300 -+#define WL_CHANSPEC_CTL_SB_SHIFT 8 -+#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 -+#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 -+#define WL_CHANSPEC_CTL_SB_NONE 0x0300 -+ -+#define WL_CHANSPEC_BW_MASK 0x0C00 -+#define WL_CHANSPEC_BW_SHIFT 10 -+#define WL_CHANSPEC_BW_10 0x0400 -+#define WL_CHANSPEC_BW_20 0x0800 -+#define WL_CHANSPEC_BW_40 0x0C00 -+ -+#define WL_CHANSPEC_BAND_MASK 0xf000 -+#define WL_CHANSPEC_BAND_SHIFT 12 -+#define WL_CHANSPEC_BAND_5G 0x1000 -+#define WL_CHANSPEC_BAND_2G 0x2000 -+#define INVCHANSPEC 255 -+ -+/* channel defines */ -+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) -+#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ -+ ((channel) + CH_10MHZ_APART) : 0) -+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) -+#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ -+ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ -+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -+#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ -+ ((channel) + CH_20MHZ_APART) : 0) -+#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ -+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ -+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ -+ WL_CHANSPEC_BAND_5G)) -+#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) -+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) -+ -+/* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ -+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) -+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) -+ -+#ifdef WL11N_20MHZONLY -+ -+#define CHSPEC_IS10(chspec) 0 -+#define CHSPEC_IS20(chspec) 1 -+#ifndef CHSPEC_IS40 -+#define CHSPEC_IS40(chspec) 0 -+#endif -+ -+#else /* !WL11N_20MHZONLY */ -+ -+#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) -+#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) -+#ifndef CHSPEC_IS40 -+#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) -+#endif -+ -+#endif /* !WL11N_20MHZONLY */ -+ -+#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) -+#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) -+#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) -+#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) -+#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) -+#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ -+ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ -+ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) -+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) -+ -+#define CHANSPEC_STR_LEN 8 -+ -+#else /* D11AC_IOTYPES */ -+ -+#define WL_CHANSPEC_CHAN_MASK 0x00ff -+#define WL_CHANSPEC_CHAN_SHIFT 0 -+#define WL_CHANSPEC_CHAN1_MASK 0x000f -+#define WL_CHANSPEC_CHAN1_SHIFT 0 -+#define WL_CHANSPEC_CHAN2_MASK 0x00f0 -+#define WL_CHANSPEC_CHAN2_SHIFT 4 -+ -+#define WL_CHANSPEC_CTL_SB_MASK 0x0700 -+#define WL_CHANSPEC_CTL_SB_SHIFT 8 -+#define WL_CHANSPEC_CTL_SB_LLL 0x0000 -+#define WL_CHANSPEC_CTL_SB_LLU 0x0100 -+#define WL_CHANSPEC_CTL_SB_LUL 0x0200 -+#define WL_CHANSPEC_CTL_SB_LUU 0x0300 -+#define WL_CHANSPEC_CTL_SB_ULL 0x0400 -+#define WL_CHANSPEC_CTL_SB_ULU 0x0500 -+#define WL_CHANSPEC_CTL_SB_UUL 0x0600 -+#define WL_CHANSPEC_CTL_SB_UUU 0x0700 -+#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL -+#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU -+#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL -+#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU -+#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL -+#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU -+#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL -+#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU -+ -+#define WL_CHANSPEC_BW_MASK 0x3800 -+#define WL_CHANSPEC_BW_SHIFT 11 -+#define WL_CHANSPEC_BW_5 0x0000 -+#define WL_CHANSPEC_BW_10 0x0800 -+#define WL_CHANSPEC_BW_20 0x1000 -+#define WL_CHANSPEC_BW_40 0x1800 -+#define WL_CHANSPEC_BW_80 0x2000 -+#define WL_CHANSPEC_BW_160 0x2800 -+#define WL_CHANSPEC_BW_8080 0x3000 -+ -+#define WL_CHANSPEC_BAND_MASK 0xc000 -+#define WL_CHANSPEC_BAND_SHIFT 14 -+#define WL_CHANSPEC_BAND_2G 0x0000 -+#define WL_CHANSPEC_BAND_3G 0x4000 -+#define WL_CHANSPEC_BAND_4G 0x8000 -+#define WL_CHANSPEC_BAND_5G 0xc000 -+#define INVCHANSPEC 255 -+ -+/* channel defines */ -+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ -+ ((channel) - CH_10MHZ_APART) : 0) -+#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ -+ ((channel) + CH_10MHZ_APART) : 0) -+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) -+#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ -+ (((channel) <= CH_MAX_2G_CHANNEL) ? \ -+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -+#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ -+ ((channel) + CH_20MHZ_APART) : 0) -+#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ -+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ -+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ -+ WL_CHANSPEC_BAND_5G)) -+#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ -+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_80 | \ -+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ -+ WL_CHANSPEC_BAND_5G)) -+#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ -+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_160 | \ -+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ -+ WL_CHANSPEC_BAND_5G)) -+ -+/* simple MACROs to get different fields of chanspec */ -+#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) -+#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) -+#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) -+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) -+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) -+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) -+ -+#ifdef WL11N_20MHZONLY -+ -+#define CHSPEC_IS10(chspec) 0 -+#define CHSPEC_IS20(chspec) 1 -+#ifndef CHSPEC_IS40 -+#define CHSPEC_IS40(chspec) 0 -+#endif -+#ifndef CHSPEC_IS80 -+#define CHSPEC_IS160(chspec) 0 -+#endif -+#ifndef CHSPEC_IS160 -+#define CHSPEC_IS160(chspec) 0 -+#endif -+#ifndef CHSPEC_IS8080 -+#define CHSPEC_IS8080(chspec) 0 -+#endif -+ -+#else /* !WL11N_20MHZONLY */ -+ -+#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) -+#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) -+#ifndef CHSPEC_IS40 -+#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) -+#endif -+#ifndef CHSPEC_IS80 -+#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) -+#endif -+#ifndef CHSPEC_IS160 -+#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) -+#endif -+#ifndef CHSPEC_IS8080 -+#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) -+#endif -+ -+#endif /* !WL11N_20MHZONLY */ -+ -+#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) -+#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) -+#define CHSPEC_SB_UPPER(chspec) \ -+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ -+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) -+#define CHSPEC_SB_LOWER(chspec) \ -+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ -+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) -+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) -+ -+/** -+ * Number of chars needed for wf_chspec_ntoa() destination character buffer. -+ */ -+#define CHANSPEC_STR_LEN 20 -+ -+ -+/* Legacy Chanspec defines -+ * These are the defines for the previous format of the chanspec_t -+ */ -+#define WL_LCHANSPEC_CHAN_MASK 0x00ff -+#define WL_LCHANSPEC_CHAN_SHIFT 0 -+ -+#define WL_LCHANSPEC_CTL_SB_MASK 0x0300 -+#define WL_LCHANSPEC_CTL_SB_SHIFT 8 -+#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 -+#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 -+#define WL_LCHANSPEC_CTL_SB_NONE 0x0300 -+ -+#define WL_LCHANSPEC_BW_MASK 0x0C00 -+#define WL_LCHANSPEC_BW_SHIFT 10 -+#define WL_LCHANSPEC_BW_10 0x0400 -+#define WL_LCHANSPEC_BW_20 0x0800 -+#define WL_LCHANSPEC_BW_40 0x0C00 -+ -+#define WL_LCHANSPEC_BAND_MASK 0xf000 -+#define WL_LCHANSPEC_BAND_SHIFT 12 -+#define WL_LCHANSPEC_BAND_5G 0x1000 -+#define WL_LCHANSPEC_BAND_2G 0x2000 -+ -+#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) -+#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) -+#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) -+#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) -+#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) -+#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) -+#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) -+#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) -+#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) -+ -+#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) -+ -+#endif /* D11AC_IOTYPES */ -+ -+/* -+ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency -+ * given a channel number. -+ * chan_freq = chan_factor * 500Mhz + chan_number * 5 -+ */ -+ -+/** -+ * Channel Factor for the starting frequence of 2.4 GHz channels. -+ * The value corresponds to 2407 MHz. -+ */ -+#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ -+ -+/** -+ * Channel Factor for the starting frequence of 5 GHz channels. -+ * The value corresponds to 5000 MHz. -+ */ -+#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ -+ -+/** -+ * Channel Factor for the starting frequence of 4.9 GHz channels. -+ * The value corresponds to 4000 MHz. -+ */ -+#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ -+ -+/* defined rate in 500kbps */ -+#define WLC_MAXRATE 108 /* in 500kbps units */ -+#define WLC_RATE_1M 2 /* in 500kbps units */ -+#define WLC_RATE_2M 4 /* in 500kbps units */ -+#define WLC_RATE_5M5 11 /* in 500kbps units */ -+#define WLC_RATE_11M 22 /* in 500kbps units */ -+#define WLC_RATE_6M 12 /* in 500kbps units */ -+#define WLC_RATE_9M 18 /* in 500kbps units */ -+#define WLC_RATE_12M 24 /* in 500kbps units */ -+#define WLC_RATE_18M 36 /* in 500kbps units */ -+#define WLC_RATE_24M 48 /* in 500kbps units */ -+#define WLC_RATE_36M 72 /* in 500kbps units */ -+#define WLC_RATE_48M 96 /* in 500kbps units */ -+#define WLC_RATE_54M 108 /* in 500kbps units */ -+ -+#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ -+ -+/** -+ * Convert chanspec to ascii string -+ * -+ * @param chspec chanspec format -+ * @param buf ascii string of chanspec -+ * -+ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes -+ * -+ * @see CHANSPEC_STR_LEN -+ */ -+extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); -+ -+/** -+ * Convert ascii string to chanspec -+ * -+ * @param a pointer to input string -+ * -+ * @return >= 0 if successful or 0 otherwise -+ */ -+extern chanspec_t wf_chspec_aton(const char *a); -+ -+/** -+ * Verify the chanspec fields are valid. -+ * -+ * Verify the chanspec is using a legal set field values, i.e. that the chanspec -+ * specified a band, bw, ctl_sb and channel and that the combination could be -+ * legal given some set of circumstances. -+ * -+ * @param chanspec input chanspec to verify -+ * -+ * @return TRUE if the chanspec is malformed, FALSE if it looks good. -+ */ -+extern bool wf_chspec_malformed(chanspec_t chanspec); -+ -+/** -+ * Verify the chanspec specifies a valid channel according to 802.11. -+ * -+ * @param chanspec input chanspec to verify -+ * -+ * @return TRUE if the chanspec is a valid 802.11 channel -+ */ -+extern bool wf_chspec_valid(chanspec_t chanspec); -+ -+/** -+ * Return the primary (control) channel. -+ * -+ * This function returns the channel number of the primary 20MHz channel. For -+ * 20MHz channels this is just the channel number. For 40MHz or wider channels -+ * it is the primary 20MHz channel specified by the chanspec. -+ * -+ * @param chspec input chanspec -+ * -+ * @return Returns the channel number of the primary 20MHz channel -+ */ -+extern uint8 wf_chspec_ctlchan(chanspec_t chspec); -+ -+/** -+ * Return the primary (control) chanspec. -+ * -+ * This function returns the chanspec of the primary 20MHz channel. For 20MHz -+ * channels this is just the chanspec. For 40MHz or wider channels it is the -+ * chanspec of the primary 20MHZ channel specified by the chanspec. -+ * -+ * @param chspec input chanspec -+ * -+ * @return Returns the chanspec of the primary 20MHz channel -+ */ -+extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); -+ -+/** -+ * Return a channel number corresponding to a frequency. -+ * -+ * Return the channel number for a given frequency and base frequency. -+ * The returned channel number is relative to the given base frequency. -+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for -+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. -+ * -+ * Frequency is specified in MHz. -+ * The base frequency is specified as (start_factor * 500 kHz). -+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for -+ * 2.4 GHz and 5 GHz bands. -+ * -+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band -+ * and [0, 200] otherwise. -+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the -+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even -+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. -+ * -+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 -+ * -+ * @param freq frequency in MHz -+ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz -+ * -+ * @return Returns a channel number -+ * -+ * @see WF_CHAN_FACTOR_2_4_G -+ * @see WF_CHAN_FACTOR_5_G -+ */ -+extern int wf_mhz2channel(uint freq, uint start_factor); -+ -+/** -+ * Return the center frequency in MHz of the given channel and base frequency. -+ * -+ * Return the center frequency in MHz of the given channel and base frequency. -+ * The channel number is interpreted relative to the given base frequency. -+ * -+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. -+ * The base frequency is specified as (start_factor * 500 kHz). -+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for -+ * 2.4 GHz and 5 GHz bands. -+ * The channel range of [1, 14] is only checked for a start_factor of -+ * WF_CHAN_FACTOR_2_4_G (4814). -+ * Odd start_factors produce channels on .5 MHz boundaries, in which case -+ * the answer is rounded down to an integral MHz. -+ * -1 is returned for an out of range channel. -+ * -+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 -+ * -+ * @param channel input channel number -+ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz -+ * -+ * @return Returns a frequency in MHz -+ * -+ * @see WF_CHAN_FACTOR_2_4_G -+ * @see WF_CHAN_FACTOR_5_G -+ */ -+extern int wf_channel2mhz(uint channel, uint start_factor); -+ -+#endif /* _bcmwifi_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/compvers.sh b/drivers/net/ethernet/broadcom/gmac/src/include/compvers.sh ---- a/drivers/net/ethernet/broadcom/gmac/src/include/compvers.sh 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/compvers.sh 2017-11-09 17:53:43.943304000 +0800 -@@ -0,0 +1,133 @@ -+#!/bin/bash -+# -+# Given a list of components, generate _version.h -+# from version.h.in in 's directory -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+# -+ -+# Optional argument -+ACTION=$1 -+[ -n "$VERBOSE" ] && export VERBOSE -+ -+SRCBASE=.. -+ -+# List of components -+# TODO: In the long term component versioning model, following list -+# TODO: or table of components will come from a central file -+COMPONENTS=( \ -+ upnp \ -+ phy \ -+ router \ -+ wps \ -+) -+ -+# Component dirs. Need one entry for each of above COMPONENTS -+COMPONENT_DIR_upnp=${SRCBASE}/router/libupnp/include -+COMPONENT_DIR_phy=${SRCBASE}/wl/phy -+COMPONENT_DIR_router=${SRCBASE}/router/shared -+COMPONENT_DIR_wps=${SRCBASE}/wps/common/include -+ -+# For a given component, query automerger for a different -+# path than COMPONENT_DIR_. -+# Force router component to be pointing to local branch or tag. -+COMPONENT_QUERY_router=src_force_local_component -+ -+ -+ -+# ===== DO NOT CHANGE ANYTHING BELOW THIS LINE ===== -+ -+NULL=/dev/null -+MKCOMPVER=${SRCBASE}/tools/release/mkversion.sh -+MERGERLOG=${SRCBASE}/../merger_sources.log -+ -+# TODO: Post svn transition, network paths will be taken away -+GETCOMPVER=getcompver.py -+GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER -+GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} -+ -+# -+# If there is a local copy GETCOMPVER use it ahead of network copy -+# -+if [ -s "$GETCOMPVER" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER" -+elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then -+ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" -+elif [ -s "$GETCOMPVER_NET" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER_NET" -+elif [ -s "$GETCOMPVER_NET_WIN" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" -+fi -+ -+# -+# If $GETCOMPVER isn't found, fetch it from SVN -+# (this is very rare) -+# -+if [ ! -s "$GETCOMPVER_PATH" ]; then -+ svn export -q \ -+ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ -+ ${GETCOMPVER} 2> $NULL -+ GETCOMPVER_PATH=$GETCOMPVER -+fi -+ -+# -+# Now walk through each specified component to generate its -+# component_version.h file from version.h.in template -+# -+for component in ${COMPONENTS[*]} -+do -+ # Get relative path of component from current dir -+ tmp="COMPONENT_DIR_$component" -+ eval rel_path=\$$tmp -+ -+ # Get query path for component -+ tmp="COMPONENT_QUERY_$component" -+ eval query_path=\$$tmp -+ -+ if [ ! -d "$rel_path" ]; then -+ continue -+ fi -+ -+ if [ "$query_path" != "" ]; then -+ abs_path=$(echo $query_path | sed -e "s%\.\.%src%g") -+ else -+ abs_path=$(echo $rel_path | sed -e "s%\.\.%src%g") -+ fi -+ -+ [ -n "$VERBOSE" ] && \ -+ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG $abs_path" -+ -+ tag=$(python $GETCOMPVER_PATH $MERGERLOG $abs_path 2> $NULL | sed -e 's/[[:space:]]*//g') -+ -+ template=$rel_path/version.h.in -+ verfile=$rel_path/${component}_version.h -+ -+ if [ "$ACTION" == "clean" ]; then -+ rm -fv $verfile -+ continue -+ fi -+ -+ # MKCOMPVER always has defaults if tag isn't set correctly -+ if [ ! -f "$verfile" -o "$FORCE" != "" ]; then -+ echo "" -+ echo ">>> Generate $abs_path/${component}_version.h from $tag" -+ -+ [ -n "$VERBOSE" ] && \ -+ echo "DBG: bash $MKCOMPVER $template $verfile $tag" -+ -+ bash $MKCOMPVER $template $verfile $tag -+ fi -+done -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h 2017-11-09 17:53:43.944299000 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ -+*/ -+ -+#ifndef _epivers_h_ -+#define _epivers_h_ -+ -+#define EPI_MAJOR_VERSION 6 -+ -+#define EPI_MINOR_VERSION 30 -+ -+#define EPI_RC_NUMBER 40 -+ -+#define EPI_INCREMENTAL_NUMBER 0 -+ -+#define EPI_BUILD_NUMBER 2 -+ -+#define EPI_VERSION 6, 30, 40, 0 -+ -+#define EPI_VERSION_NUM 0x061e2800 -+ -+#define EPI_VERSION_DEV 6.30.40 -+ -+/* Driver Version String, ASCII, 32 chars max */ -+#ifdef WLTEST -+#define EPI_VERSION_STR "6.30.40 (TOB) (r WLTEST)" -+#else -+#define EPI_VERSION_STR "6.30.40 (TOB) (r)" -+#endif -+ -+#endif /* _epivers_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h.in b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h.in ---- a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h.in 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.h.in 2017-11-09 17:53:43.945295000 +0800 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ -+ * -+*/ -+ -+#ifndef _epivers_h_ -+#define _epivers_h_ -+ -+#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@ -+ -+#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@ -+ -+#define EPI_RC_NUMBER @EPI_RC_NUMBER@ -+ -+#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@ -+ -+#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@ -+ -+#define EPI_VERSION @EPI_VERSION@ -+ -+#define EPI_VERSION_NUM @EPI_VERSION_NUM@ -+ -+#define EPI_VERSION_DEV @EPI_VERSION_DEV@ -+ -+/* Driver Version String, ASCII, 32 chars max */ -+#ifdef WLTEST -+#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@ WLTEST)" -+#else -+#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)" -+#endif -+ -+#endif /* _epivers_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.sh b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.sh ---- a/drivers/net/ethernet/broadcom/gmac/src/include/epivers.sh 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/epivers.sh 2017-11-09 17:53:43.946291000 +0800 -@@ -0,0 +1,309 @@ -+#! /bin/bash -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+# Create the epivers.h file from epivers.h.in -+# -+# Epivers.h generation mechanism supports svn based checkouts -+# -+# $Id: epivers.sh 299409 2011-11-30 00:52:43Z $ -+# -+# GetCompVer.py return value and action needed -+# i. trunk => use current date as version string -+# ii. local => use SVNURL expanded by HeadURL keyword -+# iii. => use it as as is -+# (some components can override and say give me native ver) -+# iv. empty => -+# a) If TAG is specified use it -+# a) If no TAG is specified use date -+# -+ -+# If the version header file already exists, increment its build number. -+# Otherwise, create a new file. -+if [ -f epivers.h ]; then -+ -+ # If REUSE_VERSION is set, epivers iteration is not incremented -+ # This can be used precommit and continuous integration projects -+ if [ -n "$REUSE_VERSION" ]; then -+ echo "Previous epivers.h exists. Skipping version increment" -+ exit 0 -+ fi -+ -+ build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"` -+ build=`expr ${build} + 1` -+ echo build=${build} -+ sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \ -+ < epivers.h > epivers.h.new -+ mv epivers.h epivers.h.prev -+ mv epivers.h.new epivers.h -+ exit 0 -+ -+else # epivers.h doesn't exist -+ -+ NULL="/dev/null" -+ svncmd="svn --non-interactive" -+ -+ # Check for the in file, if not there we're in the wrong directory -+ if [ ! -f epivers.h.in ]; then -+ echo "ERROR: No epivers.h.in found" -+ exit 1 -+ fi -+ -+ # Following SVNURL should be expanded on checkout -+ SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/users/kenlo/northstar/AARDVARK_TWIG_6_30_40/src/include/epivers.sh $' -+ -+ # If SVNURL isn't expanded, extract it from svn info -+ if echo "$SVNURL" | grep -vq '$.*HeadURL.*epivers.sh.*$'; then -+ [ -n "$VERBOSE" ] && \ -+ echo "DBG: SVN URL wasn't expanded. Getting it from svn info" -+ SVNURL=$($svncmd info epivers.sh 2> $NULL | egrep "^URL:") -+ fi -+ -+ if echo "${TAG}" | grep -q "_BRANCH_\|_TWIG_"; then -+ branchtag=$TAG -+ else -+ branchtag="" -+ fi -+ -+ # If this is a tagged build, use the tag to supply the numbers -+ # Tag should be in the form -+ # _REL__ -+ # or -+ # _REL___RC -+ # or -+ # _REL___RC_ -+ -+ SRCBASE=.. -+ MERGERLOG=${SRCBASE}/../merger_sources.log -+ GETCOMPVER=getcompver.py -+ GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER -+ GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} -+ -+ # -+ # If there is a local copy GETCOMPVER use it ahead of network copy -+ # -+ if [ -s "$GETCOMPVER" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER" -+ elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then -+ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" -+ elif [ -s "$GETCOMPVER_NET" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER_NET" -+ elif [ -s "$GETCOMPVER_NET_WIN" ]; then -+ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" -+ fi -+ -+ # -+ # If $GETCOMPVER isn't found, fetch it from SVN -+ # (this should be very rare) -+ # -+ if [ ! -s "$GETCOMPVER_PATH" ]; then -+ [ -n "$VERBOSE" ] && \ -+ echo "DBG: Fetching $GETCOMPVER from trunk" -+ -+ $svncmd export -q \ -+ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ -+ ${GETCOMPVER} 2> $NULL -+ -+ GETCOMPVER_PATH=$GETCOMPVER -+ fi -+ -+ # Now get tag for src/include from automerger log -+ [ -n "$VERBOSE" ] && \ -+ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG src/include" -+ -+ COMPTAG=$(python $GETCOMPVER_PATH $MERGERLOG src/include 2> $NULL | sed -e 's/[[:space:]]*//g') -+ -+ echo "DBG: Component Tag String Derived = $COMPTAG" -+ -+ # Process COMPTAG values -+ # Rule: -+ # If trunk is returned, use date as component tag -+ # If LOCAL_COMPONENT is returned, use SVN URL to get native tag -+ # If component is returned or empty, assign it to SVNTAG -+ # GetCompVer.py return value and action needed -+ # i. trunk => use current date as version string -+ # ii. local => use SVNURL expanded by HeadURL keyword -+ # iii. => use it as as is -+ # iv. empty => -+ # a) If TAG is specified use it -+ # a) If no TAG is specified use SVNURL from HeadURL -+ -+ SVNURL_VER=false -+ -+ if [ "$COMPTAG" == "" ]; then -+ SVNURL_VER=true -+ elif [ "$COMPTAG" == "LOCAL_COMPONENT" ]; then -+ SVNURL_VER=true -+ elif [ "$COMPTAG" == "trunk" ]; then -+ SVNTAG=$(date '+TRUNKCOMP_REL_%Y_%m_%d') -+ else -+ SVNTAG=$COMPTAG -+ fi -+ -+ # Given SVNURL path conventions or naming conventions, derive SVNTAG -+ # TO-DO: SVNTAG derivation logic can move to a central common API -+ # TO-DO: ${SRCBASE}/tools/build/svnurl2tag.sh -+ if [ "$SVNURL_VER" == "true" ]; then -+ case "${SVNURL}" in -+ */branches/*) -+ SVNTAG=$(echo $SVNURL | sed -e 's%.*/branches/\(.*\)/src.*%\1%g' | xargs printf "%s") -+ ;; -+ *_BRANCH_*) -+ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _BRANCH_ | xargs printf "%s") -+ ;; -+ *_TWIG_*) -+ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _TWIG_ | xargs printf "%s") -+ ;; -+ */tags/*) -+ SVNTAG=$(echo $SVNURL | sed -e 's%.*/tags/.*/\(.*\)/src.*%\1%g' | xargs printf "%s") -+ ;; -+ *_REL_*) -+ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _REL_ | xargs printf "%s") -+ ;; -+ */trunk/*) -+ SVNTAG=$(date '+TRUNKURL_REL_%Y_%m_%d') -+ ;; -+ *) -+ SVNTAG=$(date '+OTHER_REL_%Y_%m_%d') -+ ;; -+ esac -+ echo "DBG: Native Tag String Derived from URL: $SVNTAG" -+ else -+ echo "DBG: Native Tag String Derived: $SVNTAG" -+ fi -+ -+ TAG=${SVNTAG} -+ -+ # Normalize the branch name portion to "D11" in case it has underscores in it -+ branch_name=`expr match "$TAG" '\(.*\)_\(BRANCH\|TWIG\|REL\)_.*'` -+ TAG=`echo $TAG | sed -e "s%^$branch_name%D11%"` -+ -+ # Split the tag into an array on underbar or whitespace boundaries. -+ IFS="_ " tag=(${TAG}) -+ unset IFS -+ -+ tagged=1 -+ if [ ${#tag[*]} -eq 0 ]; then -+ tag=(`date '+TOT REL %Y %m %d 0 %y'`); -+ # reconstruct a TAG from the date -+ TAG=${tag[0]}_${tag[1]}_${tag[2]}_${tag[3]}_${tag[4]}_${tag[5]} -+ tagged=0 -+ fi -+ -+ # Allow environment variable to override values. -+ # Missing values default to 0 -+ # -+ maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}} -+ min=${EPI_MINOR_VERSION:-${tag[3]:-0}} -+ rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}} -+ -+ # If increment field is 0, set it to date suffix if on TOB -+ if [ -n "$branchtag" ]; then -+ [ "${tag[5]:-0}" -eq 0 ] && echo "Using date suffix for incr" -+ today=`date '+%Y%m%d'` -+ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-${today:-0}}} -+ else -+ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} -+ fi -+ origincr=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} -+ build=${EPI_BUILD_NUMBER:-0} -+ -+ # Strip 'RC' from front of rcnum if present -+ rcnum=${rcnum/#RC/} -+ -+ # strip leading zero off the number (otherwise they look like octal) -+ maj=${maj/#0/} -+ min=${min/#0/} -+ rcnum=${rcnum/#0/} -+ incremental=${incremental/#0/} -+ origincr=${origincr/#0/} -+ build=${build/#0/} -+ -+ # some numbers may now be null. replace with with zero. -+ maj=${maj:-0} -+ min=${min:-0} -+ -+ rcnum=${rcnum:-0} -+ incremental=${incremental:-0} -+ origincr=${origincr:-0} -+ build=${build:-0} -+ -+ if [ ${tagged} -eq 1 ]; then -+ # vernum is 32chars max -+ vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${origincr}` -+ else -+ vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}` -+ fi -+ -+ # make sure the size of vernum is under 32 bits. -+ # Otherwise, truncate. The string will keep full information. -+ vernum=${vernum:0:10} -+ -+ # build the string directly from the tag, irrespective of its length -+ # remove the name , the tag type, then replace all _ by . -+ tag_ver_str=${TAG/${tag[0]}_} -+ tag_ver_str=${tag_ver_str/${tag[1]}_} -+ tag_ver_str=${tag_ver_str//_/.} -+ -+ # record tag type -+ tagtype= -+ -+ if [ "${tag[1]}" = "BRANCH" -o "${tag[1]}" = "TWIG" ]; then -+ tagtype=" (TOB)" -+ echo "tag type: $tagtype" -+ fi -+ -+ echo "Effective version string: $tag_ver_str" -+ -+ if [ "$(uname -s)" == "Darwin" ]; then -+ # Mac does not like 2-digit numbers so convert the number to single -+ # digit. 5.100 becomes 5.1 -+ if [ $min -gt 99 ]; then -+ minmac=`expr $min / 100` -+ else -+ minmac=$min -+ fi -+ epi_ver_dev="${maj}.${minmac}.0" -+ else -+ epi_ver_dev="${maj}.${min}.${rcnum}" -+ fi -+ -+ # Finally get version control revision number of (if any) -+ vc_version_num=$($svncmd info ${SRCBASE} 2> $NULL | awk -F': ' '/^Revision: /{printf "%s", $2}') -+ -+ # OK, go do it -+ echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}" -+ -+ sed \ -+ -e "s;@EPI_MAJOR_VERSION@;${maj};" \ -+ -e "s;@EPI_MINOR_VERSION@;${min};" \ -+ -e "s;@EPI_RC_NUMBER@;${rcnum};" \ -+ -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \ -+ -e "s;@EPI_BUILD_NUMBER@;${build};" \ -+ -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \ -+ -e "s;@EPI_VERSION_STR@;${tag_ver_str};" \ -+ -e "s;@EPI_VERSION_TYPE@;${tagtype};" \ -+ -e "s;@VERSION_TYPE@;${tagtype};" \ -+ -e "s;@EPI_VERSION_NUM@;${vernum};" \ -+ -e "s;@EPI_VERSION_DEV@;${epi_ver_dev};" \ -+ -e "s;@VC_VERSION_NUM@;r${vc_version_num};" \ -+ < epivers.h.in > epivers.h -+ -+ # In shared workspaces across different platforms, ensure that -+ # windows generated file is made platform neutral without CRLF -+ if uname -s | egrep -i -q "cygwin"; then -+ dos2unix epivers.h > $NULL 2>&1 -+ fi -+fi # epivers.h -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/etioctl.h b/drivers/net/ethernet/broadcom/gmac/src/include/etioctl.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/etioctl.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/etioctl.h 2017-11-09 17:53:43.951293000 +0800 -@@ -0,0 +1,158 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * BCM44XX Ethernet Windows device driver custom OID definitions. -+ * -+ * $Id: etioctl.h 322208 2012-03-20 01:53:23Z $ -+ */ -+ -+#ifndef _etioctl_h_ -+#define _etioctl_h_ -+ -+/* -+ * Minor kludge alert: -+ * Duplicate a few definitions that irelay requires from epiioctl.h here -+ * so caller doesn't have to include this file and epiioctl.h . -+ * If this grows any more, it would be time to move these irelay-specific -+ * definitions out of the epiioctl.h and into a separate driver common file. -+ */ -+#ifndef EPICTRL_COOKIE -+#define EPICTRL_COOKIE 0xABADCEDE -+#endif -+ -+/* common ioctl definitions */ -+#define ETCUP 0 -+#define ETCDOWN 1 -+#define ETCLOOP 2 -+#define ETCDUMP 3 -+#define ETCSETMSGLEVEL 4 -+#define ETCPROMISC 5 -+#define ETCVAR 6 -+#define ETCSPEED 7 -+#define ETCPHYRD 9 -+#define ETCPHYWR 10 -+#define ETCQOS 11 -+#define ETCPHYRD2 12 -+#define ETCPHYWR2 13 -+#define ETCROBORD 14 -+#define ETCROBOWR 15 -+ -+/* -+ * A set of iovars defined for ET set/get -+ */ -+#define IOV_ET_POWER_SAVE_MODE 1 -+#define IOV_ET_CLEAR_DUMP 2 -+#define IOV_ET_ROBO_DEVID 3 -+#define IOV_PKTC 4 -+#define IOV_PKTCBND 5 -+#define IOV_COUNTERS 6 -+#define IOV_DUMP_CTF 7 -+ -+#if defined(linux) || defined(__ECOS) -+#define SIOCSETCUP (SIOCDEVPRIVATE + ETCUP) -+#define SIOCSETCDOWN (SIOCDEVPRIVATE + ETCDOWN) -+#define SIOCSETCLOOP (SIOCDEVPRIVATE + ETCLOOP) -+#define SIOCGETCDUMP (SIOCDEVPRIVATE + ETCDUMP) -+#define SIOCSETCSETMSGLEVEL (SIOCDEVPRIVATE + ETCSETMSGLEVEL) -+#define SIOCSETCPROMISC (SIOCDEVPRIVATE + ETCPROMISC) -+#define SIOCSETGETVAR (SIOCDEVPRIVATE + ETCVAR) -+#define SIOCSETCSPEED (SIOCDEVPRIVATE + ETCSPEED) -+#define SIOCTXGEN (SIOCDEVPRIVATE + 8) -+#define SIOCGETCPHYRD (SIOCDEVPRIVATE + ETCPHYRD) -+#define SIOCSETCPHYWR (SIOCDEVPRIVATE + ETCPHYWR) -+#define SIOCSETCQOS (SIOCDEVPRIVATE + ETCQOS) -+#define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + ETCPHYRD2) -+#define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + ETCPHYWR2) -+#define SIOCGETCROBORD (SIOCDEVPRIVATE + ETCROBORD) -+#define SIOCSETCROBOWR (SIOCDEVPRIVATE + ETCROBOWR) -+ -+/* structure to send a generic var set/get */ -+typedef struct et_var_s { -+ uint cmd; -+ uint set; -+ void *buf; -+ uint len; -+} et_var_t; -+ -+/* arg to SIOCTXGEN */ -+struct txg { -+ uint32 num; /* number of frames to send */ -+ uint32 delay; /* delay in microseconds between sending each */ -+ uint32 size; /* size of ether frame to send */ -+ uchar buf[1514]; /* starting ether frame data */ -+}; -+#endif /* linux */ -+ -+ -+#if defined(__NetBSD__) -+#define SIOCSETCUP _IOW('e', 0, struct ifreq) -+#define SIOCSETCDOWN _IOW('e', 1, struct ifreq) -+#define SIOCSETCLOOP _IOW('e', 2, struct ifreq) -+#define SIOCGETCDUMP _IOWR('e', 3, struct ifreq) -+#define SIOCSETCSETMSGLEVEL _IOW('e', 4, struct ifreq) -+#define SIOCSETCPROMISC _IOW('e', 5, struct ifreq) -+#define SIOCSETCTXDOWN _IOW('e', 6, struct ifreq) /* obsolete */ -+#define SIOCSETCSPEED _IOW('e', 7, struct ifreq) -+#define SIOCTXGEN _IOW('e', 8, struct ifreq) -+#define SIOCGETCPHYRD _IOWR('e', 9, struct ifreq) -+#define SIOCSETCPHYWR _IOW('e', 10, struct ifreq) -+#define SIOCSETCQOS _IOW('e', 11, struct ifreq) -+#define SIOCGETCPHYRD2 _IOWR('e', 12, struct ifreq) -+#define SIOCSETCPHYWR2 _IOW('e', 13, struct ifreq) -+#define SIOCGETCROBORD _IOWR('e', 14, struct ifreq) -+#define SIOCSETCROBOWR _IOW('e', 15, struct ifreq) -+ -+/* arg to SIOCTXGEN */ -+struct txg { -+ uint32 num; /* number of frames to send */ -+ uint32 delay; /* delay in microseconds between sending each */ -+ uint32 size; /* size of ether frame to send */ -+ uchar buf[1514]; /* starting ether frame data */ -+}; -+#endif /* __NetBSD__ */ -+ -+/* -+ * custom OID support -+ * -+ * 0xFF - implementation specific OID -+ * 0xE4 - first byte of Broadcom PCI vendor ID -+ * 0x14 - second byte of Broadcom PCI vendor ID -+ * 0xXX - the custom OID number -+ */ -+#define ET_OID_BASE 0xFFE41400 /* OID Base for ET */ -+ -+#define OID_ET_UP (ET_OID_BASE + ETCUP) -+#define OID_ET_DOWN (ET_OID_BASE + ETCDOWN) -+#define OID_ET_LOOP (ET_OID_BASE + ETCLOOP) -+#define OID_ET_DUMP (ET_OID_BASE + ETCDUMP) -+#define OID_ET_SETMSGLEVEL (ET_OID_BASE + ETCSETMSGLEVEL) -+#define OID_ET_PROMISC (ET_OID_BASE + ETCPROMISC) -+#define OID_ET_TXDOWN (ET_OID_BASE + 6) -+#define OID_ET_SPEED (ET_OID_BASE + ETCSPEED) -+#define OID_ET_GETINSTANCE (ET_OID_BASE + 8) -+#define OID_ET_SETCALLBACK (ET_OID_BASE + 9) -+#define OID_ET_UNSETCALLBACK (ET_OID_BASE + 10) -+ -+#define IS_ET_OID(oid) (((oid) & 0xFFFFFF00) == 0xFFE41400) -+ -+#define ET_ISQUERYOID(oid) ((oid == OID_ET_DUMP) || (oid == OID_ET_GETINSTANCE)) -+ -+/* OID_ET_SETCALLBACK data type */ -+typedef struct et_cb { -+ void (*fn)(void *, int); /* Callback function */ -+ void *context; /* Passed to callback function */ -+} et_cb_t; -+ -+#endif /* _etioctl_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/gmac_common.h b/drivers/net/ethernet/broadcom/gmac/src/include/gmac_common.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/gmac_common.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/gmac_common.h 2017-11-09 17:53:43.959311000 +0800 -@@ -0,0 +1,560 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * gmacdefs - Broadcom gmac (Unimac) specific definitions -+ * -+ * $Id: gmac_common.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _gmac_common_core_h_ -+#define _gmac_common_core_h_ -+ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD XSTR(__LINE__) -+#endif -+ -+typedef volatile struct _gmac_commonregs { -+ uint32 stag0; -+ uint32 stag1; -+ uint32 stag2; -+ uint32 stag3; -+ uint32 PAD[4]; -+ uint32 parsercontrol; -+ uint32 mib_max_len; -+ uint32 PAD[54]; -+ uint32 phyaccess; -+ uint32 phycontrol; -+ uint32 PAD[2]; -+ uint32 gmac0_rgmii_cntl; -+ uint32 PAD[59]; -+ uint32 cfp_access; -+ uint32 PAD[3]; -+ uint32 cfp_tcam_data0; -+ uint32 cfp_tcam_data1; -+ uint32 cfp_tcam_data2; -+ uint32 cfp_tcam_data3; -+ uint32 cfp_tcam_data4; -+ uint32 cfp_tcam_data5; -+ uint32 cfp_tcam_data6; -+ uint32 cfp_tcam_data7; -+ uint32 cfp_tcam_mask0; -+ uint32 cfp_tcam_mask1; -+ uint32 cfp_tcam_mask2; -+ uint32 cfp_tcam_mask3; -+ uint32 cfp_tcam_mask4; -+ uint32 cfp_tcam_mask5; -+ uint32 cfp_tcam_mask6; -+ uint32 cfp_tcam_mask7; -+ uint32 cfp_action_data; -+ uint32 PAD[19]; -+ uint32 tcam_bist_cntl; -+ uint32 tcam_bist_status; -+ uint32 tcam_cmp_status; -+ uint32 tcam_disable; -+ uint32 PAD[16]; -+ uint32 tcam_test_cntl; -+ uint32 PAD[3]; -+ uint32 udf_0_a3_a0; -+ uint32 udf_0_a7_a4; -+ uint32 udf_0_a8; -+ uint32 PAD[1]; -+ uint32 udf_1_a3_a0; -+ uint32 udf_1_a7_a4; -+ uint32 udf_1_a8; -+ uint32 PAD[1]; -+ uint32 udf_2_a3_a0; -+ uint32 udf_2_a7_a4; -+ uint32 udf_2_a8; -+ uint32 PAD[1]; -+ uint32 udf_0_b3_b0; -+ uint32 udf_0_b7_b4; -+ uint32 udf_0_b8; -+ uint32 PAD[1]; -+ uint32 udf_1_b3_b0; -+ uint32 udf_1_b7_b4; -+ uint32 udf_1_b8; -+ uint32 PAD[1]; -+ uint32 udf_2_b3_b0; -+ uint32 udf_2_b7_b4; -+ uint32 udf_2_b8; -+ uint32 PAD[1]; -+ uint32 udf_0_c3_c0; -+ uint32 udf_0_c7_c4; -+ uint32 udf_0_c8; -+ uint32 PAD[1]; -+ uint32 udf_1_c3_c0; -+ uint32 udf_1_c7_c4; -+ uint32 udf_1_c8; -+ uint32 PAD[1]; -+ uint32 udf_2_c3_c0; -+ uint32 udf_2_c7_c4; -+ uint32 udf_2_c8; -+ uint32 PAD[1]; -+ uint32 udf_0_d3_d0; -+ uint32 udf_0_d7_d4; -+ uint32 udf_0_d11_d8; -+} gmac_commonregs_t; -+ -+/* stag0 offset0x0 */ -+#define STAG0_TPID_SHIFT 0 -+#define STAG0_TPID_MASK 0xffff -+ -+/* stag1 offset0x4 */ -+#define STAG1_TPID_SHIFT 0 -+#define STAG1_TPID_MASK 0xffff -+ -+/* stag2 offset0x8 */ -+#define STAG2_TPID_SHIFT 0 -+#define STAG2_TPID_MASK 0xffff -+ -+/* stag3 offset0xc */ -+#define STAG3_TPID_SHIFT 0 -+#define STAG3_TPID_MASK 0xffff -+ -+/* parsercontrol offset0x20 */ -+#define PARSERCONTROL_MAX_PARSER_LEN_TH_SHIFT 0 -+#define PARSERCONTROL_MAX_PARSER_LEN_TH_MASK 0x3fff -+ -+/* mib_max_len offset0x24 */ -+#define MIB_MAX_LEN_MIB_MAX_LEN_SHIFT 0 -+#define MIB_MAX_LEN_MIB_MAX_LEN_MASK 0x3fff -+ -+/* phyaccess offset0x100 */ -+#define PHYACCESS_TRIGGER_SHIFT 30 -+#define PHYACCESS_TRIGGER_MASK 0x40000000 -+#define PHYACCESS_WR_CMD_SHIFT 29 -+#define PHYACCESS_WR_CMD_MASK 0x20000000 -+#define PHYACCESS_CPU_REG_ADDR_SHIFT 24 -+#define PHYACCESS_CPU_REG_ADDR_MASK 0x1f000000 -+#define PHYACCESS_CPU_PHY_ADDR_SHIFT 16 -+#define PHYACCESS_CPU_PHY_ADDR_MASK 0x1f0000 -+#define PHYACCESS_ACC_DATA_SHIFT 0 -+#define PHYACCESS_ACC_DATA_MASK 0xffff -+ -+/* phycontrol offset0x104 */ -+#define PHYCONTROL_SD_ACCESS_EN_SHIFT 25 -+#define PHYCONTROL_SD_ACCESS_EN_MASK 0x2000000 -+#define PHYCONTROL_NWAY_AUTO_POLLING_EN_SHIFT 24 -+#define PHYCONTROL_NWAY_AUTO_POLLING_EN_MASK 0x1000000 -+#define PHYCONTROL_MDC_TRANSITION_EN_SHIFT 23 -+#define PHYCONTROL_MDC_TRANSITION_EN_MASK 0x800000 -+#define PHYCONTROL_MDC_CYCLE_TH_SHIFT 16 -+#define PHYCONTROL_MDC_CYCLE_TH_MASK 0x7f0000 -+#define PHYCONTROL_EXT_PHY_ADDR_SHIFT 0 -+#define PHYCONTROL_EXT_PHY_ADDR_MASK 0x1f -+ -+/* gmac0_rgmii_cntl offset0x110 */ -+#define GMAC0_RGMII_CNTL_TIMING_SEL_SHIFT 0 -+#define GMAC0_RGMII_CNTL_TIMING_SEL_MASK 0x1 -+#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_SHIFT 1 -+#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_MASK 0x2 -+#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_SHIFT 2 -+#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_MASK 0x4 -+#define GMAC0_RGMII_CNTL_DEL_STRB_SHIFT 3 -+#define GMAC0_RGMII_CNTL_DEL_STRB_MASK 0x8 -+#define GMAC0_RGMII_CNTL_DEL_VALUE_SHIFT 4 -+#define GMAC0_RGMII_CNTL_DEL_VALUE_MASK 0x70 -+#define GMAC0_RGMII_CNTL_DEL_ADDR_SHIFT 7 -+#define GMAC0_RGMII_CNTL_DEL_ADDR_MASK 0x780 -+ -+/* cfp_access offset0x200 */ -+#define CFP_ACCESS_OP_START_DONE_SHIFT 0 -+#define CFP_ACCESS_OP_START_DONE_MASK 0x1 -+#define CFP_ACCESS_OP_SEL_SHIFT 1 -+#define CFP_ACCESS_OP_SEL_MASK 0xe -+#define CFP_ACCESS_CFP_RAM_CLEAR_SHIFT 4 -+#define CFP_ACCESS_CFP_RAM_CLEAR_MASK 0x10 -+#define CFP_ACCESS_RESERVED1_SHIFT 5 -+#define CFP_ACCESS_RESERVED1_MASK 0x3e0 -+#define CFP_ACCESS_RAM_SEL_SHIFT 10 -+#define CFP_ACCESS_RAM_SEL_MASK 0x7c00 -+#define CFP_ACCESS_TCAM_RESET_SHIFT 15 -+#define CFP_ACCESS_TCAM_RESET_MASK 0x8000 -+#define CFP_ACCESS_XCESS_ADDR_SHIFT 16 -+#define CFP_ACCESS_XCESS_ADDR_MASK 0x1ff0000 -+#define CFP_ACCESS_RESERVED0_SHIFT 25 -+#define CFP_ACCESS_RESERVED0_MASK 0xe000000 -+#define CFP_ACCESS_RD_STATUS_SHIFT 28 -+#define CFP_ACCESS_RD_STATUS_MASK 0xf0000000 -+ -+/* cfp_tcam_data0 offset0x210 */ -+#define CFP_TCAM_DATA0_DATA_SHIFT 0 -+#define CFP_TCAM_DATA0_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data1 offset0x214 */ -+#define CFP_TCAM_DATA1_DATA_SHIFT 0 -+#define CFP_TCAM_DATA1_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data2 offset0x218 */ -+#define CFP_TCAM_DATA2_DATA_SHIFT 0 -+#define CFP_TCAM_DATA2_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data3 offset0x21c */ -+#define CFP_TCAM_DATA3_DATA_SHIFT 0 -+#define CFP_TCAM_DATA3_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data4 offset0x220 */ -+#define CFP_TCAM_DATA4_DATA_SHIFT 0 -+#define CFP_TCAM_DATA4_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data5 offset0x224 */ -+#define CFP_TCAM_DATA5_DATA_SHIFT 0 -+#define CFP_TCAM_DATA5_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data6 offset0x228 */ -+#define CFP_TCAM_DATA6_DATA_SHIFT 0 -+#define CFP_TCAM_DATA6_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_data7 offset0x22c */ -+#define CFP_TCAM_DATA7_DATA_SHIFT 0 -+#define CFP_TCAM_DATA7_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask0 offset0x230 */ -+#define CFP_TCAM_MASK0_DATA_SHIFT 0 -+#define CFP_TCAM_MASK0_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask1 offset0x234 */ -+#define CFP_TCAM_MASK1_DATA_SHIFT 0 -+#define CFP_TCAM_MASK1_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask2 offset0x238 */ -+#define CFP_TCAM_MASK2_DATA_SHIFT 0 -+#define CFP_TCAM_MASK2_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask3 offset0x23c */ -+#define CFP_TCAM_MASK3_DATA_SHIFT 0 -+#define CFP_TCAM_MASK3_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask4 offset0x240 */ -+#define CFP_TCAM_MASK4_DATA_SHIFT 0 -+#define CFP_TCAM_MASK4_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask5 offset0x244 */ -+#define CFP_TCAM_MASK5_DATA_SHIFT 0 -+#define CFP_TCAM_MASK5_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask6 offset0x248 */ -+#define CFP_TCAM_MASK6_DATA_SHIFT 0 -+#define CFP_TCAM_MASK6_DATA_MASK 0xffffffff -+ -+/* cfp_tcam_mask7 offset0x24c */ -+#define CFP_TCAM_MASK7_DATA_SHIFT 0 -+#define CFP_TCAM_MASK7_DATA_MASK 0xffffffff -+ -+/* cfp_action_data offset0x250 */ -+#define CFP_ACTION_DATA_CHAINID_SHIFT 0 -+#define CFP_ACTION_DATA_CHAINID_MASK 0xff -+#define CFP_ACTION_DATA_CHANNELID_SHIFT 8 -+#define CFP_ACTION_DATA_CHANNELID_MASK 0xf00 -+#define CFP_ACTION_DATA_DROP_SHIFT 12 -+#define CFP_ACTION_DATA_DROP_MASK 0x1000 -+#define CFP_ACTION_DATA_RESERVED_SHIFT 13 -+#define CFP_ACTION_DATA_RESERVED_MASK 0xffffe000 -+ -+/* tcam_bist_cntl offset0x2a0 */ -+#define TCAM_BIST_CNTL_TCAM_BIST_EN_SHIFT 0 -+#define TCAM_BIST_CNTL_TCAM_BIST_EN_MASK 0x1 -+#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_SHIFT 1 -+#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_MASK 0x6 -+#define TCAM_BIST_CNTL_RESERVED1_SHIFT 3 -+#define TCAM_BIST_CNTL_RESERVED1_MASK 0x8 -+#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_SHIFT 4 -+#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_MASK 0xf0 -+#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_SHIFT 8 -+#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_MASK 0xff00 -+#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_SHIFT 16 -+#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_MASK 0x10000 -+#define TCAM_BIST_CNTL_RESERVED_SHIFT 17 -+#define TCAM_BIST_CNTL_RESERVED_MASK 0x7ffe0000 -+#define TCAM_BIST_CNTL_TCAM_BIST_DONE_SHIFT 31 -+#define TCAM_BIST_CNTL_TCAM_BIST_DONE_MASK 0x80000000 -+ -+/* tcam_bist_status offset0x2a4 */ -+#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_SHIFT 0 -+#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_MASK 0xffff -+#define TCAM_BIST_STATUS_RESERVED_SHIFT 16 -+#define TCAM_BIST_STATUS_RESERVED_MASK 0xffff0000 -+ -+/* tcam_cmp_status offset0x2a8 */ -+#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_SHIFT 0 -+#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_MASK 0x1ff -+#define TCAM_CMP_STATUS_RESERVED2_SHIFT 9 -+#define TCAM_CMP_STATUS_RESERVED2_MASK 0x7e00 -+#define TCAM_CMP_STATUS_TCAM_HIT_SHIFT 15 -+#define TCAM_CMP_STATUS_TCAM_HIT_MASK 0x8000 -+#define TCAM_CMP_STATUS_RESERVED1_SHIFT 16 -+#define TCAM_CMP_STATUS_RESERVED1_MASK 0xffff0000 -+ -+/* tcam_disable offset0x2ac */ -+#define TCAM_DISABLE_TCAM_DISABLE_SHIFT 0 -+#define TCAM_DISABLE_TCAM_DISABLE_MASK 0xf -+#define TCAM_DISABLE_RESERVED_SHIFT 4 -+#define TCAM_DISABLE_RESERVED_MASK 0xfffffff0 -+ -+/* tcam_test_cntl offset0x2f0 */ -+#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_SHIFT 0 -+#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_MASK 0x7ff -+#define TCAM_TEST_CNTL_RESERVED_SHIFT 11 -+#define TCAM_TEST_CNTL_RESERVED_MASK 0xfffff800 -+ -+/* udf_0_a3_a0 offset0x300 */ -+#define UDF_0_A3_A0_CFG_UDF_0_A0_SHIFT 0 -+#define UDF_0_A3_A0_CFG_UDF_0_A0_MASK 0xff -+#define UDF_0_A3_A0_CFG_UDF_0_A1_SHIFT 8 -+#define UDF_0_A3_A0_CFG_UDF_0_A1_MASK 0xff00 -+#define UDF_0_A3_A0_CFG_UDF_0_A2_SHIFT 16 -+#define UDF_0_A3_A0_CFG_UDF_0_A2_MASK 0xff0000 -+#define UDF_0_A3_A0_CFG_UDF_0_A3_SHIFT 24 -+#define UDF_0_A3_A0_CFG_UDF_0_A3_MASK 0xff000000 -+ -+/* udf_0_a7_a4 offset0x304 */ -+#define UDF_0_A7_A4_CFG_UDF_0_A4_SHIFT 0 -+#define UDF_0_A7_A4_CFG_UDF_0_A4_MASK 0xff -+#define UDF_0_A7_A4_CFG_UDF_0_A5_SHIFT 8 -+#define UDF_0_A7_A4_CFG_UDF_0_A5_MASK 0xff00 -+#define UDF_0_A7_A4_CFG_UDF_0_A6_SHIFT 16 -+#define UDF_0_A7_A4_CFG_UDF_0_A6_MASK 0xff0000 -+#define UDF_0_A7_A4_CFG_UDF_0_A7_SHIFT 24 -+#define UDF_0_A7_A4_CFG_UDF_0_A7_MASK 0xff000000 -+ -+/* udf_0_a8 offset0x308 */ -+#define UDF_0_A8_CFG_UDF_0_A8_SHIFT 0 -+#define UDF_0_A8_CFG_UDF_0_A8_MASK 0xff -+ -+/* udf_1_a3_a0 offset0x310 */ -+#define UDF_1_A3_A0_CFG_UDF_1_A0_SHIFT 0 -+#define UDF_1_A3_A0_CFG_UDF_1_A0_MASK 0xff -+#define UDF_1_A3_A0_CFG_UDF_1_A1_SHIFT 8 -+#define UDF_1_A3_A0_CFG_UDF_1_A1_MASK 0xff00 -+#define UDF_1_A3_A0_CFG_UDF_1_A2_SHIFT 16 -+#define UDF_1_A3_A0_CFG_UDF_1_A2_MASK 0xff0000 -+#define UDF_1_A3_A0_CFG_UDF_1_A3_SHIFT 24 -+#define UDF_1_A3_A0_CFG_UDF_1_A3_MASK 0xff000000 -+ -+/* udf_1_a7_a4 offset0x314 */ -+#define UDF_1_A7_A4_CFG_UDF_1_A4_SHIFT 0 -+#define UDF_1_A7_A4_CFG_UDF_1_A4_MASK 0xff -+#define UDF_1_A7_A4_CFG_UDF_1_A5_SHIFT 8 -+#define UDF_1_A7_A4_CFG_UDF_1_A5_MASK 0xff00 -+#define UDF_1_A7_A4_CFG_UDF_1_A6_SHIFT 16 -+#define UDF_1_A7_A4_CFG_UDF_1_A6_MASK 0xff0000 -+#define UDF_1_A7_A4_CFG_UDF_1_A7_SHIFT 24 -+#define UDF_1_A7_A4_CFG_UDF_1_A7_MASK 0xff000000 -+ -+/* udf_1_a8 offset0x318 */ -+#define UDF_1_A8_CFG_UDF_1_A8_SHIFT 0 -+#define UDF_1_A8_CFG_UDF_1_A8_MASK 0xff -+ -+/* udf_2_a3_a0 offset0x320 */ -+#define UDF_2_A3_A0_CFG_UDF_2_A0_SHIFT 0 -+#define UDF_2_A3_A0_CFG_UDF_2_A0_MASK 0xff -+#define UDF_2_A3_A0_CFG_UDF_2_A1_SHIFT 8 -+#define UDF_2_A3_A0_CFG_UDF_2_A1_MASK 0xff00 -+#define UDF_2_A3_A0_CFG_UDF_2_A2_SHIFT 16 -+#define UDF_2_A3_A0_CFG_UDF_2_A2_MASK 0xff0000 -+#define UDF_2_A3_A0_CFG_UDF_2_A3_SHIFT 24 -+#define UDF_2_A3_A0_CFG_UDF_2_A3_MASK 0xff000000 -+ -+/* udf_2_a7_a4 offset0x324 */ -+#define UDF_2_A7_A4_CFG_UDF_2_A4_SHIFT 0 -+#define UDF_2_A7_A4_CFG_UDF_2_A4_MASK 0xff -+#define UDF_2_A7_A4_CFG_UDF_2_A5_SHIFT 8 -+#define UDF_2_A7_A4_CFG_UDF_2_A5_MASK 0xff00 -+#define UDF_2_A7_A4_CFG_UDF_2_A6_SHIFT 16 -+#define UDF_2_A7_A4_CFG_UDF_2_A6_MASK 0xff0000 -+#define UDF_2_A7_A4_CFG_UDF_2_A7_SHIFT 24 -+#define UDF_2_A7_A4_CFG_UDF_2_A7_MASK 0xff000000 -+ -+/* udf_2_a8 offset0x328 */ -+#define UDF_2_A8_CFG_UDF_2_A8_SHIFT 0 -+#define UDF_2_A8_CFG_UDF_2_A8_MASK 0xff -+ -+/* udf_0_b3_b0 offset0x330 */ -+#define UDF_0_B3_B0_CFG_UDF_0_B0_SHIFT 0 -+#define UDF_0_B3_B0_CFG_UDF_0_B0_MASK 0xff -+#define UDF_0_B3_B0_CFG_UDF_0_B1_SHIFT 8 -+#define UDF_0_B3_B0_CFG_UDF_0_B1_MASK 0xff00 -+#define UDF_0_B3_B0_CFG_UDF_0_B2_SHIFT 16 -+#define UDF_0_B3_B0_CFG_UDF_0_B2_MASK 0xff0000 -+#define UDF_0_B3_B0_CFG_UDF_0_B3_SHIFT 24 -+#define UDF_0_B3_B0_CFG_UDF_0_B3_MASK 0xff000000 -+ -+/* udf_0_b7_b4 offset0x334 */ -+#define UDF_0_B7_B4_CFG_UDF_0_B4_SHIFT 0 -+#define UDF_0_B7_B4_CFG_UDF_0_B4_MASK 0xff -+#define UDF_0_B7_B4_CFG_UDF_0_B5_SHIFT 8 -+#define UDF_0_B7_B4_CFG_UDF_0_B5_MASK 0xff00 -+#define UDF_0_B7_B4_CFG_UDF_0_B6_SHIFT 16 -+#define UDF_0_B7_B4_CFG_UDF_0_B6_MASK 0xff0000 -+#define UDF_0_B7_B4_CFG_UDF_0_B7_SHIFT 24 -+#define UDF_0_B7_B4_CFG_UDF_0_B7_MASK 0xff000000 -+ -+/* udf_0_b8 offset0x338 */ -+#define UDF_0_B8_CFG_UDF_0_B8_SHIFT 0 -+#define UDF_0_B8_CFG_UDF_0_B8_MASK 0xff -+ -+/* udf_1_b3_b0 offset0x340 */ -+#define UDF_1_B3_B0_CFG_UDF_1_B0_SHIFT 0 -+#define UDF_1_B3_B0_CFG_UDF_1_B0_MASK 0xff -+#define UDF_1_B3_B0_CFG_UDF_1_B1_SHIFT 8 -+#define UDF_1_B3_B0_CFG_UDF_1_B1_MASK 0xff00 -+#define UDF_1_B3_B0_CFG_UDF_1_B2_SHIFT 16 -+#define UDF_1_B3_B0_CFG_UDF_1_B2_MASK 0xff0000 -+#define UDF_1_B3_B0_CFG_UDF_1_B3_SHIFT 24 -+#define UDF_1_B3_B0_CFG_UDF_1_B3_MASK 0xff000000 -+ -+/* udf_1_b7_b4 offset0x344 */ -+#define UDF_1_B7_B4_CFG_UDF_1_B4_SHIFT 0 -+#define UDF_1_B7_B4_CFG_UDF_1_B4_MASK 0xff -+#define UDF_1_B7_B4_CFG_UDF_1_B5_SHIFT 8 -+#define UDF_1_B7_B4_CFG_UDF_1_B5_MASK 0xff00 -+#define UDF_1_B7_B4_CFG_UDF_1_B6_SHIFT 16 -+#define UDF_1_B7_B4_CFG_UDF_1_B6_MASK 0xff0000 -+#define UDF_1_B7_B4_CFG_UDF_1_B7_SHIFT 24 -+#define UDF_1_B7_B4_CFG_UDF_1_B7_MASK 0xff000000 -+ -+/* udf_1_b8 offset0x348 */ -+#define UDF_1_B8_CFG_UDF_1_B8_SHIFT 0 -+#define UDF_1_B8_CFG_UDF_1_B8_MASK 0xff -+ -+/* udf_2_b3_b0 offset0x350 */ -+#define UDF_2_B3_B0_CFG_UDF_2_B0_SHIFT 0 -+#define UDF_2_B3_B0_CFG_UDF_2_B0_MASK 0xff -+#define UDF_2_B3_B0_CFG_UDF_2_B1_SHIFT 8 -+#define UDF_2_B3_B0_CFG_UDF_2_B1_MASK 0xff00 -+#define UDF_2_B3_B0_CFG_UDF_2_B2_SHIFT 16 -+#define UDF_2_B3_B0_CFG_UDF_2_B2_MASK 0xff0000 -+#define UDF_2_B3_B0_CFG_UDF_2_B3_SHIFT 24 -+#define UDF_2_B3_B0_CFG_UDF_2_B3_MASK 0xff000000 -+ -+/* udf_2_b7_b4 offset0x354 */ -+#define UDF_2_B7_B4_CFG_UDF_2_B4_SHIFT 0 -+#define UDF_2_B7_B4_CFG_UDF_2_B4_MASK 0xff -+#define UDF_2_B7_B4_CFG_UDF_2_B5_SHIFT 8 -+#define UDF_2_B7_B4_CFG_UDF_2_B5_MASK 0xff00 -+#define UDF_2_B7_B4_CFG_UDF_2_B6_SHIFT 16 -+#define UDF_2_B7_B4_CFG_UDF_2_B6_MASK 0xff0000 -+#define UDF_2_B7_B4_CFG_UDF_2_B7_SHIFT 24 -+#define UDF_2_B7_B4_CFG_UDF_2_B7_MASK 0xff000000 -+ -+/* udf_2_b8 offset0x358 */ -+#define UDF_2_B8_CFG_UDF_2_B8_SHIFT 0 -+#define UDF_2_B8_CFG_UDF_2_B8_MASK 0xff -+ -+/* udf_0_c3_c0 offset0x360 */ -+#define UDF_0_C3_C0_CFG_UDF_0_C0_SHIFT 0 -+#define UDF_0_C3_C0_CFG_UDF_0_C0_MASK 0xff -+#define UDF_0_C3_C0_CFG_UDF_0_C1_SHIFT 8 -+#define UDF_0_C3_C0_CFG_UDF_0_C1_MASK 0xff00 -+#define UDF_0_C3_C0_CFG_UDF_0_C2_SHIFT 16 -+#define UDF_0_C3_C0_CFG_UDF_0_C2_MASK 0xff0000 -+#define UDF_0_C3_C0_CFG_UDF_0_C3_SHIFT 24 -+#define UDF_0_C3_C0_CFG_UDF_0_C3_MASK 0xff000000 -+ -+/* udf_0_c7_c4 offset0x364 */ -+#define UDF_0_C7_C4_CFG_UDF_0_C4_SHIFT 0 -+#define UDF_0_C7_C4_CFG_UDF_0_C4_MASK 0xff -+#define UDF_0_C7_C4_CFG_UDF_0_C5_SHIFT 8 -+#define UDF_0_C7_C4_CFG_UDF_0_C5_MASK 0xff00 -+#define UDF_0_C7_C4_CFG_UDF_0_C6_SHIFT 16 -+#define UDF_0_C7_C4_CFG_UDF_0_C6_MASK 0xff0000 -+#define UDF_0_C7_C4_CFG_UDF_0_C7_SHIFT 24 -+#define UDF_0_C7_C4_CFG_UDF_0_C7_MASK 0xff000000 -+ -+/* udf_0_c8 offset0x368 */ -+#define UDF_0_C8_CFG_UDF_0_C8_SHIFT 0 -+#define UDF_0_C8_CFG_UDF_0_C8_MASK 0xff -+ -+/* udf_1_c3_c0 offset0x370 */ -+#define UDF_1_C3_C0_CFG_UDF_1_C0_SHIFT 0 -+#define UDF_1_C3_C0_CFG_UDF_1_C0_MASK 0xff -+#define UDF_1_C3_C0_CFG_UDF_1_C1_SHIFT 8 -+#define UDF_1_C3_C0_CFG_UDF_1_C1_MASK 0xff00 -+#define UDF_1_C3_C0_CFG_UDF_1_C2_SHIFT 16 -+#define UDF_1_C3_C0_CFG_UDF_1_C2_MASK 0xff0000 -+#define UDF_1_C3_C0_CFG_UDF_1_C3_SHIFT 24 -+#define UDF_1_C3_C0_CFG_UDF_1_C3_MASK 0xff000000 -+ -+/* udf_1_c7_c4 offset0x374 */ -+#define UDF_1_C7_C4_CFG_UDF_1_C4_SHIFT 0 -+#define UDF_1_C7_C4_CFG_UDF_1_C4_MASK 0xff -+#define UDF_1_C7_C4_CFG_UDF_1_C5_SHIFT 8 -+#define UDF_1_C7_C4_CFG_UDF_1_C5_MASK 0xff00 -+#define UDF_1_C7_C4_CFG_UDF_1_C6_SHIFT 16 -+#define UDF_1_C7_C4_CFG_UDF_1_C6_MASK 0xff0000 -+#define UDF_1_C7_C4_CFG_UDF_1_C7_SHIFT 24 -+#define UDF_1_C7_C4_CFG_UDF_1_C7_MASK 0xff000000 -+ -+/* udf_1_c8 offset0x378 */ -+#define UDF_1_C8_CFG_UDF_1_C8_SHIFT 0 -+#define UDF_1_C8_CFG_UDF_1_C8_MASK 0xff -+ -+/* udf_2_c3_c0 offset0x380 */ -+#define UDF_2_C3_C0_CFG_UDF_2_C0_SHIFT 0 -+#define UDF_2_C3_C0_CFG_UDF_2_C0_MASK 0xff -+#define UDF_2_C3_C0_CFG_UDF_2_C1_SHIFT 8 -+#define UDF_2_C3_C0_CFG_UDF_2_C1_MASK 0xff00 -+#define UDF_2_C3_C0_CFG_UDF_2_C2_SHIFT 16 -+#define UDF_2_C3_C0_CFG_UDF_2_C2_MASK 0xff0000 -+#define UDF_2_C3_C0_CFG_UDF_2_C3_SHIFT 24 -+#define UDF_2_C3_C0_CFG_UDF_2_C3_MASK 0xff000000 -+ -+/* udf_2_c7_c4 offset0x384 */ -+#define UDF_2_C7_C4_CFG_UDF_2_C4_SHIFT 0 -+#define UDF_2_C7_C4_CFG_UDF_2_C4_MASK 0xff -+#define UDF_2_C7_C4_CFG_UDF_2_C5_SHIFT 8 -+#define UDF_2_C7_C4_CFG_UDF_2_C5_MASK 0xff00 -+#define UDF_2_C7_C4_CFG_UDF_2_C6_SHIFT 16 -+#define UDF_2_C7_C4_CFG_UDF_2_C6_MASK 0xff0000 -+#define UDF_2_C7_C4_CFG_UDF_2_C7_SHIFT 24 -+#define UDF_2_C7_C4_CFG_UDF_2_C7_MASK 0xff000000 -+ -+/* udf_2_c8 offset0x388 */ -+#define UDF_2_C8_CFG_UDF_2_C8_SHIFT 0 -+#define UDF_2_C8_CFG_UDF_2_C8_MASK 0xff -+ -+/* udf_0_d3_d0 offset0x390 */ -+#define UDF_0_D3_D0_CFG_UDF_0_D0_SHIFT 0 -+#define UDF_0_D3_D0_CFG_UDF_0_D0_MASK 0xff -+#define UDF_0_D3_D0_CFG_UDF_0_D1_SHIFT 8 -+#define UDF_0_D3_D0_CFG_UDF_0_D1_MASK 0xff00 -+#define UDF_0_D3_D0_CFG_UDF_0_D2_SHIFT 16 -+#define UDF_0_D3_D0_CFG_UDF_0_D2_MASK 0xff0000 -+#define UDF_0_D3_D0_CFG_UDF_0_D3_SHIFT 24 -+#define UDF_0_D3_D0_CFG_UDF_0_D3_MASK 0xff000000 -+ -+/* udf_0_d7_d4 offset0x394 */ -+#define UDF_0_D7_D4_CFG_UDF_0_D4_SHIFT 0 -+#define UDF_0_D7_D4_CFG_UDF_0_D4_MASK 0xff -+#define UDF_0_D7_D4_CFG_UDF_0_D5_SHIFT 8 -+#define UDF_0_D7_D4_CFG_UDF_0_D5_MASK 0xff00 -+#define UDF_0_D7_D4_CFG_UDF_0_D6_SHIFT 16 -+#define UDF_0_D7_D4_CFG_UDF_0_D6_MASK 0xff0000 -+#define UDF_0_D7_D4_CFG_UDF_0_D7_SHIFT 24 -+#define UDF_0_D7_D4_CFG_UDF_0_D7_MASK 0xff000000 -+ -+/* udf_0_d11_d8 offset0x398 */ -+#define UDF_0_D11_D8_CFG_UDF_0_D8_SHIFT 0 -+#define UDF_0_D11_D8_CFG_UDF_0_D8_MASK 0xff -+#define UDF_0_D11_D8_CFG_UDF_0_D9_SHIFT 8 -+#define UDF_0_D11_D8_CFG_UDF_0_D9_MASK 0xff00 -+#define UDF_0_D11_D8_CFG_UDF_0_D10_SHIFT 16 -+#define UDF_0_D11_D8_CFG_UDF_0_D10_MASK 0xff0000 -+#define UDF_0_D11_D8_CFG_UDF_0_D11_SHIFT 24 -+#define UDF_0_D11_D8_CFG_UDF_0_D11_MASK 0xff000000 -+ -+#endif /* _gmac_common_core_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/gmac_core.h b/drivers/net/ethernet/broadcom/gmac/src/include/gmac_core.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/gmac_core.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/gmac_core.h 2017-11-09 17:53:43.960313000 +0800 -@@ -0,0 +1,304 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * gmacdefs - Broadcom gmac (Unimac) specific definitions -+ * -+ * $Id: gmac_core.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _gmac_core_h_ -+#define _gmac_core_h_ -+ -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+/* We have 4 DMA TX channels */ -+#define GMAC_NUM_DMA_TX 4 -+ -+typedef volatile struct { -+ dma64regs_t dmaxmt; /* dma tx */ -+ uint32 PAD[2]; -+ dma64regs_t dmarcv; /* dma rx */ -+ uint32 PAD[2]; -+} dma64_t; -+ -+/* -+ * Host Interface Registers -+ */ -+typedef volatile struct _gmacregs { -+ uint32 devcontrol; /* 0x000 */ -+ uint32 devstatus; /* 0x004 */ -+ uint32 PAD; -+ uint32 biststatus; /* 0x00c */ -+ uint32 PAD[4]; -+ uint32 intstatus; /* 0x020 */ -+ uint32 intmask; /* 0x024 */ -+ uint32 gptimer; /* 0x028 */ -+ uint32 PAD[53]; -+ uint32 intrecvlazy; /* 0x100 */ -+ uint32 flowctlthresh; /* 0x104 */ -+ uint32 wrrthresh; /* 0x108 */ -+ uint32 gmac_idle_cnt_thresh; /* 0x10c */ -+ uint32 PAD[28]; -+ uint32 phyaccess; /* 0x180 */ -+ uint32 PAD; -+ uint32 phycontrol; /* 0x188 */ -+ uint32 txqctl; /* 0x18c */ -+ uint32 rxqctl; /* 0x190 */ -+ uint32 gpioselect; /* 0x194 */ -+ uint32 gpio_output_en; /* 0x198 */ -+ uint32 PAD; /* 0x19c */ -+ uint32 txq_rxq_mem_ctl; /* 0x1a0 */ -+ uint32 memory_ecc_status; /* 0x1a4 */ -+ uint32 serdes_ctl; /* 0x1a8 */ -+ uint32 serdes_status0; /* 0x1ac */ -+ uint32 serdes_status1; /* 0x1b0 */ -+ uint32 PAD[11]; /* 0x1b4-1dc */ -+ uint32 clk_ctl_st; /* 0x1e0 */ -+ uint32 hw_war; /* 0x1e4 */ -+ uint32 pwrctl; /* 0x1e8 */ -+ uint32 PAD[5]; -+ -+ dma64_t dmaregs[GMAC_NUM_DMA_TX]; -+ -+ /* GAMC MIB counters */ -+ gmacmib_t mib; -+ uint32 PAD[245]; -+ -+ uint32 unimacversion; /* 0x800 */ -+ uint32 hdbkpctl; /* 0x804 */ -+ uint32 cmdcfg; /* 0x808 */ -+ uint32 macaddrhigh; /* 0x80c */ -+ uint32 macaddrlow; /* 0x810 */ -+ uint32 rxmaxlength; /* 0x814 */ -+ uint32 pausequanta; /* 0x818 */ -+ uint32 PAD[10]; -+ uint32 macmode; /* 0x844 */ -+ uint32 outertag; /* 0x848 */ -+ uint32 innertag; /* 0x84c */ -+ uint32 PAD[3]; -+ uint32 txipg; /* 0x85c */ -+ uint32 PAD[180]; -+ uint32 pausectl; /* 0xb30 */ -+ uint32 txflush; /* 0xb34 */ -+ uint32 rxstatus; /* 0xb38 */ -+ uint32 txstatus; /* 0xb3c */ -+} gmacregs_t; -+ -+#define GM_MIB_BASE 0x300 -+#define GM_MIB_LIMIT 0x800 -+ -+/* -+ * register-specific flag definitions -+ */ -+ -+/* device control */ -+#define DC_TSM 0x00000002 -+#define DC_CFCO 0x00000004 -+#define DC_RLSS 0x00000008 -+#define DC_MROR 0x00000010 -+#define DC_FCM_MASK 0x00000060 -+#define DC_FCM_SHIFT 5 -+#define DC_NAE 0x00000080 -+#define DC_TF 0x00000100 -+#define DC_RDS_MASK 0x00030000 -+#define DC_RDS_SHIFT 16 -+#define DC_TDS_MASK 0x000c0000 -+#define DC_TDS_SHIFT 18 -+ -+/* device status */ -+#define DS_RBF 0x00000001 -+#define DS_RDF 0x00000002 -+#define DS_RIF 0x00000004 -+#define DS_TBF 0x00000008 -+#define DS_TDF 0x00000010 -+#define DS_TIF 0x00000020 -+#define DS_PO 0x00000040 -+#define DS_MM_MASK 0x00000300 -+#define DS_MM_SHIFT 8 -+ -+/* bist status */ -+#define BS_MTF 0x00000001 -+#define BS_MRF 0x00000002 -+#define BS_TDB 0x00000004 -+#define BS_TIB 0x00000008 -+#define BS_TBF 0x00000010 -+#define BS_RDB 0x00000020 -+#define BS_RIB 0x00000040 -+#define BS_RBF 0x00000080 -+#define BS_URTF 0x00000100 -+#define BS_UTF 0x00000200 -+#define BS_URF 0x00000400 -+ -+/* interrupt status and mask registers */ -+#define I_MRO 0x00000001 -+#define I_MTO 0x00000002 -+#define I_TFD 0x00000004 -+#define I_LS 0x00000008 -+#define I_MDIO 0x00000010 -+#define I_MR 0x00000020 -+#define I_MT 0x00000040 -+#define I_TO 0x00000080 -+#define I_PDEE 0x00000400 -+#define I_PDE 0x00000800 -+#define I_DE 0x00001000 -+#define I_RDU 0x00002000 -+#define I_RFO 0x00004000 -+#define I_XFU 0x00008000 -+#define I_RI 0x00010000 -+#define I_XI0 0x01000000 -+#define I_XI1 0x02000000 -+#define I_XI2 0x04000000 -+#define I_XI3 0x08000000 -+#define I_INTMASK 0x0f01fcff -+#define I_ERRMASK 0x0000fc00 -+ -+/* interrupt receive lazy */ -+#define IRL_TO_MASK 0x00ffffff -+#define IRL_FC_MASK 0xff000000 -+#define IRL_FC_SHIFT 24 -+ -+/* flow control thresholds */ -+#define FCT_TT_MASK 0x00000fff -+#define FCT_RT_MASK 0x0fff0000 -+#define FCT_RT_SHIFT 16 -+ -+/* txq aribter wrr thresholds */ -+#define WRRT_Q0T_MASK 0x000000ff -+#define WRRT_Q1T_MASK 0x0000ff00 -+#define WRRT_Q1T_SHIFT 8 -+#define WRRT_Q2T_MASK 0x00ff0000 -+#define WRRT_Q2T_SHIFT 16 -+#define WRRT_Q3T_MASK 0xff000000 -+#define WRRT_Q3T_SHIFT 24 -+ -+/* phy access */ -+#define PA_DATA_MASK 0x0000ffff -+#define PA_ADDR_MASK 0x001f0000 -+#define PA_ADDR_SHIFT 16 -+#define PA_REG_MASK 0x1f000000 -+#define PA_REG_SHIFT 24 -+#define PA_WRITE 0x20000000 -+#define PA_START 0x40000000 -+ -+/* phy control */ -+#define PC_EPA_MASK 0x0000001f -+#define PC_MCT_MASK 0x007f0000 -+#define PC_MCT_SHIFT 16 -+#define PC_MTE 0x00800000 -+ -+/* rxq control */ -+#define RC_DBT_MASK 0x00000fff -+#define RC_DBT_SHIFT 0 -+#define RC_PTE 0x00001000 -+#define RC_MDP_MASK 0x3f000000 -+#define RC_MDP_SHIFT 24 -+ -+#define RC_MAC_DATA_PERIOD 9 -+ -+/* txq control */ -+#define TC_DBT_MASK 0x00000fff -+#define TC_DBT_SHIFT 0 -+ -+/* gpio select */ -+#define GS_GSC_MASK 0x0000000f -+#define GS_GSC_SHIFT 0 -+ -+/* gpio output enable */ -+#define GS_GOE_MASK 0x0000ffff -+#define GS_GOE_SHIFT 0 -+ -+/* gpio output enable */ -+#define SC_TX1G_FIFO_RST_MASK 0x00f00000 -+#define SC_TX1G_FIFO_RST_VAL 0x00f00000 -+#define SC_FORCE_SPD_STRAP_MASK 0x00060000 -+#define SC_FORCE_SPD_STRAP_VAL 0x00040000 -+#define SC_FORCE_SPD_100M_VAL 0x00020000 -+#define SC_FORCE_SPD_1G_VAL 0x00040000 -+#define SC_REF_TERM_SEL_MASK 0x00001000 -+#define SC_REFSEL_MASK 0x00000c00 -+#define SC_REFSEL_VAL 0x00000400 -+#define SC_REFDIV_MASK 0x00000300 -+#define SC_REFDIV_VAL 0x00000000 -+#define SC_LCREF_EN_MASK 0x00000040 -+#define SC_RSTB_PLL_MASK 0x00000010 -+#define SC_RSTB_MDIOREGS_MASK 0x00000008 -+#define SC_RSTB_HW_MASK 0x00000004 -+#define SC_IDDQ_MASK 0x00000002 -+#define SC_PWR_DOWN_MASK 0x00000001 -+ -+/* clk control status */ -+#define CS_FA 0x00000001 -+#define CS_FH 0x00000002 -+#define CS_FI 0x00000004 -+#define CS_AQ 0x00000008 -+#define CS_HQ 0x00000010 -+#define CS_FC 0x00000020 -+#define CS_ER 0x00000100 -+#define CS_AA 0x00010000 -+#define CS_HA 0x00020000 -+#define CS_BA 0x00040000 -+#define CS_BH 0x00080000 -+#define CS_ES 0x01000000 -+ -+/* command config */ -+#define CC_TE 0x00000001 -+#define CC_RE 0x00000002 -+#define CC_ES_MASK 0x0000000c -+#define CC_ES_SHIFT 2 -+#define CC_PROM 0x00000010 -+#define CC_PAD_EN 0x00000020 -+#define CC_CF 0x00000040 -+#define CC_PF 0x00000080 -+#define CC_RPI 0x00000100 -+#define CC_TAI 0x00000200 -+#define CC_HD 0x00000400 -+#define CC_HD_SHIFT 10 -+#define CC_SR 0x00002000 -+#define CC_ML 0x00008000 -+#define CC_OT 0x00020000 -+#define CC_OR 0x00040000 -+#define CC_AE 0x00400000 -+#define CC_CFE 0x00800000 -+#define CC_NLC 0x01000000 -+#define CC_RL 0x02000000 -+#define CC_RED 0x04000000 -+#define CC_PE 0x08000000 -+#define CC_TPI 0x10000000 -+#define CC_AT 0x20000000 -+ -+/* mac addr high */ -+#define MH_HI_MASK 0xffff -+#define MH_HI_SHIFT 16 -+#define MH_MID_MASK 0xffff -+#define MH_MID_SHIFT 0 -+ -+/* mac addr low */ -+#define ML_LO_MASK 0xffff -+#define ML_LO_SHIFT 0 -+ -+/* Core specific control flags */ -+#define SICF_SWCLKE 0x0004 -+#define SICF_SWRST 0x0008 -+ -+/* Core specific status flags */ -+#define SISF_SW_ATTACHED 0x0800 -+ -+#endif /* _gmac_core_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hndarm.h b/drivers/net/ethernet/broadcom/gmac/src/include/hndarm.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hndarm.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hndarm.h 2017-11-09 17:53:43.961300000 +0800 -@@ -0,0 +1,96 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * HND SiliconBackplane ARM core software interface. -+ * -+ * $Id: hndarm.h 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#ifndef _hndarm_h_ -+#define _hndarm_h_ -+ -+#include -+ -+extern void *hndarm_armr; -+extern uint32 hndarm_rev; -+ -+ -+extern void si_arm_init(si_t *sih); -+ -+#ifdef __ARM_ARCH_7A__ -+extern uint32 si_memc_get_ncdl(si_t *sih); -+#endif -+ -+extern void enable_arm_ints(uint32 which); -+extern void disable_arm_ints(uint32 which); -+ -+extern uint32 get_arm_cyclecount(void); -+extern void set_arm_cyclecount(uint32 ticks); -+ -+#ifdef __ARM_ARCH_7R__ -+extern uint32 get_arm_perfcount_enable(void); -+extern void set_arm_perfcount_enable(uint32 which); -+extern uint32 set_arm_perfcount_disable(void); -+ -+extern uint32 get_arm_perfcount_sel(void); -+extern void set_arm_perfcount_sel(uint32 which); -+ -+extern uint32 get_arm_perfcount_event(void); -+extern void set_arm_perfcount_event(uint32 which); -+ -+extern uint32 get_arm_perfcount(void); -+extern void set_arm_perfcount(uint32 which); -+ -+extern void enable_arm_cyclecount(void); -+extern void disable_arm_cyclecount(void); -+#endif /* __ARM_ARCH_7R__ */ -+ -+extern uint32 get_arm_inttimer(void); -+extern void set_arm_inttimer(uint32 ticks); -+ -+extern uint32 get_arm_intmask(void); -+extern void set_arm_intmask(uint32 ticks); -+ -+extern uint32 get_arm_intstatus(void); -+extern void set_arm_intstatus(uint32 ticks); -+ -+extern uint32 get_arm_firqmask(void); -+extern void set_arm_firqmask(uint32 ticks); -+ -+extern uint32 get_arm_firqstatus(void); -+extern void set_arm_firqstatus(uint32 ticks); -+ -+extern void arm_wfi(si_t *sih); -+extern void arm_jumpto(void *addr); -+ -+extern void traptest(void); -+ -+#ifdef BCMOVLHW -+#define BCMOVLHW_ENAB(sih) TRUE -+ -+extern int si_arm_ovl_remap(si_t *sih, void *virt, void *phys, uint size); -+extern int si_arm_ovl_reset(si_t *sih); -+extern bool si_arm_ovl_vaildaddr(si_t *sih, void *virt); -+extern bool si_arm_ovl_isenab(si_t *sih); -+extern bool si_arm_ovl_int(si_t *sih, uint32 pc); -+#else -+#define BCMOVLHW_ENAB(sih) FALSE -+ -+#define si_arm_ovl_remap(a, b, c, d) do {} while (0) -+#define si_arm_ovl_reset(a) do {} while (0) -+#define si_arm_ovl_int(a, b) FALSE -+#endif -+ -+#endif /* _hndarm_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hndchipc.h b/drivers/net/ethernet/broadcom/gmac/src/include/hndchipc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hndchipc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hndchipc.h 2017-11-09 17:53:43.962303000 +0800 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * HND SiliconBackplane chipcommon support. -+ * -+ * $Id: hndchipc.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _hndchipc_h_ -+#define _hndchipc_h_ -+ -+typedef void (*si_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); -+ -+extern void si_serial_init(si_t *sih, si_serial_init_fn add); -+ -+extern void *hnd_jtagm_init(si_t *sih, uint clkd, bool exttap); -+extern void hnd_jtagm_disable(si_t *sih, void *h); -+extern uint32 jtag_scan(si_t *sih, void *h, uint irsz, uint32 ir0, uint32 ir1, -+ uint drsz, uint32 dr0, uint32 *dr1, bool rti); -+ -+typedef void (*cc_isr_fn)(void* cbdata, uint32 ccintst); -+ -+extern bool si_cc_register_isr(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata); -+extern void si_cc_isr(si_t *sih, chipcregs_t *regs); -+ -+#endif /* _hndchipc_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hndcpu.h b/drivers/net/ethernet/broadcom/gmac/src/include/hndcpu.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hndcpu.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hndcpu.h 2017-11-09 17:53:43.963297000 +0800 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * HND SiliconBackplane MIPS/ARM cores software interface. -+ * -+ * $Id: hndcpu.h 258983 2011-05-11 09:59:25Z $ -+ */ -+ -+#ifndef _hndcpu_h_ -+#define _hndcpu_h_ -+ -+#if defined(mips) -+#include -+#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) -+#include -+#endif -+ -+extern uint si_irq(si_t *sih); -+extern uint32 si_cpu_clock(si_t *sih); -+extern uint32 si_mem_clock(si_t *sih); -+extern void hnd_cpu_wait(si_t *sih); -+extern void hnd_cpu_jumpto(void *addr); -+extern void hnd_cpu_reset(si_t *sih); -+extern void hnd_cpu_deadman_timer(si_t *sih, uint32 val); -+extern void si_router_coma(si_t *sih, int reset, int delay); -+extern void si_dmc_phyctl(si_t *sih, uint32 phyctl_val); -+ -+#endif /* _hndcpu_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hnddma.h b/drivers/net/ethernet/broadcom/gmac/src/include/hnddma.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hnddma.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hnddma.h 2017-11-09 17:53:43.964295000 +0800 -@@ -0,0 +1,317 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * $Id: hnddma.h 321146 2012-03-14 08:27:23Z $ -+ */ -+ -+#ifndef _hnddma_h_ -+#define _hnddma_h_ -+ -+#ifndef _hnddma_pub_ -+#define _hnddma_pub_ -+typedef const struct hnddma_pub hnddma_t; -+#endif /* _hnddma_pub_ */ -+ -+/* range param for dma_getnexttxp() and dma_txreclaim */ -+typedef enum txd_range { -+ HNDDMA_RANGE_ALL = 1, -+ HNDDMA_RANGE_TRANSMITTED, -+ HNDDMA_RANGE_TRANSFERED -+} txd_range_t; -+ -+/* dma parameters id */ -+enum dma_param_id { -+ HNDDMA_PID_TX_MULTI_OUTSTD_RD = 0, -+ HNDDMA_PID_TX_PREFETCH_CTL, -+ HNDDMA_PID_TX_PREFETCH_THRESH, -+ HNDDMA_PID_TX_BURSTLEN, -+ -+ HNDDMA_PID_RX_PREFETCH_CTL = 0x100, -+ HNDDMA_PID_RX_PREFETCH_THRESH, -+ HNDDMA_PID_RX_BURSTLEN -+}; -+ -+/* dma function type */ -+typedef void (*di_detach_t)(hnddma_t *dmah); -+typedef bool (*di_txreset_t)(hnddma_t *dmah); -+typedef bool (*di_rxreset_t)(hnddma_t *dmah); -+typedef bool (*di_rxidle_t)(hnddma_t *dmah); -+typedef void (*di_txinit_t)(hnddma_t *dmah); -+typedef bool (*di_txenabled_t)(hnddma_t *dmah); -+typedef void (*di_rxinit_t)(hnddma_t *dmah); -+typedef void (*di_txsuspend_t)(hnddma_t *dmah); -+typedef void (*di_txresume_t)(hnddma_t *dmah); -+typedef bool (*di_txsuspended_t)(hnddma_t *dmah); -+typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); -+#ifdef WL_MULTIQUEUE -+typedef void (*di_txflush_t)(hnddma_t *dmah); -+typedef void (*di_txflush_clear_t)(hnddma_t *dmah); -+#endif /* WL_MULTIQUEUE */ -+typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); -+typedef int (*di_txunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); -+typedef int (*di_rxunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); -+typedef void* (*di_getpos_t)(hnddma_t *di, bool direction); -+typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); -+typedef bool (*di_txstopped_t)(hnddma_t *dmah); -+typedef bool (*di_rxstopped_t)(hnddma_t *dmah); -+typedef bool (*di_rxenable_t)(hnddma_t *dmah); -+typedef bool (*di_rxenabled_t)(hnddma_t *dmah); -+typedef void* (*di_rx_t)(hnddma_t *dmah); -+typedef bool (*di_rxfill_t)(hnddma_t *dmah); -+typedef void (*di_txreclaim_t)(hnddma_t *dmah, txd_range_t range); -+typedef void (*di_rxreclaim_t)(hnddma_t *dmah); -+typedef uintptr (*di_getvar_t)(hnddma_t *dmah, const char *name); -+typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, txd_range_t range); -+typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); -+typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); -+typedef void* (*di_peekntxp_t)(hnddma_t *dmah, int *len, void *txps[], txd_range_t range); -+typedef void* (*di_peeknextrxp_t)(hnddma_t *dmah); -+typedef void (*di_rxparam_get_t)(hnddma_t *dmah, uint16 *rxoffset, uint16 *rxbufsize); -+typedef void (*di_txblock_t)(hnddma_t *dmah); -+typedef void (*di_txunblock_t)(hnddma_t *dmah); -+typedef uint (*di_txactive_t)(hnddma_t *dmah); -+typedef void (*di_txrotate_t)(hnddma_t *dmah); -+typedef void (*di_counterreset_t)(hnddma_t *dmah); -+typedef uint (*di_ctrlflags_t)(hnddma_t *dmah, uint mask, uint flags); -+typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); -+typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); -+typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); -+typedef uint (*di_rxactive_t)(hnddma_t *dmah); -+typedef uint (*di_txpending_t)(hnddma_t *dmah); -+typedef uint (*di_txcommitted_t)(hnddma_t *dmah); -+typedef int (*di_pktpool_set_t)(hnddma_t *dmah, pktpool_t *pool); -+typedef bool (*di_rxtxerror_t)(hnddma_t *dmah, bool istx); -+typedef void (*di_burstlen_set_t)(hnddma_t *dmah, uint8 rxburstlen, uint8 txburstlen); -+typedef uint (*di_avoidancecnt_t)(hnddma_t *dmah); -+typedef void (*di_param_set_t)(hnddma_t *dmah, uint16 paramid, uint16 paramval); -+typedef bool (*dma_glom_enable_t) (hnddma_t *dmah, uint32 val); -+typedef uint (*dma_active_rxbuf_t) (hnddma_t *dmah); -+/* dma opsvec */ -+typedef struct di_fcn_s { -+ di_detach_t detach; -+ di_txinit_t txinit; -+ di_txreset_t txreset; -+ di_txenabled_t txenabled; -+ di_txsuspend_t txsuspend; -+ di_txresume_t txresume; -+ di_txsuspended_t txsuspended; -+ di_txsuspendedidle_t txsuspendedidle; -+#ifdef WL_MULTIQUEUE -+ di_txflush_t txflush; -+ di_txflush_clear_t txflush_clear; -+#endif /* WL_MULTIQUEUE */ -+ di_txfast_t txfast; -+ di_txunframed_t txunframed; -+ di_getpos_t getpos; -+ di_txstopped_t txstopped; -+ di_txreclaim_t txreclaim; -+ di_getnexttxp_t getnexttxp; -+ di_peeknexttxp_t peeknexttxp; -+ di_peekntxp_t peekntxp; -+ di_txblock_t txblock; -+ di_txunblock_t txunblock; -+ di_txactive_t txactive; -+ di_txrotate_t txrotate; -+ -+ di_rxinit_t rxinit; -+ di_rxreset_t rxreset; -+ di_rxidle_t rxidle; -+ di_rxstopped_t rxstopped; -+ di_rxenable_t rxenable; -+ di_rxenabled_t rxenabled; -+ di_rx_t rx; -+ di_rxfill_t rxfill; -+ di_rxreclaim_t rxreclaim; -+ di_getnextrxp_t getnextrxp; -+ di_peeknextrxp_t peeknextrxp; -+ di_rxparam_get_t rxparam_get; -+ -+ di_fifoloopbackenable_t fifoloopbackenable; -+ di_getvar_t d_getvar; -+ di_counterreset_t counterreset; -+ di_ctrlflags_t ctrlflags; -+ di_dump_t dump; -+ di_dumptx_t dumptx; -+ di_dumprx_t dumprx; -+ di_rxactive_t rxactive; -+ di_txpending_t txpending; -+ di_txcommitted_t txcommitted; -+ di_pktpool_set_t pktpool_set; -+ di_rxtxerror_t rxtxerror; -+ di_burstlen_set_t burstlen_set; -+ di_avoidancecnt_t avoidancecnt; -+ di_param_set_t param_set; -+ dma_glom_enable_t glom_enab; -+ di_rxunframed_t rxunframed; -+ dma_active_rxbuf_t dma_activerxbuf; -+ uint endnum; -+} di_fcn_t; -+ -+/* -+ * Exported data structure (read-only) -+ */ -+/* export structure */ -+struct hnddma_pub { -+ const di_fcn_t *di_fn; /* DMA function pointers */ -+ uint txavail; /* # free tx descriptors */ -+ uint dmactrlflags; /* dma control flags */ -+ -+ /* rx error counters */ -+ uint rxgiants; /* rx giant frames */ -+ uint rxnobuf; /* rx out of dma descriptors */ -+ /* tx error counters */ -+ uint txnobuf; /* tx out of dma descriptors */ -+ uint txnodesc; /* tx out of dma descriptors running count */ -+}; -+ -+ -+extern hnddma_t * dma_attach(osl_t *osh, const char *name, si_t *sih, -+ volatile void *dmaregstx, volatile void *dmaregsrx, -+ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, -+ uint rxoffset, uint *msg_level); -+#ifdef BCMDMA32 -+ -+#define dma_detach(di) ((di)->di_fn->detach(di)) -+#define dma_txreset(di) ((di)->di_fn->txreset(di)) -+#define dma_rxreset(di) ((di)->di_fn->rxreset(di)) -+#define dma_rxidle(di) ((di)->di_fn->rxidle(di)) -+#define dma_txinit(di) ((di)->di_fn->txinit(di)) -+#define dma_txenabled(di) ((di)->di_fn->txenabled(di)) -+#define dma_rxinit(di) ((di)->di_fn->rxinit(di)) -+#define dma_txsuspend(di) ((di)->di_fn->txsuspend(di)) -+#define dma_txresume(di) ((di)->di_fn->txresume(di)) -+#define dma_txsuspended(di) ((di)->di_fn->txsuspended(di)) -+#define dma_txsuspendedidle(di) ((di)->di_fn->txsuspendedidle(di)) -+#ifdef WL_MULTIQUEUE -+#define dma_txflush(di) ((di)->di_fn->txflush(di)) -+#define dma_txflush_clear(di) ((di)->di_fn->txflush_clear(di)) -+#endif /* WL_MULTIQUEUE */ -+#define dma_txfast(di, p, commit) ((di)->di_fn->txfast(di, p, commit)) -+#define dma_fifoloopbackenable(di) ((di)->di_fn->fifoloopbackenable(di)) -+#define dma_txstopped(di) ((di)->di_fn->txstopped(di)) -+#define dma_rxstopped(di) ((di)->di_fn->rxstopped(di)) -+#define dma_rxenable(di) ((di)->di_fn->rxenable(di)) -+#define dma_rxenabled(di) ((di)->di_fn->rxenabled(di)) -+#define dma_rx(di) ((di)->di_fn->rx(di)) -+#define dma_rxfill(di) ((di)->di_fn->rxfill(di)) -+#define dma_txreclaim(di, range) ((di)->di_fn->txreclaim(di, range)) -+#define dma_rxreclaim(di) ((di)->di_fn->rxreclaim(di)) -+#define dma_getvar(di, name) ((di)->di_fn->d_getvar(di, name)) -+#define dma_getnexttxp(di, range) ((di)->di_fn->getnexttxp(di, range)) -+#define dma_getnextrxp(di, forceall) ((di)->di_fn->getnextrxp(di, forceall)) -+#define dma_peeknexttxp(di) ((di)->di_fn->peeknexttxp(di)) -+#define dma_peekntxp(di, l, t, r) ((di)->di_fn->peekntxp(di, l, t, r)) -+#define dma_peeknextrxp(di) ((di)->di_fn->peeknextrxp(di)) -+#define dma_rxparam_get(di, off, bufs) ((di)->di_fn->rxparam_get(di, off, bufs)) -+ -+#define dma_txblock(di) ((di)->di_fn->txblock(di)) -+#define dma_txunblock(di) ((di)->di_fn->txunblock(di)) -+#define dma_txactive(di) ((di)->di_fn->txactive(di)) -+#define dma_rxactive(di) ((di)->di_fn->rxactive(di)) -+#define dma_txrotate(di) ((di)->di_fn->txrotate(di)) -+#define dma_counterreset(di) ((di)->di_fn->counterreset(di)) -+#define dma_ctrlflags(di, mask, flags) ((di)->di_fn->ctrlflags((di), (mask), (flags))) -+#define dma_txpending(di) ((di)->di_fn->txpending(di)) -+#define dma_txcommitted(di) ((di)->di_fn->txcommitted(di)) -+#define dma_pktpool_set(di, pool) ((di)->di_fn->pktpool_set((di), (pool))) -+#if defined(BCMDBG) -+#define dma_dump(di, buf, dumpring) ((di)->di_fn->dump(di, buf, dumpring)) -+#define dma_dumptx(di, buf, dumpring) ((di)->di_fn->dumptx(di, buf, dumpring)) -+#define dma_dumprx(di, buf, dumpring) ((di)->di_fn->dumprx(di, buf, dumpring)) -+#endif -+#define dma_rxtxerror(di, istx) ((di)->di_fn->rxtxerror(di, istx)) -+#define dma_burstlen_set(di, rxlen, txlen) ((di)->di_fn->burstlen_set(di, rxlen, txlen)) -+#define dma_avoidance_cnt(di) ((di)->di_fn->avoidancecnt(di)) -+#define dma_param_set(di, paramid, paramval) ((di)->di_fn->param_set(di, paramid, paramval)) -+#define dma_activerxbuf(di) ((di)->di_fn->dma_activerxbuf(di)) -+ -+#else /* BCMDMA32 */ -+extern const di_fcn_t dma64proc; -+ -+#define dma_detach(di) (dma64proc.detach(di)) -+#define dma_txreset(di) (dma64proc.txreset(di)) -+#define dma_rxreset(di) (dma64proc.rxreset(di)) -+#define dma_rxidle(di) (dma64proc.rxidle(di)) -+#define dma_txinit(di) (dma64proc.txinit(di)) -+#define dma_txenabled(di) (dma64proc.txenabled(di)) -+#define dma_rxinit(di) (dma64proc.rxinit(di)) -+#define dma_txsuspend(di) (dma64proc.txsuspend(di)) -+#define dma_txresume(di) (dma64proc.txresume(di)) -+#define dma_txsuspended(di) (dma64proc.txsuspended(di)) -+#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di)) -+#ifdef WL_MULTIQUEUE -+#define dma_txflush(di) (dma64proc.txflush(di)) -+#define dma_txflush_clear(di) (dma64proc.txflush_clear(di)) -+#endif /* WL_MULTIQUEUE */ -+#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit)) -+#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit)) -+#define dma_getpos(di, dir) (dma64proc.getpos(di, dir)) -+#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di)) -+#define dma_txstopped(di) (dma64proc.txstopped(di)) -+#define dma_rxstopped(di) (dma64proc.rxstopped(di)) -+#define dma_rxenable(di) (dma64proc.rxenable(di)) -+#define dma_rxenabled(di) (dma64proc.rxenabled(di)) -+#define dma_rx(di) (dma64proc.rx(di)) -+#define dma_rxfill(di) (dma64proc.rxfill(di)) -+#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range)) -+#define dma_rxreclaim(di) (dma64proc.rxreclaim(di)) -+#define dma_getvar(di, name) (dma64proc.d_getvar(di, name)) -+#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range)) -+#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall)) -+#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di)) -+#define dma_peekntxp(di, l, t, r) (dma64proc.peekntxp(di, l, t, r)) -+#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di)) -+#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs)) -+ -+#define dma_txblock(di) (dma64proc.txblock(di)) -+#define dma_txunblock(di) (dma64proc.txunblock(di)) -+#define dma_txactive(di) (dma64proc.txactive(di)) -+#define dma_rxactive(di) (dma64proc.rxactive(di)) -+#define dma_txrotate(di) (dma64proc.txrotate(di)) -+#define dma_counterreset(di) (dma64proc.counterreset(di)) -+#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags))) -+#define dma_txpending(di) (dma64proc.txpending(di)) -+#define dma_txcommitted(di) (dma64proc.txcommitted(di)) -+#define dma_pktpool_set(di, pool) (dma64proc.pktpool_set((di), (pool))) -+#define dma_rxunframed(di, p, l, commit)(dma64proc.rxunframed(di, p, l, commit)) -+#if defined(BCMDBG) -+#define dma_dump(di, buf, dumpring) (dma64proc.dump(di, buf, dumpring)) -+#define dma_dumptx(di, buf, dumpring) (dma64proc.dumptx(di, buf, dumpring)) -+#define dma_dumprx(di, buf, dumpring) (dma64proc.dumprx(di, buf, dumpring)) -+#endif -+#define dma_rxtxerror(di, istx) (dma64proc.rxtxerror(di, istx)) -+#define dma_burstlen_set(di, rxlen, txlen) (dma64proc.burstlen_set(di, rxlen, txlen)) -+#define dma_avoidance_cnt(di) (dma64proc.avoidancecnt(di)) -+#define dma_param_set(di, paramid, paramval) (dma64proc.param_set(di, paramid, paramval)) -+ -+#define dma_glom_enable(di, val) (dma64proc.glom_enab(di, val)) -+#define dma_activerxbuf(di) (dma64proc.dma_activerxbuf(di)) -+ -+#endif /* BCMDMA32 */ -+ -+/* return addresswidth allowed -+ * This needs to be done after SB attach but before dma attach. -+ * SB attach provides ability to probe backplane and dma core capabilities -+ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach -+ */ -+extern uint dma_addrwidth(si_t *sih, void *dmaregs); -+ -+/* pio helpers */ -+extern void dma_txpioloopback(osl_t *osh, dma32regs_t *); -+ -+#endif /* _hnddma_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hndsoc.h b/drivers/net/ethernet/broadcom/gmac/src/include/hndsoc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hndsoc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hndsoc.h 2017-11-09 17:53:43.965312000 +0800 -@@ -0,0 +1,259 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom HND chip & on-chip-interconnect-related definitions. -+ * -+ * $Id: hndsoc.h 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#ifndef _HNDSOC_H -+#define _HNDSOC_H -+ -+/* Include the soci specific files */ -+#include -+#include -+ -+/* -+ * SOC Interconnect Address Map. -+ * All regions may not exist on all chips. -+ */ -+#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ -+#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ -+#define SI_PCI_MEM_SZ (64 * 1024 * 1024) -+#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ -+#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ -+#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ -+#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -+#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ -+#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ -+#define SI_MAXCORES 20 /* Max cores (this is arbitrary, for software -+ * convenience and could be changed if we -+ * make any larger chips -+ */ -+ -+#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ -+#define SI_FASTRAM_SWAPPED 0x19800000 -+ -+#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ -+#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ -+#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ -+#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ -+#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ -+ -+#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ -+#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ -+#define SI_NS_NORFLASH_SZ 0x02000000 /* Size of NorthStar NOR flash region */ -+#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ -+ -+#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ -+#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ -+#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ -+#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ -+#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ -+#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ -+ -+#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ -+#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ -+#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ -+#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 -+ * (2 ZettaBytes), low 32 bits -+ */ -+#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 -+ * (2 ZettaBytes), high 32 bits -+ */ -+#define SI_NS_CUR 0x1800B000 /* NorthStar CUR base */ -+ -+#define SI_NS_CHIPCB_SRAB 0x18036000 /* NorthStar+ Chip Common B SRAB base */ -+ -+/* core codes */ -+#define NODEV_CORE_ID 0x700 /* Invalid coreid */ -+#define CC_CORE_ID 0x800 /* chipcommon core */ -+#define ILINE20_CORE_ID 0x801 /* iline20 core */ -+#define SRAM_CORE_ID 0x802 /* sram core */ -+#define SDRAM_CORE_ID 0x803 /* sdram core */ -+#define PCI_CORE_ID 0x804 /* pci core */ -+#define MIPS_CORE_ID 0x805 /* mips core */ -+#define ENET_CORE_ID 0x806 /* enet mac core */ -+#define CODEC_CORE_ID 0x807 /* v90 codec core */ -+#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ -+#define ADSL_CORE_ID 0x809 /* ADSL core */ -+#define ILINE100_CORE_ID 0x80a /* iline100 core */ -+#define IPSEC_CORE_ID 0x80b /* ipsec core */ -+#define UTOPIA_CORE_ID 0x80c /* utopia core */ -+#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ -+#define SOCRAM_CORE_ID 0x80e /* internal memory core */ -+#define MEMC_CORE_ID 0x80f /* memc sdram core */ -+#define OFDM_CORE_ID 0x810 /* OFDM phy core */ -+#define EXTIF_CORE_ID 0x811 /* external interface core */ -+#define D11_CORE_ID 0x812 /* 802.11 MAC core */ -+#define APHY_CORE_ID 0x813 /* 802.11a phy core */ -+#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ -+#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ -+#define MIPS33_CORE_ID 0x816 /* mips3302 core */ -+#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ -+#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ -+#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ -+#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ -+#define SDIOH_CORE_ID 0x81b /* sdio host core */ -+#define ROBO_CORE_ID 0x81c /* roboswitch core */ -+#define ATA100_CORE_ID 0x81d /* parallel ATA core */ -+#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ -+#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ -+#define PCIE_CORE_ID 0x820 /* pci express core */ -+#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ -+#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ -+#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ -+#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ -+#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ -+#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ -+#define PMU_CORE_ID 0x827 /* PMU core */ -+#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ -+#define SDIOD_CORE_ID 0x829 /* SDIO device core */ -+#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ -+#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ -+#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ -+#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ -+#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ -+#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ -+#define SC_CORE_ID 0x831 /* shared common core */ -+#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ -+#define SPIH_CORE_ID 0x833 /* SPI host core */ -+#define I2S_CORE_ID 0x834 /* I2S core */ -+#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ -+#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ -+ -+#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */ -+#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */ -+#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ -+#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ -+#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ -+#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ -+#define EROM_CORE_ID 0x366 /* EROM core ID */ -+#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -+#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all -+ * unused address ranges -+ */ -+ -+#define CC_4706_CORE_ID 0x500 /* chipcommon core */ -+#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ -+#define NS_DMA_CORE_ID 0x502 /* DMA core */ -+#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ -+#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ -+#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ -+#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ -+#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ -+#define NS_ROM_CORE_ID 0x508 /* ROM core */ -+#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ -+#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ -+#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ -+#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ -+#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID -+#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ -+#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ -+#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ -+#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ -+#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ -+#define ALTA_CORE_ID 0x534 /* I2S core */ -+#define DDR23_PHY_CORE_ID 0x5dd -+ -+#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */ -+#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */ -+#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 -+ * (2 ZettaBytes), high 32 bits -+ */ -+#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ -+#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ -+#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ -+ -+/* There are TWO constants on all HND chips: SI_ENUM_BASE above, -+ * and chipcommon being the first core: -+ */ -+#define SI_CC_IDX 0 -+ -+/* SOC Interconnect types (aka chip types) */ -+#define SOCI_SB 0 -+#define SOCI_AI 1 -+#define SOCI_UBUS 2 -+#define SOCI_NS 3 -+ -+/* Common core control flags */ -+#define SICF_BIST_EN 0x8000 -+#define SICF_PME_EN 0x4000 -+#define SICF_CORE_BITS 0x3ffc -+#define SICF_FGC 0x0002 -+#define SICF_CLOCK_EN 0x0001 -+ -+/* Common core status flags */ -+#define SISF_BIST_DONE 0x8000 -+#define SISF_BIST_ERROR 0x4000 -+#define SISF_GATED_CLK 0x2000 -+#define SISF_DMA64 0x1000 -+#define SISF_CORE_BITS 0x0fff -+ -+/* Norstar core status flags */ -+#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ -+#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ -+#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ -+#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ -+#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ -+#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ -+ -+/* A register that is common to all cores to -+ * communicate w/PMU regarding clock control. -+ */ -+#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ -+ -+/* clk_ctl_st register */ -+#define CCS_FORCEALP 0x00000001 /* force ALP request */ -+#define CCS_FORCEHT 0x00000002 /* force HT request */ -+#define CCS_FORCEILP 0x00000004 /* force ILP request */ -+#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ -+#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ -+#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ -+#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */ -+#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ -+#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ -+#define CCS_ERSRC_REQ_SHIFT 8 -+#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ -+#define CCS_HTAVAIL 0x00020000 /* HT is available */ -+#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */ -+#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */ -+#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ -+#define CCS_ERSRC_STS_SHIFT 24 -+ -+#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ -+#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ -+ -+/* Not really related to SOC Interconnect, but a couple of software -+ * conventions for the use the flash space: -+ */ -+ -+/* Minumum amount of flash we support */ -+#define FLASH_MIN 0x00020000 /* Minimum flash size */ -+ -+/* A boot/binary may have an embedded block that describes its size */ -+#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ -+#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ -+#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ -+#define BISZ_TXTST_IDX 1 /* 1: text start */ -+#define BISZ_TXTEND_IDX 2 /* 2: text end */ -+#define BISZ_DATAST_IDX 3 /* 3: data start */ -+#define BISZ_DATAEND_IDX 4 /* 4: data end */ -+#define BISZ_BSSST_IDX 5 /* 5: bss start */ -+#define BISZ_BSSEND_IDX 6 /* 6: bss end */ -+#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ -+ -+#endif /* _HNDSOC_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/hndtcam.h b/drivers/net/ethernet/broadcom/gmac/src/include/hndtcam.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/hndtcam.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/hndtcam.h 2017-11-09 17:53:43.966304000 +0800 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * HND SOCRAM TCAM software interface. -+ * -+ * $Id: hndtcam.h 317281 2012-02-27 11:23:27Z $ -+ */ -+#ifndef _hndtcam_h_ -+#define _hndtcam_h_ -+ -+/* -+ * 0 - 1 -+ * 1 - 2 Consecutive locations are patched -+ * 2 - 4 Consecutive locations are patched -+ * 3 - 8 Consecutive locations are patched -+ * 4 - 16 Consecutive locations are patched -+ * Define default to patch 2 locations -+ */ -+ -+#ifdef PATCHCOUNT -+#define SRPC_PATCHCOUNT PATCHCOUNT -+#else -+#define PATCHCOUNT 0 -+#define SRPC_PATCHCOUNT PATCHCOUNT -+#endif -+ -+#if defined(__ARM_ARCH_7R__) -+#ifndef PATCHCOUNT -+#define PATCHCOUNT 1 -+#endif -+#define ARMCR4_TCAMPATCHCOUNT PATCHCOUNT -+#define ARMCR4_TCAMADDR_MASK (~((1 << (ARMCR4_TCAMPATCHCOUNT + 2))-1)) -+#define ARMCR4_PATCHNLOC (1 << ARMCR4_TCAMPATCHCOUNT) -+#endif /* defined(__ARM_ARCH_7R__) */ -+ -+/* N Consecutive location to patch */ -+#define SRPC_PATCHNLOC (1 << (SRPC_PATCHCOUNT)) -+ -+#define PATCHHDR(_p) __attribute__ ((__section__ (".patchhdr."#_p))) _p -+#define PATCHENTRY(_p) __attribute__ ((__section__ (".patchentry."#_p))) _p -+ -+#if defined(__ARM_ARCH_7R__) -+typedef struct { -+ uint32 data[ARMCR4_PATCHNLOC]; -+} patch_entry_t; -+#else -+typedef struct { -+ uint32 data[SRPC_PATCHNLOC]; -+} patch_entry_t; -+#endif -+ -+typedef struct { -+ void *addr; /* patch address */ -+ uint32 len; /* bytes to patch in entry */ -+ patch_entry_t *entry; /* patch entry data */ -+} patch_hdr_t; -+ -+/* patch values and address structure */ -+typedef struct patchaddrvalue { -+ uint32 addr; -+ uint32 value; -+} patchaddrvalue_t; -+ -+extern void *socram_regs; -+extern uint32 socram_rev; -+ -+extern void *arm_regs; -+ -+extern void hnd_patch_init(void *srp); -+extern void hnd_tcam_write(void *srp, uint16 idx, uint32 data); -+extern void hnd_tcam_read(void *srp, uint16 idx, uint32 *content); -+void * hnd_tcam_init(void *srp, int no_addrs); -+extern void hnd_tcam_disablepatch(void *srp); -+extern void hnd_tcam_enablepatch(void *srp); -+#ifdef CONFIG_XIP -+extern void hnd_tcam_bootloader_load(void *srp, char *pvars); -+#else -+extern void hnd_tcam_load(void *srp, const patchaddrvalue_t *patchtbl); -+#endif /* CONFIG_XIP */ -+extern void BCMATTACHFN(hnd_tcam_load_default)(void); -+extern void hnd_tcam_reclaim(void); -+ -+#endif /* _hndtcam_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/linux_osl.h b/drivers/net/ethernet/broadcom/gmac/src/include/linux_osl.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/linux_osl.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/linux_osl.h 2017-11-09 17:53:43.968293000 +0800 -@@ -0,0 +1,737 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Linux OS Independent Layer -+ * -+ * $Id: linux_osl.h 329351 2012-04-25 01:48:39Z $ -+ */ -+ -+#ifndef _linux_osl_h_ -+#define _linux_osl_h_ -+ -+#include -+ -+/* Linux Kernel: File Operations: start */ -+extern void * osl_os_open_image(char * filename); -+extern int osl_os_get_image_block(char * buf, int len, void * image); -+extern void osl_os_close_image(void * image); -+extern int osl_os_image_size(void *image); -+/* Linux Kernel: File Operations: end */ -+ -+#ifdef BCMDRIVER -+ -+/* OSL initialization */ -+extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); -+extern void osl_detach(osl_t *osh); -+ -+/* Global ASSERT type */ -+extern uint32 g_assert_type; -+ -+/* ASSERT */ -+ #ifdef __GNUC__ -+ #define GCC_VERSION \ -+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -+ #if GCC_VERSION > 30100 -+ #define ASSERT(exp) do {} while (0) -+ #else -+ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */ -+ #define ASSERT(exp) -+ #endif /* GCC_VERSION > 30100 */ -+ #endif /* __GNUC__ */ -+ -+/* microsecond delay */ -+#define OSL_DELAY(usec) osl_delay(usec) -+extern void osl_delay(uint usec); -+ -+#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ -+ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) -+#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ -+ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) -+extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); -+extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); -+ -+/* PCI configuration space access macros */ -+#define OSL_PCI_READ_CONFIG(osh, offset, size) \ -+ osl_pci_read_config((osh), (offset), (size)) -+#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ -+ osl_pci_write_config((osh), (offset), (size), (val)) -+extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); -+extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); -+ -+/* PCI device bus # and slot # */ -+#define OSL_PCI_BUS(osh) osl_pci_bus(osh) -+#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) -+extern uint osl_pci_bus(osl_t *osh); -+extern uint osl_pci_slot(osl_t *osh); -+extern struct pci_dev *osl_pci_device(osl_t *osh); -+ -+/* Pkttag flag should be part of public information */ -+typedef struct { -+ bool pkttag; -+ bool mmbus; /* Bus supports memory-mapped register accesses */ -+ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ -+ void *tx_ctx; /* Context to the callback function */ -+#ifdef OSLREGOPS -+ osl_rreg_fn_t rreg_fn; /* Read Register function */ -+ osl_wreg_fn_t wreg_fn; /* Write Register function */ -+ void *reg_ctx; /* Context to the reg callback functions */ -+#else -+ void *unused[3]; -+#endif -+} osl_pubinfo_t; -+ -+#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ -+ do { \ -+ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ -+ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ -+ } while (0) -+ -+#ifdef OSLREGOPS -+#define REGOPSSET(osh, rreg, wreg, ctx) \ -+ do { \ -+ ((osl_pubinfo_t*)osh)->rreg_fn = rreg; \ -+ ((osl_pubinfo_t*)osh)->wreg_fn = wreg; \ -+ ((osl_pubinfo_t*)osh)->reg_ctx = ctx; \ -+ } while (0) -+#endif /* OSLREGOPS */ -+ -+/* host/bus architecture-specific byte swap */ -+// #define BUS_SWAP32(v) (v) /* JIRA:LINUXDEV-16 */ -+#ifdef IL_BIGENDIAN -+#define BUS_SWAP32(v) bcmswap32(v) -+#else -+#define BUS_SWAP32(v) (v) -+#endif /* IL_BIGENDIAN */ -+ -+ #define MALLOC(osh, size) osl_malloc((osh), (size)) -+ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) -+ #define MALLOCED(osh) osl_malloced((osh)) -+ extern void *osl_malloc(osl_t *osh, uint size); -+ extern void osl_mfree(osl_t *osh, void *addr, uint size); -+ extern uint osl_malloced(osl_t *osh); -+ -+#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC) -+#define NATIVE_MFREE(osh, addr, size) kfree(addr) -+#ifdef USBAP -+#include -+#define VMALLOC(osh, size) vmalloc(size) -+#define VFREE(osh, addr, size) vfree(addr) -+#endif /* USBAP */ -+ -+#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) -+extern uint osl_malloc_failed(osl_t *osh); -+ -+/* allocate/free shared (dma-able) consistent memory */ -+#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() -+#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \ -+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap)) -+#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ -+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) -+extern uint osl_dma_consistent_align(void); -+extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap); -+extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); -+ -+/* map/unmap direction */ -+#define DMA_TX 1 /* TX direction for DMA */ -+#define DMA_RX 2 /* RX direction for DMA */ -+ -+/* map/unmap shared (dma-able) memory */ -+#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ -+ osl_dma_unmap((osh), (pa), (size), (direction)) -+extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah); -+extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); -+ -+/* API for DMA addressing capability */ -+#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) -+ -+#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op -+#define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op -+ -+#define OSL_ERROR(bcmerror) osl_error(bcmerror) -+extern int osl_error(int bcmerror); -+ -+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ -+#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ -+ -+/* -+ * BINOSL selects the slightly slower function-call-based binary compatible osl. -+ * Macros expand to calls to functions defined in linux_osl.c . -+ */ -+#ifndef BINOSL -+#include /* use current 2.4.x calling conventions */ -+#include /* for vsn/printf's */ -+#include /* for mem*, str* */ -+ -+#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) -+#define printf(fmt, args...) printk(fmt , ## args) -+#include /* for vsn/printf's */ -+#include /* for mem*, str* */ -+/* bcopy's: Linux kernel doesn't provide these (anymore) */ -+#define bcopy(src, dst, len) memcpy((dst), (src), (len)) -+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -+#define bzero(b, len) memset((b), '\0', (len)) -+ -+/* register access macros */ -+#if defined(OSLREGOPS) -+#define R_REG(osh, r) (\ -+ sizeof(*(r)) == sizeof(uint8) ? osl_readb((osh), (volatile uint8*)(r)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? osl_readw((osh), (volatile uint16*)(r)) : \ -+ osl_readl((osh), (volatile uint32*)(r)) \ -+) -+#define W_REG(osh, r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): osl_writeb((osh), (volatile uint8*)(r), (uint8)(v)); break; \ -+ case sizeof(uint16): osl_writew((osh), (volatile uint16*)(r), (uint16)(v)); break; \ -+ case sizeof(uint32): osl_writel((osh), (volatile uint32*)(r), (uint32)(v)); break; \ -+ } \ -+} while (0) -+ -+extern uint8 osl_readb(osl_t *osh, volatile uint8 *r); -+extern uint16 osl_readw(osl_t *osh, volatile uint16 *r); -+extern uint32 osl_readl(osl_t *osh, volatile uint32 *r); -+extern void osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v); -+extern void osl_writew(osl_t *osh, volatile uint16 *r, uint16 v); -+extern void osl_writel(osl_t *osh, volatile uint32 *r, uint32 v); -+#else /* OSLREGOPS */ -+ -+#ifndef IL_BIGENDIAN -+#ifndef __mips__ -+#define R_REG(osh, r) (\ -+ SELECT_BUS_READ(osh, \ -+ ({ \ -+ __typeof(*(r)) __osl_v; \ -+ BCM_REFERENCE(osh); \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): __osl_v = \ -+ readb((volatile uint8*)(r)); break; \ -+ case sizeof(uint16): __osl_v = \ -+ readw((volatile uint16*)(r)); break; \ -+ case sizeof(uint32): __osl_v = \ -+ readl((volatile uint32*)(r)); break; \ -+ } \ -+ __osl_v; \ -+ }), \ -+ OSL_READ_REG(osh, r)) \ -+) -+#else /* __mips__ */ -+#define R_REG(osh, r) (\ -+ SELECT_BUS_READ(osh, \ -+ ({ \ -+ __typeof(*(r)) __osl_v; \ -+ BCM_REFERENCE(osh); \ -+ __asm__ __volatile__("sync"); \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): __osl_v = \ -+ readb((volatile uint8*)(r)); break; \ -+ case sizeof(uint16): __osl_v = \ -+ readw((volatile uint16*)(r)); break; \ -+ case sizeof(uint32): __osl_v = \ -+ readl((volatile uint32*)(r)); break; \ -+ } \ -+ __asm__ __volatile__("sync"); \ -+ __osl_v; \ -+ }), \ -+ ({ \ -+ __typeof(*(r)) __osl_v; \ -+ __asm__ __volatile__("sync"); \ -+ __osl_v = OSL_READ_REG(osh, r); \ -+ __asm__ __volatile__("sync"); \ -+ __osl_v; \ -+ })) \ -+) -+#endif /* __mips__ */ -+ -+#define W_REG(osh, r, v) do { \ -+ BCM_REFERENCE(osh); \ -+ SELECT_BUS_WRITE(osh, \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ -+ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ -+ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ -+ }, \ -+ (OSL_WRITE_REG(osh, r, v))); \ -+ } while (0) -+#else /* IL_BIGENDIAN */ -+#define R_REG(osh, r) (\ -+ SELECT_BUS_READ(osh, \ -+ ({ \ -+ __typeof(*(r)) __osl_v; \ -+ BCM_REFERENCE(osh); \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): __osl_v = \ -+ readb((volatile uint8*)((uintptr)(r)^3)); break; \ -+ case sizeof(uint16): __osl_v = \ -+ readw((volatile uint16*)((uintptr)(r)^2)); break; \ -+ case sizeof(uint32): __osl_v = \ -+ readl((volatile uint32*)(r)); break; \ -+ } \ -+ __osl_v; \ -+ }), \ -+ OSL_READ_REG(osh, r)) \ -+) -+#define W_REG(osh, r, v) do { \ -+ BCM_REFERENCE(osh); \ -+ SELECT_BUS_WRITE(osh, \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): writeb((uint8)(v), \ -+ (volatile uint8*)((uintptr)(r)^3)); break; \ -+ case sizeof(uint16): writew((uint16)(v), \ -+ (volatile uint16*)((uintptr)(r)^2)); break; \ -+ case sizeof(uint32): writel((uint32)(v), \ -+ (volatile uint32*)(r)); break; \ -+ }, \ -+ (OSL_WRITE_REG(osh, r, v))); \ -+ } while (0) -+#endif /* IL_BIGENDIAN */ -+#endif /* OSLREGOPS */ -+ -+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) -+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) -+ -+/* bcopy, bcmp, and bzero functions */ -+#define bcopy(src, dst, len) memcpy((dst), (src), (len)) -+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -+#define bzero(b, len) memset((b), '\0', (len)) -+ -+/* uncached/cached virtual address */ -+#ifdef __mips__ -+#include -+#define OSL_UNCACHED(va) ((void *)KSEG1ADDR((va))) -+#define OSL_CACHED(va) ((void *)KSEG0ADDR((va))) -+#else -+#define OSL_UNCACHED(va) ((void *)va) -+#define OSL_CACHED(va) ((void *)va) -+ -+/* ARM NorthStar */ -+#define OSL_CACHE_FLUSH(va, len) -+ -+#endif /* mips */ -+ -+#ifdef __mips__ -+#define OSL_PREF_RANGE_LD(va, sz) prefetch_range_PREF_LOAD_RETAINED(va, sz) -+#define OSL_PREF_RANGE_ST(va, sz) prefetch_range_PREF_STORE_RETAINED(va, sz) -+#else /* __mips__ */ -+#define OSL_PREF_RANGE_LD(va, sz) -+#define OSL_PREF_RANGE_ST(va, sz) -+#endif /* __mips__ */ -+ -+/* get processor cycle count */ -+#if defined(mips) -+#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) -+#elif defined(__i386__) -+#define OSL_GETCYCLES(x) rdtscl((x)) -+#else -+#define OSL_GETCYCLES(x) ((x) = 0) -+#endif /* defined(mips) */ -+ -+/* dereference an address that may cause a bus exception */ -+#ifdef mips -+#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) -+#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into"\ -+ " a module") -+#else -+#define BUSPROBE(val, addr) get_dbe((val), (addr)) -+#include -+#endif /* defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) */ -+#else -+#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) -+#endif /* mips */ -+ -+/* map/unmap physical to virtual I/O */ -+#if !defined(CONFIG_MMC_MSM7X00A) -+#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) -+#else -+#define REG_MAP(pa, size) (void *)(0) -+#endif /* !defined(CONFIG_MMC_MSM7X00A */ -+#define REG_UNMAP(va) iounmap((va)) -+ -+/* shared (dma-able) memory access macros */ -+#define R_SM(r) *(r) -+#define W_SM(r, v) (*(r) = (v)) -+#define BZERO_SM(r, len) memset((r), '\0', (len)) -+ -+/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for -+ * performance reasons), we need the Linux headers. -+ */ -+#include /* use current 2.4.x calling conventions */ -+ -+/* packet primitives */ -+#define PKTGET(osh, len, send) osl_pktget((osh), (len)) -+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) -+#define PKTLIST_DUMP(osh, buf) -+#define PKTDBG_TRACE(osh, pkt, bit) -+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -+#ifdef DHD_USE_STATIC_BUF -+#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) -+#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) -+#endif /* DHD_USE_STATIC_BUF */ -+#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) -+#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) -+#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) -+#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) -+#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) -+#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) -+#define PKTSETLEN(osh, skb, len) __pskb_trim((struct sk_buff*)(skb), (len)) -+#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) -+#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) -+#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) -+#define PKTSETPOOL(osh, skb, x, y) do {} while (0) -+#define PKTPOOL(osh, skb) FALSE -+#define PKTSHRINK(osh, m) (m) -+ -+#define FASTBUF (1 << 16) -+#define CTFBUF (1 << 17) -+#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) -+#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) -+#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) -+#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) -+#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) -+#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) -+#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) -+ -+#define PKTSETSKIPCT(osh, skb) -+#define PKTCLRSKIPCT(osh, skb) -+#define PKTSKIPCT(osh, skb) -+#define PKTCLRCHAINED(osh, skb) -+#define PKTSETCHAINED(osh, skb) -+#define CTF_MARK(m) 0 -+ -+#ifdef BCMFA -+#ifdef BCMFA_HW_HASH -+#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) -+#else -+#define PKTSETFAHIDX(skb, idx) -+#endif /* BCMFA_SW_HASH */ -+#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) -+#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) -+#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) -+ -+#define AUX_TCP_FIN_RST (1 << 0) -+#define AUX_FREED (1 << 1) -+#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) -+#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) -+#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) -+#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) -+#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) -+#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) -+#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) -+#else -+#define PKTISFAAUX(skb) (FALSE) -+#define PKTISFABRIDGED(skb) (FALSE) -+#define PKTISFAFREED(skb) (FALSE) -+ -+#define PKTCLRFAAUX(skb) -+#define PKTSETFAFREED(skb) -+#define PKTCLRFAFREED(skb) -+#endif /* BCMFA */ -+ -+extern void osl_pktfree(osl_t *osh, void *skb, bool send); -+extern void *osl_pktget_static(osl_t *osh, uint len); -+extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); -+ -+extern void *osl_pkt_frmnative(osl_t *osh, void *skb); -+extern void *osl_pktget(osl_t *osh, uint len); -+extern void *osl_pktdup(osl_t *osh, void *skb); -+extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); -+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) -+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) -+ -+#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) -+#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) -+#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) -+#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) -+#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) -+#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ -+ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) -+/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ -+#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) -+ -+#ifdef CONFIG_NF_CONNTRACK_MARK -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -+#define PKTMARK(p) (((struct sk_buff *)(p))->mark) -+#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) -+#else /* !2.6.0 */ -+#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) -+#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) -+#endif /* 2.6.0 */ -+#else /* CONFIG_NF_CONNTRACK_MARK */ -+#define PKTMARK(p) 0 -+#define PKTSETMARK(p, m) -+#endif /* CONFIG_NF_CONNTRACK_MARK */ -+ -+#else /* BINOSL */ -+ -+/* Where to get the declarations for mem, str, printf, bcopy's? Two basic approaches. -+ * -+ * First, use the Linux header files and the C standard library replacmenent versions -+ * built-in to the kernel. Use this approach when compiling non hybrid code or compling -+ * the OS port files. The second approach is to use our own defines/prototypes and -+ * functions we have provided in the Linux OSL, i.e. linux_osl.c. Use this approach when -+ * compiling the files that make up the hybrid binary. We are ensuring we -+ * don't directly link to the kernel replacement routines from the hybrid binary. -+ * -+ * NOTE: The issue we are trying to avoid is any questioning of whether the -+ * hybrid binary is derived from Linux. The wireless common code (wlc) is designed -+ * to be OS independent through the use of the OSL API and thus the hybrid binary doesn't -+ * derive from the Linux kernel at all. But since we defined our OSL API to include -+ * a small collection of standard C library routines and these routines are provided in -+ * the kernel we want to avoid even the appearance of deriving at all even though clearly -+ * usage of a C standard library API doesn't represent a derivation from Linux. Lastly -+ * note at the time of this checkin 4 references to memcpy/memset could not be eliminated -+ * from the binary because they are created internally by GCC as part of things like -+ * structure assignment. I don't think the compiler should be doing this but there is -+ * no options to disable it on Intel architectures (there is for MIPS so somebody must -+ * agree with me). I may be able to even remove these references eventually with -+ * a GNU binutil such as objcopy via a symbol rename (i.e. memcpy to osl_memcpy). -+ */ -+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) -+ #define printf(fmt, args...) printk(fmt , ## args) -+ #include /* for vsn/printf's */ -+ #include /* for mem*, str* */ -+ /* bcopy's: Linux kernel doesn't provide these (anymore) */ -+ #define bcopy(src, dst, len) memcpy((dst), (src), (len)) -+ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -+ #define bzero(b, len) memset((b), '\0', (len)) -+ -+ /* These are provided only because when compiling linux_osl.c there -+ * must be an explicit prototype (separate from the definition) because -+ * we are compiling with GCC option -Wstrict-prototypes. Conversely -+ * these could be placed directly in linux_osl.c. -+ */ -+ extern int osl_printf(const char *format, ...); -+ extern int osl_sprintf(char *buf, const char *format, ...); -+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); -+ extern int osl_vsprintf(char *buf, const char *format, va_list ap); -+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); -+ extern int osl_strcmp(const char *s1, const char *s2); -+ extern int osl_strncmp(const char *s1, const char *s2, uint n); -+ extern int osl_strlen(const char *s); -+ extern char* osl_strcpy(char *d, const char *s); -+ extern char* osl_strncpy(char *d, const char *s, uint n); -+ extern char* osl_strchr(const char *s, int c); -+ extern char* osl_strrchr(const char *s, int c); -+ extern void *osl_memset(void *d, int c, size_t n); -+ extern void *osl_memcpy(void *d, const void *s, size_t n); -+ extern void *osl_memmove(void *d, const void *s, size_t n); -+ extern int osl_memcmp(const void *s1, const void *s2, size_t n); -+#else -+ -+ /* In the below defines we undefine the macro first in case it is -+ * defined. This shouldn't happen because we are not using Linux -+ * header files but because our Linux 2.4 make includes modversions.h -+ * through a GCC -include compile option, they get defined to point -+ * at the appropriate versioned symbol name. Note this doesn't -+ * happen with our Linux 2.6 makes. -+ */ -+ -+ /* *printf functions */ -+ #include /* va_list needed for v*printf */ -+ #include /* size_t needed for *nprintf */ -+ #undef printf -+ #undef sprintf -+ #undef snprintf -+ #undef vsprintf -+ #undef vsnprintf -+ #define printf(fmt, args...) osl_printf((fmt) , ## args) -+ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args) -+ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args) -+ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap)) -+ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap)) -+ extern int osl_printf(const char *format, ...); -+ extern int osl_sprintf(char *buf, const char *format, ...); -+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); -+ extern int osl_vsprintf(char *buf, const char *format, va_list ap); -+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); -+ -+ /* str* functions */ -+ #undef strcmp -+ #undef strncmp -+ #undef strlen -+ #undef strcpy -+ #undef strncpy -+ #undef strchr -+ #undef strrchr -+ #define strcmp(s1, s2) osl_strcmp((s1), (s2)) -+ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) -+ #define strlen(s) osl_strlen((s)) -+ #define strcpy(d, s) osl_strcpy((d), (s)) -+ #define strncpy(d, s, n) osl_strncpy((d), (s), (n)) -+ #define strchr(s, c) osl_strchr((s), (c)) -+ #define strrchr(s, c) osl_strrchr((s), (c)) -+ extern int osl_strcmp(const char *s1, const char *s2); -+ extern int osl_strncmp(const char *s1, const char *s2, uint n); -+ extern int osl_strlen(const char *s); -+ extern char* osl_strcpy(char *d, const char *s); -+ extern char* osl_strncpy(char *d, const char *s, uint n); -+ extern char* osl_strchr(const char *s, int c); -+ extern char* osl_strrchr(const char *s, int c); -+ -+ /* mem* functions */ -+ #undef memset -+ #undef memcpy -+ #undef memcmp -+ #define memset(d, c, n) osl_memset((d), (c), (n)) -+ #define memcpy(d, s, n) osl_memcpy((d), (s), (n)) -+ #define memmove(d, s, n) osl_memmove((d), (s), (n)) -+ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n)) -+ extern void *osl_memset(void *d, int c, size_t n); -+ extern void *osl_memcpy(void *d, const void *s, size_t n); -+ extern void *osl_memmove(void *d, const void *s, size_t n); -+ extern int osl_memcmp(const void *s1, const void *s2, size_t n); -+ -+ /* bcopy, bcmp, and bzero functions */ -+ #undef bcopy -+ #undef bcmp -+ #undef bzero -+ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len)) -+ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len)) -+ #define bzero(b, len) osl_memset((b), '\0', (len)) -+#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ -+ -+/* register access macros */ -+#define R_REG(osh, r) (\ -+ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ -+ osl_readl((volatile uint32*)(r)) \ -+) -+#define W_REG(osh, r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ -+ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ -+ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ -+ } \ -+} while (0) -+ -+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) -+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) -+extern uint8 osl_readb(volatile uint8 *r); -+extern uint16 osl_readw(volatile uint16 *r); -+extern uint32 osl_readl(volatile uint32 *r); -+extern void osl_writeb(uint8 v, volatile uint8 *r); -+extern void osl_writew(uint16 v, volatile uint16 *r); -+extern void osl_writel(uint32 v, volatile uint32 *r); -+ -+/* system up time in ms */ -+#define OSL_SYSUPTIME() osl_sysuptime() -+extern uint32 osl_sysuptime(void); -+ -+/* uncached/cached virtual address */ -+#define OSL_UNCACHED(va) osl_uncached((va)) -+extern void *osl_uncached(void *va); -+#define OSL_CACHED(va) osl_cached((va)) -+extern void *osl_cached(void *va); -+ -+#define OSL_PREF_RANGE_LD(va, sz) -+#define OSL_PREF_RANGE_ST(va, sz) -+ -+/* get processor cycle count */ -+#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) -+extern uint osl_getcycles(void); -+ -+/* dereference an address that may target abort */ -+#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) -+extern int osl_busprobe(uint32 *val, uint32 addr); -+ -+/* map/unmap physical to virtual */ -+#define REG_MAP(pa, size) osl_reg_map((pa), (size)) -+#define REG_UNMAP(va) osl_reg_unmap((va)) -+extern void *osl_reg_map(uint32 pa, uint size); -+extern void osl_reg_unmap(void *va); -+ -+/* shared (dma-able) memory access macros */ -+#define R_SM(r) *(r) -+#define W_SM(r, v) (*(r) = (v)) -+#define BZERO_SM(r, len) bzero((r), (len)) -+ -+/* packet primitives */ -+#define PKTGET(osh, len, send) osl_pktget((osh), (len)) -+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) -+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb)) -+#define PKTLIST_DUMP(osh, buf) -+#define PKTDBG_TRACE(osh, pkt, bit) -+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -+#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) -+#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) -+#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) -+#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) -+#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) -+#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x)) -+#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) -+#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) -+#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) -+#define PKTTAG(skb) osl_pkttag((skb)) -+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt)) -+#define PKTLINK(skb) osl_pktlink((skb)) -+#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) -+#define PKTPRIO(skb) osl_pktprio((skb)) -+#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) -+#define PKTSHARED(skb) osl_pktshared((skb)) -+#define PKTSETPOOL(osh, skb, x, y) do {} while (0) -+#define PKTPOOL(osh, skb) FALSE -+ -+extern void *osl_pktget(osl_t *osh, uint len); -+extern void *osl_pktdup(osl_t *osh, void *skb); -+extern void *osl_pkt_frmnative(osl_t *osh, void *skb); -+extern void osl_pktfree(osl_t *osh, void *skb, bool send); -+extern uchar *osl_pktdata(osl_t *osh, void *skb); -+extern uint osl_pktlen(osl_t *osh, void *skb); -+extern uint osl_pktheadroom(osl_t *osh, void *skb); -+extern uint osl_pkttailroom(osl_t *osh, void *skb); -+extern void *osl_pktnext(osl_t *osh, void *skb); -+extern void osl_pktsetnext(void *skb, void *x); -+extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); -+extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); -+extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); -+extern void *osl_pkttag(void *skb); -+extern void *osl_pktlink(void *skb); -+extern void osl_pktsetlink(void *skb, void *x); -+extern uint osl_pktprio(void *skb); -+extern void osl_pktsetprio(void *skb, uint x); -+extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); -+extern bool osl_pktshared(void *skb); -+ -+ -+#endif /* BINOSL */ -+ -+#define PKTALLOCED(osh) osl_pktalloced(osh) -+extern uint osl_pktalloced(osl_t *osh); -+ -+#define DMA_MAP(osh, va, size, direction, p, dmah) \ -+ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) -+ -+#else /* ! BCMDRIVER */ -+ -+ -+/* ASSERT */ -+ #define ASSERT(exp) do {} while (0) -+ -+/* MALLOC and MFREE */ -+#define MALLOC(o, l) malloc(l) -+#define MFREE(o, p, l) free(p) -+#include -+ -+/* str* and mem* functions */ -+#include -+ -+/* *printf functions */ -+#include -+ -+/* bcopy, bcmp, and bzero */ -+extern void bcopy(const void *src, void *dst, size_t len); -+extern int bcmp(const void *b1, const void *b2, size_t len); -+extern void bzero(void *b, size_t len); -+#endif /* ! BCMDRIVER */ -+ -+#endif /* _linux_osl_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/linuxver.h b/drivers/net/ethernet/broadcom/gmac/src/include/linuxver.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/linuxver.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/linuxver.h 2017-11-09 17:53:43.969290000 +0800 -@@ -0,0 +1,662 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Linux-specific abstractions to gain some independence from linux kernel versions. -+ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. -+ * -+ * $Id: linuxver.h 312774 2012-02-03 22:20:14Z $ -+ */ -+ -+#ifndef _linuxver_h_ -+#define _linuxver_h_ -+ -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -+#include -+#else -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) -+#include -+#else -+#include -+#endif -+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ -+#include -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) -+/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ -+#ifdef __UNDEF_NO_VERSION__ -+#undef __NO_VERSION__ -+#else -+#define __NO_VERSION__ -+#endif -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") -+#define module_param_string(_name_, _string_, _size_, _perm_) \ -+ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) -+#endif -+ -+/* linux/malloc.h is deprecated, use linux/slab.h instead. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) -+#include -+#else -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) -+#include -+#else -+#include -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) -+#undef IP_TOS -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */ -+#include -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) -+#include -+#else -+#include -+#ifndef work_struct -+#define work_struct tq_struct -+#endif -+#ifndef INIT_WORK -+#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) -+#endif -+#ifndef schedule_work -+#define schedule_work(_work) schedule_task((_work)) -+#endif -+#ifndef flush_scheduled_work -+#define flush_scheduled_work() flush_scheduled_tasks() -+#endif -+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func) -+#else -+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work) -+typedef void (*work_func_t)(void *work); -+#endif /* >= 2.6.20 */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -+/* Some distributions have their own 2.6.x compatibility layers */ -+#ifndef IRQ_NONE -+typedef void irqreturn_t; -+#define IRQ_NONE -+#define IRQ_HANDLED -+#define IRQ_RETVAL(x) -+#endif -+#else -+typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -+#define IRQF_SHARED SA_SHIRQ -+#endif /* < 2.6.18 */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) -+#ifdef CONFIG_NET_RADIO -+#define CONFIG_WIRELESS_EXT -+#endif -+#endif /* < 2.6.17 */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) -+#define MOD_INC_USE_COUNT -+#define MOD_DEC_USE_COUNT -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) -+#include -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) -+#include -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) -+#include -+#else -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) -+#include -+#endif -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ -+ -+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) -+#include -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) -+#include -+#include -+#endif -+#include -+#include -+#include -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)) -+/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which -+ * does this, but it's not in 2.4 so we do our own for now. -+ */ -+static inline void -+cs_error(client_handle_t handle, int func, int ret) -+{ -+ error_info_t err = { func, ret }; -+ CardServices(ReportError, handle, &err); -+} -+#endif -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16)) -+ -+typedef struct pcmcia_device dev_link_t; -+ -+#endif -+ -+#endif /* CONFIG_PCMCIA */ -+ -+#ifndef __exit -+#define __exit -+#endif -+#ifndef __devexit -+#define __devexit -+#endif -+#ifndef __devinit -+#define __devinit __init -+#endif -+#ifndef __devinitdata -+#define __devinitdata -+#endif -+#ifndef __devexit_p -+#define __devexit_p(x) x -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) -+ -+#define pci_get_drvdata(dev) (dev)->sysdata -+#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) -+ -+/* -+ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration -+ */ -+ -+struct pci_device_id { -+ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ -+ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ -+ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ -+ unsigned long driver_data; /* Data private to the driver */ -+}; -+ -+struct pci_driver { -+ struct list_head node; -+ char *name; -+ const struct pci_device_id *id_table; /* NULL if wants all devices */ -+ int (*probe)(struct pci_dev *dev, -+ const struct pci_device_id *id); /* New device inserted */ -+ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug -+ * capable driver) -+ */ -+ void (*suspend)(struct pci_dev *dev); /* Device suspended */ -+ void (*resume)(struct pci_dev *dev); /* Device woken up */ -+}; -+ -+#define MODULE_DEVICE_TABLE(type, name) -+#define PCI_ANY_ID (~0) -+ -+/* compatpci.c */ -+#define pci_module_init pci_register_driver -+extern int pci_register_driver(struct pci_driver *drv); -+extern void pci_unregister_driver(struct pci_driver *drv); -+ -+#endif /* PCI registration */ -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) -+#define pci_module_init pci_register_driver -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) -+#ifdef MODULE -+#define module_init(x) int init_module(void) { return x(); } -+#define module_exit(x) void cleanup_module(void) { x(); } -+#else -+#define module_init(x) __initcall(x); -+#define module_exit(x) __exitcall(x); -+#endif -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) -+#define WL_USE_NETDEV_OPS -+#else -+#undef WL_USE_NETDEV_OPS -+#endif -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) -+#define WL_CONFIG_RFKILL -+#else -+#undef WL_CONFIG_RFKILL -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) -+#define list_for_each(pos, head) \ -+ for (pos = (head)->next; pos != (head); pos = pos->next) -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) -+#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) -+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) -+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) -+#define pci_enable_device(dev) do { } while (0) -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) -+#define net_device device -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) -+ -+/* -+ * DMA mapping -+ * -+ * See linux/Documentation/DMA-mapping.txt -+ */ -+ -+#ifndef PCI_DMA_TODEVICE -+#define PCI_DMA_TODEVICE 1 -+#define PCI_DMA_FROMDEVICE 2 -+#endif -+ -+typedef u32 dma_addr_t; -+ -+/* Pure 2^n version of get_order */ -+static inline int get_order(unsigned long size) -+{ -+ int order; -+ -+ size = (size-1) >> (PAGE_SHIFT-1); -+ order = -1; -+ do { -+ size >>= 1; -+ order++; -+ } while (size); -+ return order; -+} -+ -+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, -+ dma_addr_t *dma_handle) -+{ -+ void *ret; -+ int gfp = GFP_ATOMIC | GFP_DMA; -+ -+ ret = (void *)__get_free_pages(gfp, get_order(size)); -+ -+ if (ret != NULL) { -+ memset(ret, 0, size); -+ *dma_handle = virt_to_bus(ret); -+ } -+ return ret; -+} -+static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, -+ void *vaddr, dma_addr_t dma_handle) -+{ -+ free_pages((unsigned long)vaddr, get_order(size)); -+} -+#ifdef ILSIM -+extern uint pci_map_single(void *dev, void *va, uint size, int direction); -+extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); -+#else -+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) -+#define pci_unmap_single(cookie, address, size, dir) -+#endif -+ -+#endif /* DMA mapping */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) -+ -+#define dev_kfree_skb_any(a) dev_kfree_skb(a) -+#define netif_down(dev) do { (dev)->start = 0; } while (0) -+ -+/* pcmcia-cs provides its own netdevice compatibility layer */ -+#ifndef _COMPAT_NETDEVICE_H -+ -+/* -+ * SoftNet -+ * -+ * For pre-softnet kernels we need to tell the upper layer not to -+ * re-enter start_xmit() while we are in there. However softnet -+ * guarantees not to enter while we are in there so there is no need -+ * to do the netif_stop_queue() dance unless the transmit queue really -+ * gets stuck. This should also improve performance according to tests -+ * done by Aman Singla. -+ */ -+ -+#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -+#define netif_wake_queue(dev) \ -+ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) -+#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) -+ -+static inline void netif_start_queue(struct net_device *dev) -+{ -+ dev->tbusy = 0; -+ dev->interrupt = 0; -+ dev->start = 1; -+} -+ -+#define netif_queue_stopped(dev) (dev)->tbusy -+#define netif_running(dev) (dev)->start -+ -+#endif /* _COMPAT_NETDEVICE_H */ -+ -+#define netif_device_attach(dev) netif_start_queue(dev) -+#define netif_device_detach(dev) netif_stop_queue(dev) -+ -+/* 2.4.x renamed bottom halves to tasklets */ -+#define tasklet_struct tq_struct -+static inline void tasklet_schedule(struct tasklet_struct *tasklet) -+{ -+ queue_task(tasklet, &tq_immediate); -+ mark_bh(IMMEDIATE_BH); -+} -+ -+static inline void tasklet_init(struct tasklet_struct *tasklet, -+ void (*func)(unsigned long), -+ unsigned long data) -+{ -+ tasklet->next = NULL; -+ tasklet->sync = 0; -+ tasklet->routine = (void (*)(void *))func; -+ tasklet->data = (void *)data; -+} -+#define tasklet_kill(tasklet) { do {} while (0); } -+ -+/* 2.4.x introduced del_timer_sync() */ -+#define del_timer_sync(timer) del_timer(timer) -+ -+#else -+ -+#define netif_down(dev) -+ -+#endif /* SoftNet */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) -+ -+/* -+ * Emit code to initialise a tq_struct's routine and data pointers -+ */ -+#define PREPARE_TQUEUE(_tq, _routine, _data) \ -+ do { \ -+ (_tq)->routine = _routine; \ -+ (_tq)->data = _data; \ -+ } while (0) -+ -+/* -+ * Emit code to initialise all of a tq_struct -+ */ -+#define INIT_TQUEUE(_tq, _routine, _data) \ -+ do { \ -+ INIT_LIST_HEAD(&(_tq)->list); \ -+ (_tq)->sync = 0; \ -+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ -+ } while (0) -+ -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ -+ -+/* Power management related macro & routines */ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9) -+#define PCI_SAVE_STATE(a, b) pci_save_state(a) -+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a) -+#else -+#define PCI_SAVE_STATE(a, b) pci_save_state(a, b) -+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) -+static inline int -+pci_save_state(struct pci_dev *dev, u32 *buffer) -+{ -+ int i; -+ if (buffer) { -+ for (i = 0; i < 16; i++) -+ pci_read_config_dword(dev, i * 4, &buffer[i]); -+ } -+ return 0; -+} -+ -+static inline int -+pci_restore_state(struct pci_dev *dev, u32 *buffer) -+{ -+ int i; -+ -+ if (buffer) { -+ for (i = 0; i < 16; i++) -+ pci_write_config_dword(dev, i * 4, buffer[i]); -+ } -+ /* -+ * otherwise, write the context information we know from bootup. -+ * This works around a problem where warm-booting from Windows -+ * combined with a D3(hot)->D0 transition causes PCI config -+ * header data to be forgotten. -+ */ -+ else { -+ for (i = 0; i < 6; i ++) -+ pci_write_config_dword(dev, -+ PCI_BASE_ADDRESS_0 + (i * 4), -+ pci_resource_start(dev, i)); -+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); -+ } -+ return 0; -+} -+#endif /* PCI power management */ -+ -+/* Old cp0 access macros deprecated in 2.4.19 */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) -+#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) -+#endif -+ -+/* Module refcount handled internally in 2.6.x */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) -+#ifndef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) do {} while (0) -+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -+#else -+#define OLD_MOD_INC_USE_COUNT do {} while (0) -+#define OLD_MOD_DEC_USE_COUNT do {} while (0) -+#endif -+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ -+#ifndef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) do {} while (0) -+#endif -+#ifndef MOD_INC_USE_COUNT -+#define MOD_INC_USE_COUNT do {} while (0) -+#endif -+#ifndef MOD_DEC_USE_COUNT -+#define MOD_DEC_USE_COUNT do {} while (0) -+#endif -+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ -+ -+#ifndef SET_NETDEV_DEV -+#define SET_NETDEV_DEV(net, pdev) do {} while (0) -+#endif -+ -+#ifndef HAVE_FREE_NETDEV -+#define free_netdev(dev) kfree(dev) -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -+/* struct packet_type redefined in 2.6.x */ -+#define af_packet_priv data -+#endif -+ -+/* suspend args */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) -+#define DRV_SUSPEND_STATE_TYPE pm_message_t -+#else -+#define DRV_SUSPEND_STATE_TYPE uint32 -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+#define CHECKSUM_HW CHECKSUM_PARTIAL -+#endif -+ -+typedef struct { -+ void *parent; /* some external entity that the thread supposed to work for */ -+ struct task_struct *p_task; -+ long thr_pid; -+ int prio; /* priority */ -+ struct semaphore sema; -+ int terminated; -+ struct completion completed; -+} tsk_ctl_t; -+ -+ -+/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ -+/* note this macro assumes there may be only one context waiting on thread's completion */ -+#ifdef DHD_DEBUG -+#define DBG_THR(x) printk x -+#else -+#define DBG_THR(x) -+#endif -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -+#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) -+#else -+#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) -+#endif -+ -+ -+#define PROC_START(thread_func, owner, tsk_ctl, flags) \ -+{ \ -+ sema_init(&((tsk_ctl)->sema), 0); \ -+ init_completion(&((tsk_ctl)->completed)); \ -+ (tsk_ctl)->parent = owner; \ -+ (tsk_ctl)->terminated = FALSE; \ -+ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ -+ if ((tsk_ctl)->thr_pid > 0) \ -+ wait_for_completion(&((tsk_ctl)->completed)); \ -+ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ -+} -+ -+#define PROC_STOP(tsk_ctl) \ -+{ \ -+ (tsk_ctl)->terminated = TRUE; \ -+ smp_wmb(); \ -+ up(&((tsk_ctl)->sema)); \ -+ wait_for_completion(&((tsk_ctl)->completed)); \ -+ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ -+ (tsk_ctl)->thr_pid = -1; \ -+} -+ -+/* ----------------------- */ -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) -+#define KILL_PROC(nr, sig) \ -+{ \ -+struct task_struct *tsk; \ -+struct pid *pid; \ -+pid = find_get_pid((pid_t)nr); \ -+tsk = pid_task(pid, PIDTYPE_PID); \ -+if (tsk) send_sig(sig, tsk, 1); \ -+} -+#else -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ -+ KERNEL_VERSION(2, 6, 30)) -+#define KILL_PROC(pid, sig) \ -+{ \ -+ struct task_struct *tsk; \ -+ tsk = find_task_by_vpid(pid); \ -+ if (tsk) send_sig(sig, tsk, 1); \ -+} -+#else -+#define KILL_PROC(pid, sig) \ -+{ \ -+ kill_proc(pid, sig, 1); \ -+} -+#endif -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -+#include -+#include -+#else -+#include -+ -+#define __wait_event_interruptible_timeout(wq, condition, ret) \ -+do { \ -+ wait_queue_t __wait; \ -+ init_waitqueue_entry(&__wait, current); \ -+ \ -+ add_wait_queue(&wq, &__wait); \ -+ for (;;) { \ -+ set_current_state(TASK_INTERRUPTIBLE); \ -+ if (condition) \ -+ break; \ -+ if (!signal_pending(current)) { \ -+ ret = schedule_timeout(ret); \ -+ if (!ret) \ -+ break; \ -+ continue; \ -+ } \ -+ ret = -ERESTARTSYS; \ -+ break; \ -+ } \ -+ current->state = TASK_RUNNING; \ -+ remove_wait_queue(&wq, &__wait); \ -+} while (0) -+ -+#define wait_event_interruptible_timeout(wq, condition, timeout) \ -+({ \ -+ long __ret = timeout; \ -+ if (!(condition)) \ -+ __wait_event_interruptible_timeout(wq, condition, __ret); \ -+ __ret; \ -+}) -+ -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ -+ -+/* -+For < 2.6.24, wl creates its own netdev but doesn't -+align the priv area like the genuine alloc_netdev(). -+Since netdev_priv() always gives us the aligned address, it will -+not match our unaligned address for < 2.6.24 -+*/ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) -+#define DEV_PRIV(dev) (dev->priv) -+#else -+#define DEV_PRIV(dev) netdev_priv(dev) -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -+#define WL_ISR(i, d, p) wl_isr((i), (d)) -+#else -+#define WL_ISR(i, d, p) wl_isr((i), (d), (p)) -+#endif /* < 2.6.20 */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -+#define netdev_priv(dev) dev->priv -+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ -+ -+#endif /* _linuxver_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/osl.h b/drivers/net/ethernet/broadcom/gmac/src/include/osl.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/osl.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/osl.h 2017-11-09 17:53:43.969308000 +0800 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * OS Abstraction Layer -+ * -+ * $Id: osl.h 321101 2012-03-14 02:53:01Z $ -+ */ -+ -+#ifndef _osl_h_ -+#define _osl_h_ -+ -+/* osl handle type forward declaration */ -+typedef struct osl_info osl_t; -+typedef struct osl_dmainfo osldma_t; -+ -+#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ -+ -+/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ -+typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); -+ -+/* Drivers use REGOPSSET() to register register read/write funcitons */ -+typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); -+typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); -+ -+#ifdef __mips__ -+#define PREF_LOAD 0 -+#define PREF_STORE 1 -+#define PREF_LOAD_STREAMED 4 -+#define PREF_STORE_STREAMED 5 -+#define PREF_LOAD_RETAINED 6 -+#define PREF_STORE_RETAINED 7 -+#define PREF_WBACK_INV 25 -+#define PREF_PREPARE4STORE 30 -+ -+ -+#define MAKE_PREFETCH_FN(hint) \ -+static inline void prefetch_##hint(const void *addr) \ -+{ \ -+ __asm__ __volatile__(\ -+ " .set mips4 \n" \ -+ " pref %0, (%1) \n" \ -+ " .set mips0 \n" \ -+ : \ -+ : "i" (hint), "r" (addr)); \ -+} -+ -+#define MAKE_PREFETCH_RANGE_FN(hint) \ -+static inline void prefetch_range_##hint(const void *addr, int len) \ -+{ \ -+ int size = len; \ -+ while (size > 0) { \ -+ prefetch_##hint(addr); \ -+ size -= 32; \ -+ } \ -+} -+ -+MAKE_PREFETCH_FN(PREF_LOAD) -+MAKE_PREFETCH_RANGE_FN(PREF_LOAD) -+MAKE_PREFETCH_FN(PREF_STORE) -+MAKE_PREFETCH_RANGE_FN(PREF_STORE) -+MAKE_PREFETCH_FN(PREF_LOAD_STREAMED) -+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED) -+MAKE_PREFETCH_FN(PREF_STORE_STREAMED) -+MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED) -+MAKE_PREFETCH_FN(PREF_LOAD_RETAINED) -+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED) -+MAKE_PREFETCH_FN(PREF_STORE_RETAINED) -+MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED) -+#endif /* __mips__ */ -+ -+#if defined(linux) -+#include -+#else -+#error "Unsupported OSL requested" -+#endif -+ -+#ifndef PKTDBG_TRACE -+#define PKTDBG_TRACE(osh, pkt, bit) -+#endif -+ -+#ifndef PKTCTFMAP -+#define PKTCTFMAP(osh, p) -+#endif /* PKTCTFMAP */ -+ -+/* -------------------------------------------------------------------------- -+** Register manipulation macros. -+*/ -+ -+#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) -+ -+#ifndef AND_REG -+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) -+#endif /* !AND_REG */ -+ -+#ifndef OR_REG -+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) -+#endif /* !OR_REG */ -+ -+#if !defined(OSL_SYSUPTIME) -+#define OSL_SYSUPTIME() (0) -+#define OSL_SYSUPTIME_SUPPORT FALSE -+#else -+#define OSL_SYSUPTIME_SUPPORT TRUE -+#endif /* OSL_SYSUPTIME */ -+ -+#define PKTCGETATTR(s) (0) -+#define PKTCSETATTR(skb, f, p, b) -+#define PKTCCLRATTR(skb) -+#define PKTCCNT(skb) (1) -+#define PKTCLEN(skb) PKTLEN(NULL, skb) -+#define PKTCGETFLAGS(skb) (0) -+#define PKTCSETFLAGS(skb, f) -+#define PKTCCLRFLAGS(skb) -+#define PKTCFLAGS(skb) (0) -+#define PKTCSETCNT(skb, c) -+#define PKTCINCRCNT(skb) -+#define PKTCADDCNT(skb, c) -+#define PKTCSETLEN(skb, l) -+#define PKTCADDLEN(skb, l) -+#define PKTCSETFLAG(skb, fb) -+#define PKTCCLRFLAG(skb, fb) -+#define PKTCLINK(skb) NULL -+#define PKTSETCLINK(skb, x) -+#undef PKTISCHAINED -+#define PKTISCHAINED(skb) FALSE -+#define FOREACH_CHAINED_PKT(skb, nskb) \ -+ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) -+#define PKTCFREE PKTFREE -+ -+ -+#endif /* _osl_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_end.h b/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_end.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_end.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_end.h 2017-11-09 17:53:43.970305000 +0800 -@@ -0,0 +1,71 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Declare directives for structure packing. No padding will be provided -+ * between the members of packed structures, and therefore, there is no -+ * guarantee that structure members will be aligned. -+ * -+ * Declaring packed structures is compiler specific. In order to handle all -+ * cases, packed structures should be delared as: -+ * -+ * #include -+ * -+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { -+ * some_struct_members; -+ * } BWL_POST_PACKED_STRUCT foobar_t; -+ * -+ * #include -+ * -+ * -+ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+ -+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h -+ * and undefined in packed_section_end.h. If it is NOT defined at this -+ * point, then there is a missing include of packed_section_start.h. -+ */ -+#ifdef BWL_PACKED_SECTION -+ #undef BWL_PACKED_SECTION -+#else -+ #error "BWL_PACKED_SECTION is NOT defined!" -+#endif -+ -+ -+#if defined(_MSC_VER) -+ /* Disable compiler warning about pragma pack changing alignment. */ -+ #pragma warning(disable:4103) -+ -+ /* The Microsoft compiler uses pragmas for structure packing. Other -+ * compilers use structure attribute modifiers. Refer to -+ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined in -+ * typedefs.h -+ */ -+ #if defined(BWL_DEFAULT_PACKING) -+ /* require default structure packing */ -+ #pragma pack(pop) -+ #undef BWL_DEFAULT_PACKING -+ #else /* BWL_PACKED_SECTION */ -+ #pragma pack() -+ #endif /* BWL_PACKED_SECTION */ -+#endif /* _MSC_VER */ -+ -+ -+/* Compiler-specific directives for structure packing are declared in -+ * packed_section_start.h. This marks the end of the structure packing section, -+ * so, undef them here. -+ */ -+#undef BWL_PRE_PACKED_STRUCT -+#undef BWL_POST_PACKED_STRUCT -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_start.h b/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_start.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_start.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/packed_section_start.h 2017-11-09 17:53:43.971302000 +0800 -@@ -0,0 +1,76 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Declare directives for structure packing. No padding will be provided -+ * between the members of packed structures, and therefore, there is no -+ * guarantee that structure members will be aligned. -+ * -+ * Declaring packed structures is compiler specific. In order to handle all -+ * cases, packed structures should be delared as: -+ * -+ * #include -+ * -+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { -+ * some_struct_members; -+ * } BWL_POST_PACKED_STRUCT foobar_t; -+ * -+ * #include -+ * -+ * -+ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $ -+ */ -+ -+ -+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h -+ * and undefined in packed_section_end.h. If it is already defined at this -+ * point, then there is a missing include of packed_section_end.h. -+ */ -+#ifdef BWL_PACKED_SECTION -+ #error "BWL_PACKED_SECTION is already defined!" -+#else -+ #define BWL_PACKED_SECTION -+#endif -+ -+ -+#if defined(_MSC_VER) -+ /* Disable compiler warning about pragma pack changing alignment. */ -+ #pragma warning(disable:4103) -+ -+ /* The Microsoft compiler uses pragmas for structure packing. Other -+ * compilers use structure attribute modifiers. Refer to -+ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined below. -+ */ -+ #if defined(BWL_DEFAULT_PACKING) -+ /* Default structure packing */ -+ #pragma pack(push, 8) -+ #else /* BWL_PACKED_SECTION */ -+ #pragma pack(1) -+ #endif /* BWL_PACKED_SECTION */ -+#endif /* _MSC_VER */ -+ -+ -+/* Declare compiler-specific directives for structure packing. */ -+#if defined(_MSC_VER) -+ #define BWL_PRE_PACKED_STRUCT -+ #define BWL_POST_PACKED_STRUCT -+#elif defined(__GNUC__) || defined(__lint) -+ #define BWL_PRE_PACKED_STRUCT -+ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed)) -+#elif defined(__CC_ARM) -+ #define BWL_PRE_PACKED_STRUCT __packed -+ #define BWL_POST_PACKED_STRUCT -+#else -+ #error "Unknown compiler!" -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/pcicfg.h b/drivers/net/ethernet/broadcom/gmac/src/include/pcicfg.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/pcicfg.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/pcicfg.h 2017-11-09 17:53:43.972306000 +0800 -@@ -0,0 +1,569 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * pcicfg.h: PCI configuration constants and structures. -+ * -+ * $Id: pcicfg.h 316716 2012-02-23 04:39:13Z $ -+ */ -+ -+#ifndef _h_pcicfg_ -+#define _h_pcicfg_ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* The following inside ifndef's so we don't collide with NTDDK.H */ -+#ifndef PCI_MAX_BUS -+#define PCI_MAX_BUS 0x100 -+#endif -+#ifndef PCI_MAX_DEVICES -+#define PCI_MAX_DEVICES 0x20 -+#endif -+#ifndef PCI_MAX_FUNCTION -+#define PCI_MAX_FUNCTION 0x8 -+#endif -+ -+#ifndef PCI_INVALID_VENDORID -+#define PCI_INVALID_VENDORID 0xffff -+#endif -+#ifndef PCI_INVALID_DEVICEID -+#define PCI_INVALID_DEVICEID 0xffff -+#endif -+ -+ -+/* Convert between bus-slot-function-register and config addresses */ -+ -+#define PCICFG_BUS_SHIFT 16 /* Bus shift */ -+#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ -+#define PCICFG_FUN_SHIFT 8 /* Function shift */ -+#define PCICFG_OFF_SHIFT 0 /* Register shift */ -+ -+#define PCICFG_BUS_MASK 0xff /* Bus mask */ -+#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ -+#define PCICFG_FUN_MASK 7 /* Function mask */ -+#define PCICFG_OFF_MASK 0xff /* Bus mask */ -+ -+#define PCI_CONFIG_ADDR(b, s, f, o) \ -+ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ -+ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ -+ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ -+ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) -+ -+#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) -+#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) -+#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) -+#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) -+ -+/* PCIE Config space accessing MACROS */ -+ -+#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ -+#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ -+#define PCIECFG_FUN_SHIFT 16 /* Function shift */ -+#define PCIECFG_OFF_SHIFT 0 /* Register shift */ -+ -+#define PCIECFG_BUS_MASK 0xff /* Bus mask */ -+#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ -+#define PCIECFG_FUN_MASK 7 /* Function mask */ -+#define PCIECFG_OFF_MASK 0xfff /* Register mask */ -+ -+#define PCIE_CONFIG_ADDR(b, s, f, o) \ -+ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ -+ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ -+ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ -+ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) -+ -+#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) -+#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) -+#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) -+#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) -+ -+/* The actual config space */ -+ -+#define PCI_BAR_MAX 6 -+ -+#define PCI_ROM_BAR 8 -+ -+#define PCR_RSVDA_MAX 2 -+ -+/* Bits in PCI bars' flags */ -+ -+#define PCIBAR_FLAGS 0xf -+#define PCIBAR_IO 0x1 -+#define PCIBAR_MEM1M 0x2 -+#define PCIBAR_MEM64 0x4 -+#define PCIBAR_PREFETCH 0x8 -+#define PCIBAR_MEM32_MASK 0xFFFFFF80 -+ -+/* pci config status reg has a bit to indicate that capability ptr is present */ -+ -+#define PCI_CAPPTR_PRESENT 0x0010 -+ -+typedef struct _pci_config_regs { -+ uint16 vendor; -+ uint16 device; -+ uint16 command; -+ uint16 status; -+ uint8 rev_id; -+ uint8 prog_if; -+ uint8 sub_class; -+ uint8 base_class; -+ uint8 cache_line_size; -+ uint8 latency_timer; -+ uint8 header_type; -+ uint8 bist; -+ uint32 base[PCI_BAR_MAX]; -+ uint32 cardbus_cis; -+ uint16 subsys_vendor; -+ uint16 subsys_id; -+ uint32 baserom; -+ uint32 rsvd_a[PCR_RSVDA_MAX]; -+ uint8 int_line; -+ uint8 int_pin; -+ uint8 min_gnt; -+ uint8 max_lat; -+ uint8 dev_dep[192]; -+} pci_config_regs; -+ -+#define SZPCR (sizeof (pci_config_regs)) -+#define MINSZPCR 64 /* offsetof (dev_dep[0] */ -+ -+#endif /* !LINUX_POSTMOGRIFY_REMOVAL */ -+/* A structure for the config registers is nice, but in most -+ * systems the config space is not memory mapped, so we need -+ * field offsetts. :-( -+ */ -+#define PCI_CFG_VID 0 -+#define PCI_CFG_DID 2 -+#define PCI_CFG_CMD 4 -+#define PCI_CFG_STAT 6 -+#define PCI_CFG_REV 8 -+#define PCI_CFG_PROGIF 9 -+#define PCI_CFG_SUBCL 0xa -+#define PCI_CFG_BASECL 0xb -+#define PCI_CFG_CLSZ 0xc -+#define PCI_CFG_LATTIM 0xd -+#define PCI_CFG_HDR 0xe -+#define PCI_CFG_BIST 0xf -+#define PCI_CFG_BAR0 0x10 -+#define PCI_CFG_BAR1 0x14 -+#define PCI_CFG_BAR2 0x18 -+#define PCI_CFG_BAR3 0x1c -+#define PCI_CFG_BAR4 0x20 -+#define PCI_CFG_BAR5 0x24 -+#define PCI_CFG_CIS 0x28 -+#define PCI_CFG_SVID 0x2c -+#define PCI_CFG_SSID 0x2e -+#define PCI_CFG_ROMBAR 0x30 -+#define PCI_CFG_CAPPTR 0x34 -+#define PCI_CFG_INT 0x3c -+#define PCI_CFG_PIN 0x3d -+#define PCI_CFG_MINGNT 0x3e -+#define PCI_CFG_MAXLAT 0x3f -+#define PCI_CFG_DEVCTRL 0xd8 -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+ -+#ifdef __NetBSD__ -+#undef PCI_CLASS_DISPLAY -+#undef PCI_CLASS_MEMORY -+#undef PCI_CLASS_BRIDGE -+#undef PCI_CLASS_INPUT -+#undef PCI_CLASS_DOCK -+#endif /* __NetBSD__ */ -+ -+#ifdef EFI -+#undef PCI_CLASS_BRIDGE -+#undef PCI_CLASS_OLD -+#undef PCI_CLASS_DISPLAY -+#undef PCI_CLASS_SERIAL -+#undef PCI_CLASS_SATELLITE -+#endif /* EFI */ -+ -+/* Classes and subclasses */ -+ -+typedef enum { -+ PCI_CLASS_OLD = 0, -+ PCI_CLASS_DASDI, -+ PCI_CLASS_NET, -+ PCI_CLASS_DISPLAY, -+ PCI_CLASS_MMEDIA, -+ PCI_CLASS_MEMORY, -+ PCI_CLASS_BRIDGE, -+ PCI_CLASS_COMM, -+ PCI_CLASS_BASE, -+ PCI_CLASS_INPUT, -+ PCI_CLASS_DOCK, -+ PCI_CLASS_CPU, -+ PCI_CLASS_SERIAL, -+ PCI_CLASS_INTELLIGENT = 0xe, -+ PCI_CLASS_SATELLITE, -+ PCI_CLASS_CRYPT, -+ PCI_CLASS_DSP, -+ PCI_CLASS_XOR = 0xfe -+} pci_classes; -+ -+typedef enum { -+ PCI_DASDI_SCSI, -+ PCI_DASDI_IDE, -+ PCI_DASDI_FLOPPY, -+ PCI_DASDI_IPI, -+ PCI_DASDI_RAID, -+ PCI_DASDI_OTHER = 0x80 -+} pci_dasdi_subclasses; -+ -+typedef enum { -+ PCI_NET_ETHER, -+ PCI_NET_TOKEN, -+ PCI_NET_FDDI, -+ PCI_NET_ATM, -+ PCI_NET_OTHER = 0x80 -+} pci_net_subclasses; -+ -+typedef enum { -+ PCI_DISPLAY_VGA, -+ PCI_DISPLAY_XGA, -+ PCI_DISPLAY_3D, -+ PCI_DISPLAY_OTHER = 0x80 -+} pci_display_subclasses; -+ -+typedef enum { -+ PCI_MMEDIA_VIDEO, -+ PCI_MMEDIA_AUDIO, -+ PCI_MMEDIA_PHONE, -+ PCI_MEDIA_OTHER = 0x80 -+} pci_mmedia_subclasses; -+ -+typedef enum { -+ PCI_MEMORY_RAM, -+ PCI_MEMORY_FLASH, -+ PCI_MEMORY_OTHER = 0x80 -+} pci_memory_subclasses; -+ -+typedef enum { -+ PCI_BRIDGE_HOST, -+ PCI_BRIDGE_ISA, -+ PCI_BRIDGE_EISA, -+ PCI_BRIDGE_MC, -+ PCI_BRIDGE_PCI, -+ PCI_BRIDGE_PCMCIA, -+ PCI_BRIDGE_NUBUS, -+ PCI_BRIDGE_CARDBUS, -+ PCI_BRIDGE_RACEWAY, -+ PCI_BRIDGE_OTHER = 0x80 -+} pci_bridge_subclasses; -+ -+typedef enum { -+ PCI_COMM_UART, -+ PCI_COMM_PARALLEL, -+ PCI_COMM_MULTIUART, -+ PCI_COMM_MODEM, -+ PCI_COMM_OTHER = 0x80 -+} pci_comm_subclasses; -+ -+typedef enum { -+ PCI_BASE_PIC, -+ PCI_BASE_DMA, -+ PCI_BASE_TIMER, -+ PCI_BASE_RTC, -+ PCI_BASE_PCI_HOTPLUG, -+ PCI_BASE_OTHER = 0x80 -+} pci_base_subclasses; -+ -+typedef enum { -+ PCI_INPUT_KBD, -+ PCI_INPUT_PEN, -+ PCI_INPUT_MOUSE, -+ PCI_INPUT_SCANNER, -+ PCI_INPUT_GAMEPORT, -+ PCI_INPUT_OTHER = 0x80 -+} pci_input_subclasses; -+ -+typedef enum { -+ PCI_DOCK_GENERIC, -+ PCI_DOCK_OTHER = 0x80 -+} pci_dock_subclasses; -+ -+typedef enum { -+ PCI_CPU_386, -+ PCI_CPU_486, -+ PCI_CPU_PENTIUM, -+ PCI_CPU_ALPHA = 0x10, -+ PCI_CPU_POWERPC = 0x20, -+ PCI_CPU_MIPS = 0x30, -+ PCI_CPU_COPROC = 0x40, -+ PCI_CPU_OTHER = 0x80 -+} pci_cpu_subclasses; -+ -+typedef enum { -+ PCI_SERIAL_IEEE1394, -+ PCI_SERIAL_ACCESS, -+ PCI_SERIAL_SSA, -+ PCI_SERIAL_USB, -+ PCI_SERIAL_FIBER, -+ PCI_SERIAL_SMBUS, -+ PCI_SERIAL_OTHER = 0x80 -+} pci_serial_subclasses; -+ -+typedef enum { -+ PCI_INTELLIGENT_I2O -+} pci_intelligent_subclasses; -+ -+typedef enum { -+ PCI_SATELLITE_TV, -+ PCI_SATELLITE_AUDIO, -+ PCI_SATELLITE_VOICE, -+ PCI_SATELLITE_DATA, -+ PCI_SATELLITE_OTHER = 0x80 -+} pci_satellite_subclasses; -+ -+typedef enum { -+ PCI_CRYPT_NETWORK, -+ PCI_CRYPT_ENTERTAINMENT, -+ PCI_CRYPT_OTHER = 0x80 -+} pci_crypt_subclasses; -+ -+typedef enum { -+ PCI_DSP_DPIO, -+ PCI_DSP_OTHER = 0x80 -+} pci_dsp_subclasses; -+ -+typedef enum { -+ PCI_XOR_QDMA, -+ PCI_XOR_OTHER = 0x80 -+} pci_xor_subclasses; -+ -+/* Header types */ -+#define PCI_HEADER_MULTI 0x80 -+#define PCI_HEADER_MASK 0x7f -+typedef enum { -+ PCI_HEADER_NORMAL, -+ PCI_HEADER_BRIDGE, -+ PCI_HEADER_CARDBUS -+} pci_header_types; -+ -+ -+/* Overlay for a PCI-to-PCI bridge */ -+ -+#define PPB_RSVDA_MAX 2 -+#define PPB_RSVDD_MAX 8 -+ -+typedef struct _ppb_config_regs { -+ uint16 vendor; -+ uint16 device; -+ uint16 command; -+ uint16 status; -+ uint8 rev_id; -+ uint8 prog_if; -+ uint8 sub_class; -+ uint8 base_class; -+ uint8 cache_line_size; -+ uint8 latency_timer; -+ uint8 header_type; -+ uint8 bist; -+ uint32 rsvd_a[PPB_RSVDA_MAX]; -+ uint8 prim_bus; -+ uint8 sec_bus; -+ uint8 sub_bus; -+ uint8 sec_lat; -+ uint8 io_base; -+ uint8 io_lim; -+ uint16 sec_status; -+ uint16 mem_base; -+ uint16 mem_lim; -+ uint16 pf_mem_base; -+ uint16 pf_mem_lim; -+ uint32 pf_mem_base_hi; -+ uint32 pf_mem_lim_hi; -+ uint16 io_base_hi; -+ uint16 io_lim_hi; -+ uint16 subsys_vendor; -+ uint16 subsys_id; -+ uint32 rsvd_b; -+ uint8 rsvd_c; -+ uint8 int_pin; -+ uint16 bridge_ctrl; -+ uint8 chip_ctrl; -+ uint8 diag_ctrl; -+ uint16 arb_ctrl; -+ uint32 rsvd_d[PPB_RSVDD_MAX]; -+ uint8 dev_dep[192]; -+} ppb_config_regs; -+ -+ -+/* PCI CAPABILITY DEFINES */ -+#define PCI_CAP_POWERMGMTCAP_ID 0x01 -+#define PCI_CAP_MSICAP_ID 0x05 -+#define PCI_CAP_VENDSPEC_ID 0x09 -+#define PCI_CAP_PCIECAP_ID 0x10 -+ -+/* Data structure to define the Message Signalled Interrupt facility -+ * Valid for PCI and PCIE configurations -+ */ -+typedef struct _pciconfig_cap_msi { -+ uint8 capID; -+ uint8 nextptr; -+ uint16 msgctrl; -+ uint32 msgaddr; -+} pciconfig_cap_msi; -+ -+/* Data structure to define the Power managment facility -+ * Valid for PCI and PCIE configurations -+ */ -+typedef struct _pciconfig_cap_pwrmgmt { -+ uint8 capID; -+ uint8 nextptr; -+ uint16 pme_cap; -+ uint16 pme_sts_ctrl; -+ uint8 pme_bridge_ext; -+ uint8 data; -+} pciconfig_cap_pwrmgmt; -+ -+#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */ -+#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */ -+#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */ -+#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */ -+ -+/* Data structure to define the PCIE capability */ -+typedef struct _pciconfig_cap_pcie { -+ uint8 capID; -+ uint8 nextptr; -+ uint16 pcie_cap; -+ uint32 dev_cap; -+ uint16 dev_ctrl; -+ uint16 dev_status; -+ uint32 link_cap; -+ uint16 link_ctrl; -+ uint16 link_status; -+ uint32 slot_cap; -+ uint16 slot_ctrl; -+ uint16 slot_status; -+ uint16 root_ctrl; -+ uint16 root_cap; -+ uint32 root_status; -+} pciconfig_cap_pcie; -+ -+/* PCIE Enhanced CAPABILITY DEFINES */ -+#define PCIE_EXTCFG_OFFSET 0x100 -+#define PCIE_ADVERRREP_CAPID 0x0001 -+#define PCIE_VC_CAPID 0x0002 -+#define PCIE_DEVSNUM_CAPID 0x0003 -+#define PCIE_PWRBUDGET_CAPID 0x0004 -+ -+/* PCIE Extended configuration */ -+#define PCIE_ADV_CORR_ERR_MASK 0x114 -+#define CORR_ERR_RE (1 << 0) /* Receiver */ -+#define CORR_ERR_BT (1 << 6) /* Bad TLP */ -+#define CORR_ERR_BD (1 << 7) /* Bad DLLP */ -+#define CORR_ERR_RR (1 << 8) /* REPLAY_NUM rollover */ -+#define CORR_ERR_RT (1 << 12) /* Reply timer timeout */ -+#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \ -+ CORR_ERR_RR | CORR_ERR_RT) -+ -+/* PCIE Root Control Register bits (Host mode only) */ -+#define PCIE_RC_CORR_SERR_EN 0x0001 -+#define PCIE_RC_NONFATAL_SERR_EN 0x0002 -+#define PCIE_RC_FATAL_SERR_EN 0x0004 -+#define PCIE_RC_PME_INT_EN 0x0008 -+#define PCIE_RC_CRS_EN 0x0010 -+ -+/* PCIE Root Capability Register bits (Host mode only) */ -+#define PCIE_RC_CRS_VISIBILITY 0x0001 -+ -+/* Header to define the PCIE specific capabilities in the extended config space */ -+typedef struct _pcie_enhanced_caphdr { -+ uint16 capID; -+ uint16 cap_ver : 4; -+ uint16 next_ptr : 12; -+} pcie_enhanced_caphdr; -+ -+ -+/* Everything below is BRCM HND proprietary */ -+ -+ -+/* Brcm PCI configuration registers */ -+#define cap_list rsvd_a[0] -+#define bar0_window dev_dep[0x80 - 0x40] -+#define bar1_window dev_dep[0x84 - 0x40] -+#define sprom_control dev_dep[0x88 - 0x40] -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ -+#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ -+#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ -+#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ -+#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ -+#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ -+#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ -+#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */ -+#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */ -+#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ -+#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ -+#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ -+#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ -+#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ -+ -+#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ -+#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ -+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ -+#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the -+ * 8KB window, so their address is the "regular" -+ * address plus 4K -+ */ -+/* -+ * PCIE GEN2 changed some of the above locations for -+ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase -+ * BAR0 maps 32K of register space -+*/ -+#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ -+#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ -+#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ -+ -+#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ -+/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ -+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ -+#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ -+#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* On AI chips we have a second window to map DMP regs are mapped: */ -+#define PCI_16KB0_WIN2_OFFSET (4 * 1024) /* bar0 + 4K is "Window 2" */ -+ -+/* PCI_INT_STATUS */ -+#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ -+ -+/* PCI_INT_MASK */ -+#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ -+#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ -+#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* PCI_SPROM_CONTROL */ -+#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ -+#define SPROM_LOCKED 0x08 /* SPROM Locked */ -+#define SPROM_BLANK 0x04 /* indicating a blank SPROM */ -+#define SPROM_WRITEEN 0x10 /* SPROM write enable */ -+#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ -+#define SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ -+#define SPROM_OTPIN_USE 0x80 /* device OTP In use */ -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+/* Bits in PCI command and status regs */ -+#define PCI_CMD_IO 0x00000001 /* I/O enable */ -+#define PCI_CMD_MEMORY 0x00000002 /* Memory enable */ -+#define PCI_CMD_MASTER 0x00000004 /* Master enable */ -+#define PCI_CMD_SPECIAL 0x00000008 /* Special cycles enable */ -+#define PCI_CMD_INVALIDATE 0x00000010 /* Invalidate? */ -+#define PCI_CMD_VGA_PAL 0x00000040 /* VGA Palate */ -+#define PCI_STAT_TA 0x08000000 /* target abort status */ -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+#define PCI_CONFIG_SPACE_SIZE 256 -+#endif /* _h_pcicfg_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/phy542xx.h b/drivers/net/ethernet/broadcom/gmac/src/include/phy542xx.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/phy542xx.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/phy542xx.h 2017-11-09 17:53:43.973296000 +0800 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+#ifndef _PHY542XX_H_ -+#define _PHY542XX_H_ -+ -+#include -+ -+/* Broadcom BCM542xx */ -+#define phy542xx_rd_reg phy542xx_reg_read -+#define phy542xx_wr_reg phy542xx_reg_write -+ -+#define BCM542XX_REG_EXP_SEL 0x17 -+#define BCM542XX_REG_EXP_SELECT_7E 0x0F7E -+#define BCM542XX_REG_EXP_DATA 0x15 -+#define BCM542XX_REG_EXP_RDB_EN 0x0000 -+ -+#define BCM542XX_REG_RDB_ADDR 0x1e -+#define BCM542XX_REG_RDB_DATA 0x1f -+ -+#define MIIM_BCM542xx_RDB_AUXSTATUS 0x09 -+#define MIIM_BCM542xx_AUXSTATUS_LINKMODE_MASK 0x0700 -+#define MIIM_BCM542xx_AUXSTATUS_LINKMODE_SHIFT 8 -+ -+#define BCM542XX_REG_RDB_MII_MISC_CTRL 0x02f -+ -+#define BCM542XX_REG_RDB_EXT_SERDES_CTRL 0x234 -+#define BCM542XX_REG_EXT_SERDES_AUTO_FX (1 << 6) -+#define BCM542XX_REG_EXT_SERDES_FX_FD (1 << 5) -+#define BCM542XX_REG_EXT_SERDES_FX (1 << 4) -+#define BCM542XX_REG_EXT_SERDES_LED (1 << 3) -+#define BCM542XX_REG_EXT_SEL_SYNC_ST (1 << 2) -+#define BCM542XX_REG_EXT_SELECT_SD (1 << 1) -+#define BCM542XX_REG_EXT_SERDES_SEL (1 << 0) -+#define BCM542XX_REG_EXT_SERDES_FX_MASK (BCM542XX_REG_EXT_SERDES_FX | \ -+ BCM542XX_REG_EXT_SERDES_AUTO_FX) -+ -+#define BCM542XX_REG_RDB_SGMII_SLAVE 0x235 -+#define BCM542XX_REG_SGMII_SLAVE_AUTO (1 << 0) -+ -+#define MIIM_BCM542xx_RDB_AUTO_DETECT_MEDIUM 0x23e -+#define BCM542XX_REG_MII_AUTO_DET_MED_2ND_SERDES (1 << 9) -+#define BCM542XX_REG_MII_INV_FIBER_SD (1 << 8) -+#define BCM542XX_REG_MII_FIBER_IN_USE_LED (1 << 7) -+#define BCM542XX_REG_MII_FIBER_LED (1 << 6) -+#define BCM542XX_REG_MII_FIBER_SD_SYNC (1 << 5) -+#define BCM542XX_REG_MII_FIBER_AUTO_PWRDN (1 << 4) -+#define BCM542XX_REG_MII_SD_en_ov (1 << 3) -+#define BCM542XX_REG_MII_AUTO_DET_MED_DEFAULT (1 << 2) -+#define BCM542XX_REG_MII_AUTO_DET_MED_PRI (1 << 1) -+#define BCM542XX_REG_MII_AUTO_DET_MED_EN (1 << 0) -+#define BCM542XX_REG_MII_AUTO_DET_MASK 0x033f -+ -+#define BCM542XX_REG_RDB_MODE_CTRL 0x021 -+#define BCM542XX_REG_MODE_CTRL_COPPER_LINK (1 << 7) -+#define BCM542XX_REG_MODE_CTRL_SERDES_LINK (1 << 6) -+#define BCM542XX_REG_MODE_CTRL_COPPER_ENERGY_DET (1 << 5) -+#define BCM542XX_REG_MODE_CNTL_MODE_SEL_2 (1 << 2) -+#define BCM542XX_REG_MODE_CNTL_MODE_SEL_1 (1 << 1) -+#define BCM542XX_REG_MODE_CTRL_1000X_EN (1 << 0) -+ -+#define BCM542XX_REG_RDB_COPPER_MISC_CTRL 0x02f -+#define BCM542XX_REG_MISC_CTRL_FORCE_AUTO_MDIX (1 << 9) -+ -+#define BCM542XX_REG_MODE_SEL_COPPER_2_SGMII (0x0) -+#define BCM542XX_REG_MODE_SEL_FIBER_2_SGMII (BCM542XX_REG_MODE_CNTL_MODE_SEL_1) -+#define BCM542XX_REG_MODE_SEL_SGMII_2_COPPER (BCM542XX_REG_MODE_CNTL_MODE_SEL_2) -+#define BCM542XX_REG_MODE_SEL_GBIC (BCM542XX_REG_MODE_CNTL_MODE_SEL_1 | \ -+ BCM542XX_REG_MODE_CNTL_MODE_SEL_2) -+ -+#define BCM542XX_REG_RDB_2ND_SERDES_BASE 0xb00 -+#define BCM542XX_REG_RDB_2ND_SERDES_MISC_1000X 0xb17 -+ -+ -+extern int phy542xx_reg_read(u32 phy_addr, u32 flags, int reg_addr, u16 *data); -+extern int phy542xx_reg_write(u32 phy_addr, u32 flags, int reg_addr, u16 data); -+extern int phy542xx_reset_setup(u32 phy_addr); -+extern int phy542xx_init(u32 phy_addr); -+extern int phy542xx_enable_set(u32 phy_addr, int enable); -+extern int phy542xx_force_auto_mdix(u32 phy_addr, int enable); -+ -+#endif /* _PHY542XX_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.11.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.11.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.11.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.11.h 2017-11-09 17:53:43.976303000 +0800 -@@ -0,0 +1,2356 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Fundamental types and constants relating to 802.11 -+ * -+ * $Id: 802.11.h 308961 2012-01-18 03:01:00Z $ -+ */ -+ -+#ifndef _802_11_H_ -+#define _802_11_H_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+#ifndef _NET_ETHERNET_H_ -+#include -+#endif -+ -+#include -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+ -+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ -+ -+/* Generic 802.11 frame constants */ -+#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ -+#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ -+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ -+#define DOT11_FCS_LEN 4 /* d11 FCS length */ -+#define DOT11_ICV_LEN 4 /* d11 ICV length */ -+#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ -+#define DOT11_QOS_LEN 2 /* d11 QoS length */ -+#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ -+ -+#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ -+#define DOT11_IV_LEN 4 /* d11 IV length */ -+#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ -+#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ -+#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ -+#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ -+ -+/* Includes MIC */ -+#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ -+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ -+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ -+ DOT11_QOS_LEN + \ -+ DOT11_IV_AES_CCM_LEN + \ -+ DOT11_MAX_MPDU_BODY_LEN + \ -+ DOT11_ICV_LEN + \ -+ DOT11_FCS_LEN) /* d11 max MPDU length */ -+ -+#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ -+ -+/* dot11RTSThreshold */ -+#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ -+#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ -+ -+/* dot11FragmentationThreshold */ -+#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ -+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength -+ * of the attached PHY -+ */ -+#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ -+ -+/* dot11BeaconPeriod */ -+#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ -+#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ -+ -+/* dot11DTIMPeriod */ -+#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ -+#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ -+ -+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ -+#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ -+#define DOT11_OUI_LEN 3 /* d11 OUI length */ -+BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { -+ uint8 dsap; /* always 0xAA */ -+ uint8 ssap; /* always 0xAA */ -+ uint8 ctl; /* always 0x03 */ -+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 -+ * Bridge-Tunnel: 0x00 0x00 0xF8 -+ */ -+ uint16 type; /* ethertype */ -+} BWL_POST_PACKED_STRUCT; -+ -+/* RFC1042 header used by 802.11 per 802.1H */ -+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ -+ -+/* Generic 802.11 MAC header */ -+/* -+ * N.B.: This struct reflects the full 4 address 802.11 MAC header. -+ * The fields are defined such that the shorter 1, 2, and 3 -+ * address headers just use the first k fields. -+ */ -+BWL_PRE_PACKED_STRUCT struct dot11_header { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr a1; /* address 1 */ -+ struct ether_addr a2; /* address 2 */ -+ struct ether_addr a3; /* address 3 */ -+ uint16 seq; /* sequence control */ -+ struct ether_addr a4; /* address 4 */ -+} BWL_POST_PACKED_STRUCT; -+ -+/* Control frames */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr ra; /* receiver address */ -+ struct ether_addr ta; /* transmitter address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr ra; /* receiver address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr ra; /* receiver address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* AID */ -+ struct ether_addr bssid; /* receiver address, STA in AP */ -+ struct ether_addr ta; /* transmitter address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr ra; /* receiver address */ -+ struct ether_addr bssid; /* transmitter address, STA in AP */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ -+ -+/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling -+* category+OUI+vendor specific content ( this can be variable) -+*/ -+BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { -+ uint8 category; -+ uint8 OUI[3]; -+ uint8 type; -+ uint8 subtype; -+ uint8 data[1040]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; -+ -+/* generic vender specific action frame with variable length */ -+BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { -+ uint8 category; -+ uint8 OUI[3]; -+ uint8 type; -+ uint8 subtype; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; -+#define DOT11_ACTION_VS_HDR_LEN 6 -+ -+#define BCM_ACTION_OUI_BYTE0 0x00 -+#define BCM_ACTION_OUI_BYTE1 0x90 -+#define BCM_ACTION_OUI_BYTE2 0x4c -+ -+/* BA/BAR Control parameters */ -+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ -+#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ -+#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ -+ -+#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ -+#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ -+ -+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ -+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ -+ -+#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ -+#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ -+ -+/* control frame header (BA/BAR) */ -+BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr ra; /* receiver address */ -+ struct ether_addr ta; /* transmitter address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ -+ -+/* BAR frame payload */ -+BWL_PRE_PACKED_STRUCT struct dot11_bar { -+ uint16 bar_control; /* BAR Control */ -+ uint16 seqnum; /* Starting Sequence control */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_BAR_LEN 4 /* BAR frame payload length */ -+ -+#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ -+#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ -+/* BA frame payload */ -+BWL_PRE_PACKED_STRUCT struct dot11_ba { -+ uint16 ba_control; /* BA Control */ -+ uint16 seqnum; /* Starting Sequence control */ -+ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ -+ -+/* Management frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_management_header { -+ uint16 fc; /* frame control */ -+ uint16 durid; /* duration/ID */ -+ struct ether_addr da; /* receiver address */ -+ struct ether_addr sa; /* transmitter address */ -+ struct ether_addr bssid; /* BSS ID */ -+ uint16 seq; /* sequence control */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ -+ -+/* Management frame payloads */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { -+ uint32 timestamp[2]; -+ uint16 beacon_interval; -+ uint16 capability; -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ -+#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_auth { -+ uint16 alg; /* algorithm */ -+ uint16 seq; /* sequence control */ -+ uint16 status; /* status code */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { -+ uint16 capability; /* capability information */ -+ uint16 listen; /* listen interval */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { -+ uint16 capability; /* capability information */ -+ uint16 listen; /* listen interval */ -+ struct ether_addr ap; /* Current AP address */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { -+ uint16 capability; /* capability information */ -+ uint16 status; /* status code */ -+ uint16 aid; /* association ID */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_measure { -+ uint8 category; -+ uint8 action; -+ uint8 token; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { -+ uint8 category; -+ uint8 action; -+ uint8 ch_width; -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { -+ uint8 category; -+ uint8 action; -+ uint8 control; -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { -+ uint8 category; -+ uint8 action; -+ uint16 id; -+} BWL_POST_PACKED_STRUCT; -+ -+#define SM_PWRSAVE_ENABLE 1 -+#define SM_PWRSAVE_MODE 2 -+ -+/* ************* 802.11h related definitions. ************* */ -+BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { -+ uint8 id; -+ uint8 len; -+ uint8 power; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_power_cnst dot11_power_cnst_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_power_cap { -+ uint8 min; -+ uint8 max; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_power_cap dot11_power_cap_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { -+ uint8 id; -+ uint8 len; -+ uint8 tx_pwr; -+ uint8 margin; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_tpc_rep dot11_tpc_rep_t; -+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { -+ uint8 id; -+ uint8 len; -+ uint8 first_channel; -+ uint8 num_channels; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_supp_channels dot11_supp_channels_t; -+ -+/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband -+ * offset for 40MHz operation. The possible 3 values are: -+ * 1 = above control channel -+ * 3 = below control channel -+ * 0 = no extension channel -+ */ -+BWL_PRE_PACKED_STRUCT struct dot11_extch { -+ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ -+ uint8 len; /* IE length */ -+ uint8 extch; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_extch dot11_extch_ie_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { -+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ -+ uint8 len; /* IE length */ -+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ -+ uint8 type; /* type inidicates what follows */ -+ uint8 extch; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; -+ -+#define BRCM_EXTCH_IE_LEN 5 -+#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ -+#define DOT11_EXTCH_IE_LEN 1 -+#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ -+#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ -+#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ -+#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { -+ uint8 category; -+ uint8 action; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_ACTION_FRMHDR_LEN 2 -+ -+/* CSA IE data structure */ -+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { -+ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ -+ uint8 len; /* length of IE */ -+ uint8 mode; /* mode 0 or 1 */ -+ uint8 channel; /* channel switch to */ -+ uint8 count; /* number of beacons before switching */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_channel_switch dot11_chan_switch_ie_t; -+ -+#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ -+/* CSA mode - 802.11h-2003 $7.3.2.20 */ -+#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ -+#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { -+ uint8 category; -+ uint8 action; -+ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ -+ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_csa_body { -+ uint8 mode; /* mode 0 or 1 */ -+ uint8 reg; /* regulatory class */ -+ uint8 channel; /* channel switch to */ -+ uint8 count; /* number of beacons before switching */ -+} BWL_POST_PACKED_STRUCT; -+ -+/* 11n Extended Channel Switch IE data structure */ -+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { -+ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ -+ uint8 len; /* length of IE */ -+ struct dot11_csa_body b; /* body of the ie */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_ext_csa dot11_ext_csa_ie_t; -+#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { -+ uint8 category; -+ uint8 action; -+ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { -+ uint8 category; -+ uint8 action; -+ struct dot11_csa_body b; /* body of the ie */ -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { -+ uint8 id; -+ uint8 len; -+ uint8 info; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_obss_coex dot11_obss_coex_t; -+#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ -+ -+#define DOT11_OBSS_COEX_INFO_REQ 0x01 -+#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 -+#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { -+ uint8 id; -+ uint8 len; -+ uint8 regclass; -+ uint8 chanlist[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; -+#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { -+ uint8 id; -+ uint8 len; -+ uint8 cap[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_extcap_ie dot11_extcap_ie_t; -+ -+#define DOT11_EXTCAP_LEN_MAX 7 -+#define DOT11_EXTCAP_LEN_COEX 1 -+#define DOT11_EXTCAP_LEN_BT 3 -+#define DOT11_EXTCAP_LEN_IW 4 -+#define DOT11_EXTCAP_LEN_SI 6 -+ -+#define DOT11_EXTCAP_LEN_TDLS 5 -+BWL_PRE_PACKED_STRUCT struct dot11_extcap { -+ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_extcap dot11_extcap_t; -+ -+/* TDLS Capabilities */ -+#define TDLS_CAP_TDLS 37 /* TDLS support */ -+#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ -+#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ -+#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ -+#define TDLS_CAP_PROH 38 /* TDLS prohibited */ -+#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ -+ -+#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ -+ -+/* 802.11h/802.11k Measurement Request/Report IEs */ -+/* Measurement Type field */ -+#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ -+#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ -+#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ -+#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ -+#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ -+#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ -+#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ -+#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ -+#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ -+#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ -+#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ -+ -+/* Measurement Request Modes */ -+#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ -+#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ -+#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ -+#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ -+#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ -+/* Measurement Report Modes */ -+#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ -+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ -+#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ -+/* Basic Measurement Map bits */ -+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ -+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ -+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ -+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ -+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_meas_req { -+ uint8 id; -+ uint8 len; -+ uint8 token; -+ uint8 mode; -+ uint8 type; -+ uint8 channel; -+ uint8 start_time[8]; -+ uint16 duration; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_meas_req dot11_meas_req_t; -+#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ -+/* length of Measure Request IE data not including variable len */ -+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { -+ uint8 id; -+ uint8 len; -+ uint8 token; -+ uint8 mode; -+ uint8 type; -+ BWL_PRE_PACKED_STRUCT union -+ { -+ BWL_PRE_PACKED_STRUCT struct { -+ uint8 channel; -+ uint8 start_time[8]; -+ uint16 duration; -+ uint8 map; -+ } BWL_POST_PACKED_STRUCT basic; -+ uint8 data[1]; -+ } BWL_POST_PACKED_STRUCT rep; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_meas_rep dot11_meas_rep_t; -+ -+/* length of Measure Report IE data not including variable len */ -+#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { -+ uint8 channel; -+ uint8 start_time[8]; -+ uint16 duration; -+ uint8 map; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; -+#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_quiet { -+ uint8 id; -+ uint8 len; -+ uint8 count; /* TBTTs until beacon interval in quiet starts */ -+ uint8 period; /* Beacon intervals between periodic quiet periods ? */ -+ uint16 duration; /* Length of quiet period, in TU's */ -+ uint16 offset; /* TU's offset from TBTT in Count field */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_quiet dot11_quiet_t; -+ -+BWL_PRE_PACKED_STRUCT struct chan_map_tuple { -+ uint8 channel; -+ uint8 map; -+} BWL_POST_PACKED_STRUCT; -+typedef struct chan_map_tuple chan_map_tuple_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { -+ uint8 id; -+ uint8 len; -+ uint8 eaddr[ETHER_ADDR_LEN]; -+ uint8 interval; -+ chan_map_tuple_t map[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; -+ -+/* WME Elements */ -+#define WME_OUI "\x00\x50\xf2" /* WME OUI */ -+#define WME_OUI_LEN 3 -+#define WME_OUI_TYPE 2 /* WME type */ -+#define WME_TYPE 2 /* WME type, deprecated */ -+#define WME_SUBTYPE_IE 0 /* Information Element */ -+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ -+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ -+#define WME_VER 1 /* WME version */ -+ -+/* WME Access Category Indices (ACIs) */ -+#define AC_BE 0 /* Best Effort */ -+#define AC_BK 1 /* Background */ -+#define AC_VI 2 /* Video */ -+#define AC_VO 3 /* Voice */ -+#define AC_COUNT 4 /* number of ACs */ -+ -+typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ -+ -+#define AC_BITMAP_NONE 0x0 /* No ACs */ -+#define AC_BITMAP_ALL 0xf /* All ACs */ -+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) -+#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) -+#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) -+ -+/* WME Information Element (IE) */ -+BWL_PRE_PACKED_STRUCT struct wme_ie { -+ uint8 oui[3]; -+ uint8 type; -+ uint8 subtype; -+ uint8 version; -+ uint8 qosinfo; -+} BWL_POST_PACKED_STRUCT; -+typedef struct wme_ie wme_ie_t; -+#define WME_IE_LEN 7 /* WME IE length */ -+ -+BWL_PRE_PACKED_STRUCT struct edcf_acparam { -+ uint8 ACI; -+ uint8 ECW; -+ uint16 TXOP; /* stored in network order (ls octet first) */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct edcf_acparam edcf_acparam_t; -+ -+/* WME Parameter Element (PE) */ -+BWL_PRE_PACKED_STRUCT struct wme_param_ie { -+ uint8 oui[3]; -+ uint8 type; -+ uint8 subtype; -+ uint8 version; -+ uint8 qosinfo; -+ uint8 rsvd; -+ edcf_acparam_t acparam[AC_COUNT]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct wme_param_ie wme_param_ie_t; -+#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ -+ -+/* QoS Info field for IE as sent from AP */ -+#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ -+#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ -+#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ -+#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ -+ -+/* QoS Info field for IE as sent from STA */ -+#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ -+#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ -+#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ -+#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ -+#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ -+#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ -+#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ -+#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ -+#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ -+#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ -+#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ -+#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ -+ -+/* ACI */ -+#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ -+#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ -+#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ -+#define EDCF_ACM_MASK 0x10 /* ACM mask */ -+#define EDCF_ACI_MASK 0x60 /* ACI mask */ -+#define EDCF_ACI_SHIFT 5 /* ACI shift */ -+#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ -+ -+/* ECW */ -+#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ -+#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ -+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) -+#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ -+#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ -+#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ -+ -+/* TXOP */ -+#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ -+#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ -+#define EDCF_TXOP2USEC(txop) ((txop) << 5) -+ -+/* Default BE ACI value for non-WME connection STA */ -+#define NON_EDCF_AC_BE_ACI_STA 0x02 -+ -+/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ -+#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ -+#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ -+#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ -+#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ -+#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ -+#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ -+#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ -+#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ -+#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ -+#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ -+#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ -+#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ -+ -+/* Default EDCF parameters that AP uses; WMM draft Table 14 */ -+#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ -+#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ -+#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ -+#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ -+#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ -+#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ -+#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ -+#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ -+#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ -+#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ -+#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ -+#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ -+ -+/* EDCA Parameter IE */ -+BWL_PRE_PACKED_STRUCT struct edca_param_ie { -+ uint8 qosinfo; -+ uint8 rsvd; -+ edcf_acparam_t acparam[AC_COUNT]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct edca_param_ie edca_param_ie_t; -+#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ -+ -+/* QoS Capability IE */ -+BWL_PRE_PACKED_STRUCT struct qos_cap_ie { -+ uint8 qosinfo; -+} BWL_POST_PACKED_STRUCT; -+typedef struct qos_cap_ie qos_cap_ie_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { -+ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ -+ uint8 length; -+ uint16 station_count; /* total number of STAs associated */ -+ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ -+ uint16 aac; /* available admission capacity */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; -+#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ -+ -+/* nom_msdu_size */ -+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ -+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ -+ -+/* surplus_bandwidth */ -+/* Represented as 3 bits of integer, binary point, 13 bits fraction */ -+#define INTEGER_SHIFT 13 /* integer shift */ -+#define FRACTION_MASK 0x1FFF /* fraction mask */ -+ -+/* Management Notification Frame */ -+BWL_PRE_PACKED_STRUCT struct dot11_management_notification { -+ uint8 category; /* DOT11_ACTION_NOTIFICATION */ -+ uint8 action; -+ uint8 token; -+ uint8 status; -+ uint8 data[1]; /* Elements */ -+} BWL_POST_PACKED_STRUCT; -+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ -+ -+/* Timeout Interval IE */ -+BWL_PRE_PACKED_STRUCT struct ti_ie { -+ uint8 ti_type; -+ uint32 ti_val; -+} BWL_POST_PACKED_STRUCT; -+typedef struct ti_ie ti_ie_t; -+#define TI_TYPE_REASSOC_DEADLINE 1 -+#define TI_TYPE_KEY_LIFETIME 2 -+ -+/* WME Action Codes */ -+#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ -+#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ -+#define WME_DELTS_REQUEST 2 /* WME DELTS request */ -+ -+/* WME Setup Response Status Codes */ -+#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ -+#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ -+#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ -+ -+/* Macro to take a pointer to a beacon or probe response -+ * body and return the char* pointer to the SSID info element -+ */ -+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) -+ -+/* Authentication frame payload constants */ -+#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ -+#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ -+#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ -+#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ -+ -+/* Frame control macros */ -+#define FC_PVER_MASK 0x3 /* PVER mask */ -+#define FC_PVER_SHIFT 0 /* PVER shift */ -+#define FC_TYPE_MASK 0xC /* type mask */ -+#define FC_TYPE_SHIFT 2 /* type shift */ -+#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ -+#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ -+#define FC_TODS 0x100 /* to DS */ -+#define FC_TODS_SHIFT 8 /* to DS shift */ -+#define FC_FROMDS 0x200 /* from DS */ -+#define FC_FROMDS_SHIFT 9 /* from DS shift */ -+#define FC_MOREFRAG 0x400 /* more frag. */ -+#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ -+#define FC_RETRY 0x800 /* retry */ -+#define FC_RETRY_SHIFT 11 /* retry shift */ -+#define FC_PM 0x1000 /* PM */ -+#define FC_PM_SHIFT 12 /* PM shift */ -+#define FC_MOREDATA 0x2000 /* more data */ -+#define FC_MOREDATA_SHIFT 13 /* more data shift */ -+#define FC_WEP 0x4000 /* WEP */ -+#define FC_WEP_SHIFT 14 /* WEP shift */ -+#define FC_ORDER 0x8000 /* order */ -+#define FC_ORDER_SHIFT 15 /* order shift */ -+ -+/* sequence control macros */ -+#define SEQNUM_SHIFT 4 /* seq. number shift */ -+#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ -+#define FRAGNUM_MASK 0xF /* frag. number mask */ -+ -+/* Frame Control type/subtype defs */ -+ -+/* FC Types */ -+#define FC_TYPE_MNG 0 /* management type */ -+#define FC_TYPE_CTL 1 /* control type */ -+#define FC_TYPE_DATA 2 /* data type */ -+ -+/* Management Subtypes */ -+#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ -+#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ -+#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ -+#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ -+#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ -+#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ -+#define FC_SUBTYPE_BEACON 8 /* beacon */ -+#define FC_SUBTYPE_ATIM 9 /* ATIM */ -+#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ -+#define FC_SUBTYPE_AUTH 11 /* authentication */ -+#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ -+#define FC_SUBTYPE_ACTION 13 /* action */ -+#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ -+ -+/* Control Subtypes */ -+#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ -+#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ -+#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ -+#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ -+#define FC_SUBTYPE_RTS 11 /* RTS */ -+#define FC_SUBTYPE_CTS 12 /* CTS */ -+#define FC_SUBTYPE_ACK 13 /* ACK */ -+#define FC_SUBTYPE_CF_END 14 /* CF-END */ -+#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ -+ -+/* Data Subtypes */ -+#define FC_SUBTYPE_DATA 0 /* Data */ -+#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ -+#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ -+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ -+#define FC_SUBTYPE_NULL 4 /* Null */ -+#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ -+#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ -+#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ -+#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ -+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ -+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ -+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ -+#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ -+#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ -+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ -+ -+/* Data Subtype Groups */ -+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) -+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) -+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) -+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) -+ -+/* Type/Subtype Combos */ -+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ -+ -+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ -+ -+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ -+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ -+ -+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ -+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ -+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ -+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ -+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ -+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ -+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ -+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ -+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ -+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ -+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ -+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ -+ -+#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ -+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ -+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ -+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ -+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ -+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ -+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ -+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ -+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ -+ -+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ -+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ -+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ -+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ -+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ -+ -+/* QoS Control Field */ -+ -+/* 802.1D Priority */ -+#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ -+#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ -+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ -+ -+/* Traffic Identifier */ -+#define QOS_TID_SHIFT 0 /* QoS TID shift */ -+#define QOS_TID_MASK 0x000f /* QoS TID mask */ -+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ -+ -+/* End of Service Period (U-APSD) */ -+#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ -+#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ -+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ -+ -+/* Ack Policy */ -+#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ -+#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ -+#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ -+#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ -+#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ -+#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ -+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ -+ -+/* A-MSDU flag */ -+#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ -+#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ -+ -+/* Management Frames */ -+ -+/* Management Frame Constants */ -+ -+/* Fixed fields */ -+#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ -+#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ -+#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ -+#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ -+#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ -+#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ -+#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ -+#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ -+#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ -+#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ -+ -+/* DUR/ID field in assoc resp is 0xc000 | AID */ -+#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ -+ -+/* Reason Codes */ -+#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ -+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ -+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ -+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station -+ * is leaving (or has left) IBSS or ESS -+ */ -+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ -+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle -+ * all currently associated stations -+ */ -+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from -+ * nonauthenticated station -+ */ -+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from -+ * nonassociated station -+ */ -+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is -+ * leaving (or has left) BSS -+ */ -+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not -+ * authenticated with responding station -+ */ -+#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ -+#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ -+/* 12 is unused */ -+ -+/* 32-39 are QSTA specific reasons added in 11e */ -+#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ -+#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ -+#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ -+#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ -+#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ -+#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ -+#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ -+#define DOT11_RC_TIMEOUT 39 /* timeout */ -+ -+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ -+ -+#define DOT11_RC_TDLS_PEER_UNREACH 25 -+#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 -+ -+/* Status Codes */ -+#define DOT11_SC_SUCCESS 0 /* Successful */ -+#define DOT11_SC_FAILURE 1 /* Unspecified failure */ -+#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ -+ /* schedule provided */ -+#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ -+#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ -+#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ -+#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ -+#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested -+ * capabilities in the Capability -+ * Information field -+ */ -+#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability -+ * to confirm that association exists -+ */ -+#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason -+ * outside the scope of this standard -+ */ -+#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support -+ * the specified authentication -+ * algorithm -+ */ -+#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame -+ * with authentication transaction -+ * sequence number out of expected -+ * sequence -+ */ -+#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of -+ * challenge failure -+ */ -+#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout -+ * waiting for next frame in sequence -+ */ -+#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is -+ * unable to handle additional -+ * associated stations -+ */ -+#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting -+ * station not supporting all of the -+ * data rates in the BSSBasicRateSet -+ * parameter -+ */ -+#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting -+ * station not supporting the Short -+ * Preamble option -+ */ -+#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting -+ * station not supporting the PBCC -+ * Modulation option -+ */ -+#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting -+ * station not supporting the Channel -+ * Agility option -+ */ -+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum -+ * Management capability is required. -+ */ -+#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info -+ * in the Power Cap element is -+ * unacceptable. -+ */ -+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info -+ * in the Supported Channel element is -+ * unacceptable -+ */ -+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting -+ * station not supporting the Short Slot -+ * Time option -+ */ -+#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting -+ * station not supporting the ER-PBCC -+ * Modulation option -+ */ -+#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting -+ * station not supporting the DSS-OFDM -+ * option -+ */ -+#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP -+ * being unable to reach the R0 Key Holder -+ */ -+#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later -+ */ -+#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management -+ * frame policy violation -+ */ -+ -+#define DOT11_SC_DECLINED 37 /* request declined */ -+#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ -+#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ -+#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ -+#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ -+#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ -+#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ -+#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ -+#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ -+ -+#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ -+#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ -+#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ -+ -+/* Info Elts, length of INFORMATION portion of Info Elts */ -+#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ -+#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ -+ -+/* TIM Info element has 3 bytes fixed info in INFORMATION field, -+ * followed by 1 to 251 bytes of Partial Virtual Bitmap -+ */ -+#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ -+#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ -+#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ -+#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ -+#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ -+ -+/* TLV defines */ -+#define TLV_TAG_OFF 0 /* tag offset */ -+#define TLV_LEN_OFF 1 /* length offset */ -+#define TLV_HDR_LEN 2 /* header length */ -+#define TLV_BODY_OFF 2 /* body offset */ -+ -+/* Management Frame Information Element IDs */ -+#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ -+#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ -+#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ -+#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ -+#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ -+#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ -+#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ -+#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ -+#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ -+#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ -+#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ -+#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ -+#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ -+#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ -+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ -+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ -+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ -+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ -+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ -+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ -+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ -+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ -+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ -+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ -+#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ -+#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ -+#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ -+#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ -+#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ -+#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ -+#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ -+#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ -+#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ -+#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ -+#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ -+#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ -+#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ -+#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ -+#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ -+#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ -+#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ -+#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ -+#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ -+#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ -+#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ -+#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ -+#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ -+#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ -+#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ -+#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ -+#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ -+#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ -+#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ -+#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ -+#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ -+#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ -+#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ -+#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ -+#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ -+#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ -+#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ -+#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ -+ -+#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ -+#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ -+/* should start using this one instead of above two */ -+#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ -+ -+/* Rate element Basic flag and rate mask */ -+#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ -+#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ -+ -+/* ERP info element bit values */ -+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ -+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present -+ *in the BSS -+ */ -+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for -+ *ERP-OFDM frames -+ */ -+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, -+ * 1 == not allowed -+ */ -+/* TS Delay element offset & size */ -+#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ -+#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ -+ -+/* Capability Information Field */ -+#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ -+#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ -+#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ -+#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ -+#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ -+#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ -+#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ -+#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ -+#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ -+#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ -+#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ -+#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ -+ -+/* Extended capabilities IE bitfields */ -+/* 20/40 BSS Coexistence Management support bit position */ -+#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 -+/* scheduled PSMP support bit position */ -+#define DOT11_EXT_CAP_SPSMP 6 -+/* BSS Transition Management support bit position */ -+#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 -+/* Interworking support bit position */ -+#define DOT11_EXT_CAP_IW 31 -+/* service Interval granularity bit position and mask */ -+#define DOT11_EXT_CAP_SI 41 -+#define DOT11_EXT_CAP_SI_MASK 0x0E -+ -+/* -+ * Action Frame Constants -+ */ -+#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ -+#define DOT11_ACTION_CAT_OFF 0 /* category offset */ -+#define DOT11_ACTION_ACT_OFF 1 /* action offset */ -+ -+/* Action Category field (sec 7.3.1.11) */ -+#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ -+#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ -+#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ -+#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ -+#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ -+#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ -+#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ -+#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ -+#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ -+#define DOT11_ACTION_CAT_HT 7 /* category for HT */ -+#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ -+#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ -+#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ -+#define DOT11_ACTION_NOTIFICATION 17 -+#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ -+#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ -+ -+/* Spectrum Management Action IDs (sec 7.4.1) */ -+#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ -+#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ -+#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ -+#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ -+#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ -+#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ -+ -+/* HT action ids */ -+#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ -+#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ -+ -+/* Public action ids */ -+#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ -+#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ -+ -+/* Block Ack action types */ -+#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ -+#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ -+#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ -+ -+/* ADDBA action parameters */ -+#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ -+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ -+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ -+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ -+#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ -+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ -+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ -+ -+#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ -+#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ -+ -+/* Fast Transition action types */ -+#define DOT11_FT_ACTION_FT_RESERVED 0 -+#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ -+#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ -+#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ -+#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ -+ -+/* DLS action types */ -+#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ -+#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ -+#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ -+ -+/* Wireless Network Management (WNM) action types */ -+#define DOT11_WNM_ACTION_EVENT_REQ 0 -+#define DOT11_WNM_ACTION_EVENT_REP 1 -+#define DOT11_WNM_ACTION_DIAG_REQ 2 -+#define DOT11_WNM_ACTION_DIAG_REP 3 -+#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 -+#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 -+#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 -+#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 -+#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 -+#define DOT11_WNM_ACTION_FMS_REQ 9 -+#define DOT11_WNM_ACTION_FMS_RESP 10 -+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 -+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 -+#define DOT11_WNM_ACTION_TFS_REQ 13 -+#define DOT11_WNM_ACTION_TFS_RESP 14 -+#define DOT11_WNM_ACTION_TFS_NOTIFY 15 -+#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 -+#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 -+#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 -+#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 -+#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 -+#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 -+#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 -+#define DOT11_WNM_ACTION_DMS_REQ 23 -+#define DOT11_WNM_ACTION_DMS_RESP 24 -+#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 -+#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 -+#define DOT11_WNM_ACTION_NOTFCTN_RES 27 -+ -+#define DOT11_MNG_COUNTRY_ID_LEN 3 -+ -+/* DLS Request frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_dls_req { -+ uint8 category; /* category of action frame (2) */ -+ uint8 action; /* DLS action: req (0) */ -+ struct ether_addr da; /* destination address */ -+ struct ether_addr sa; /* source address */ -+ uint16 cap; /* capability */ -+ uint16 timeout; /* timeout value */ -+ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_dls_req dot11_dls_req_t; -+#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ -+ -+/* DLS response frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { -+ uint8 category; /* category of action frame (2) */ -+ uint8 action; /* DLS action: req (0) */ -+ uint16 status; /* status code field */ -+ struct ether_addr da; /* destination address */ -+ struct ether_addr sa; /* source address */ -+ uint8 data[1]; /* optional: capability, rate ... */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_dls_resp dot11_dls_resp_t; -+#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ -+ -+ -+/* BSS Management Transition Query frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { -+ uint8 category; /* category of action frame (10) */ -+ uint8 action; /* WNM action: trans_query (6) */ -+ uint8 token; /* dialog token */ -+ uint8 reason; /* transition query reason */ -+ uint8 data[1]; /* Elements */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; -+#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ -+ -+/* BSS Management Transition Request frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { -+ uint8 category; /* category of action frame (10) */ -+ uint8 action; /* WNM action: trans_req (7) */ -+ uint8 token; /* dialog token */ -+ uint8 reqmode; /* transition request mode */ -+ uint16 disassoc_tmr; /* disassociation timer */ -+ uint8 validity_intrvl; /* validity interval */ -+ uint8 data[1]; /* optional: BSS term duration, ... */ -+ /* ...session info URL, list */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; -+#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ -+ -+#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ -+ -+ -+/* BSS Mgmt Transition Request Mode Field - 802.11v */ -+#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 -+#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 -+#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 -+#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 -+#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 -+ -+ -+/* BSS Management transition response frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { -+ uint8 category; /* category of action frame (10) */ -+ uint8 action; /* WNM action: trans_res (8) */ -+ uint8 token; /* dialog token */ -+ uint8 status; /* transition status */ -+ uint8 term_delay; /* validity interval */ -+ uint8 data[1]; /* optional: BSS term duration, ... */ -+ /* ...session info URL, list */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; -+#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ -+ -+/* BSS Mgmt Transition Response Status Field */ -+#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 -+#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 -+#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 -+ -+ -+/* Neighbor Report BSSID Information Field */ -+#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 -+#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 -+#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 -+ -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 -+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 -+ -+/* Neighbor Report Subelements */ -+#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 -+ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_addba_req { -+ uint8 category; /* category of action frame (3) */ -+ uint8 action; /* action: addba req */ -+ uint8 token; /* identifier */ -+ uint16 addba_param_set; /* parameter set */ -+ uint16 timeout; /* timeout in seconds */ -+ uint16 start_seqnum; /* starting sequence number */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_addba_req dot11_addba_req_t; -+#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { -+ uint8 category; /* category of action frame (3) */ -+ uint8 action; /* action: addba resp */ -+ uint8 token; /* identifier */ -+ uint16 status; /* status of add request */ -+ uint16 addba_param_set; /* negotiated parameter set */ -+ uint16 timeout; /* negotiated timeout in seconds */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_addba_resp dot11_addba_resp_t; -+#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ -+ -+/* DELBA action parameters */ -+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ -+#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ -+#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ -+#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ -+ -+BWL_PRE_PACKED_STRUCT struct dot11_delba { -+ uint8 category; /* category of action frame (3) */ -+ uint8 action; /* action: addba req */ -+ uint16 delba_param_set; /* paarmeter set */ -+ uint16 reason; /* reason for dellba */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_delba dot11_delba_t; -+#define DOT11_DELBA_LEN 6 /* length of delba frame */ -+ -+/* SA Query action field value */ -+#define SA_QUERY_REQUEST 0 -+#define SA_QUERY_RESPONSE 1 -+ -+/* ************* 802.11r related definitions. ************* */ -+ -+/* Over-the-DS Fast Transition Request frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_ft_req { -+ uint8 category; /* category of action frame (6) */ -+ uint8 action; /* action: ft req */ -+ uint8 sta_addr[ETHER_ADDR_LEN]; -+ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; -+ uint8 data[1]; /* Elements */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_ft_req dot11_ft_req_t; -+#define DOT11_FT_REQ_FIXED_LEN 14 -+ -+/* Over-the-DS Fast Transition Response frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_ft_res { -+ uint8 category; /* category of action frame (6) */ -+ uint8 action; /* action: ft resp */ -+ uint8 sta_addr[ETHER_ADDR_LEN]; -+ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; -+ uint16 status; /* status code */ -+ uint8 data[1]; /* Elements */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_ft_res dot11_ft_res_t; -+#define DOT11_FT_RES_FIXED_LEN 16 -+ -+ -+/* ************* 802.11k related definitions. ************* */ -+ -+/* Radio measurements enabled capability ie */ -+ -+#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ -+BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { -+ uint8 cap[DOT11_RRM_CAP_LEN]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; -+ -+/* Bitmap definitions for cap ie */ -+#define DOT11_RRM_CAP_LINK 0 -+#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 -+#define DOT11_RRM_CAP_PARALLEL 2 -+#define DOT11_RRM_CAP_REPEATED 3 -+#define DOT11_RRM_CAP_BCN_PASSIVE 4 -+#define DOT11_RRM_CAP_BCN_ACTIVE 5 -+#define DOT11_RRM_CAP_BCN_TABLE 6 -+#define DOT11_RRM_CAP_BCN_REP_COND 7 -+#define DOT11_RRM_CAP_AP_CHANREP 16 -+ -+ -+/* Operating Class (formerly "Regulatory Class") definitions */ -+#define DOT11_OP_CLASS_NONE 255 -+ -+ -+/* Radio Measurements action ids */ -+#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ -+#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ -+#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ -+#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ -+#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ -+#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ -+ -+/* Generic radio measurement action frame header */ -+BWL_PRE_PACKED_STRUCT struct dot11_rm_action { -+ uint8 category; /* category of action frame (5) */ -+ uint8 action; /* radio measurement action */ -+ uint8 token; /* dialog token */ -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rm_action dot11_rm_action_t; -+#define DOT11_RM_ACTION_LEN 3 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_rmreq { -+ uint8 category; /* category of action frame (5) */ -+ uint8 action; /* radio measurement action */ -+ uint8 token; /* dialog token */ -+ uint16 reps; /* no. of repetitions */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rmreq dot11_rmreq_t; -+#define DOT11_RMREQ_LEN 5 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { -+ uint8 id; -+ uint8 len; -+ uint8 token; -+ uint8 mode; -+ uint8 type; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rm_ie dot11_rm_ie_t; -+#define DOT11_RM_IE_LEN 5 -+ -+/* Definitions for "mode" bits in rm req */ -+#define DOT11_RMREQ_MODE_PARALLEL 1 -+#define DOT11_RMREQ_MODE_ENABLE 2 -+#define DOT11_RMREQ_MODE_REQUEST 4 -+#define DOT11_RMREQ_MODE_REPORT 8 -+#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ -+ -+/* Definitions for "mode" bits in rm rep */ -+#define DOT11_RMREP_MODE_LATE 1 -+#define DOT11_RMREP_MODE_INCAPABLE 2 -+#define DOT11_RMREP_MODE_REFUSED 4 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { -+ uint8 id; -+ uint8 len; -+ uint8 token; -+ uint8 mode; -+ uint8 type; -+ uint8 reg; -+ uint8 channel; -+ uint16 interval; -+ uint16 duration; -+ uint8 bcn_mode; -+ struct ether_addr bssid; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; -+#define DOT11_RMREQ_BCN_LEN 18 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { -+ uint8 reg; -+ uint8 channel; -+ uint32 starttime[2]; -+ uint16 duration; -+ uint8 frame_info; -+ uint8 rcpi; -+ uint8 rsni; -+ struct ether_addr bssid; -+ uint8 antenna_id; -+ uint32 parent_tsf; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; -+#define DOT11_RMREP_BCN_LEN 26 -+ -+/* Beacon request measurement mode */ -+#define DOT11_RMREQ_BCN_PASSIVE 0 -+#define DOT11_RMREQ_BCN_ACTIVE 1 -+#define DOT11_RMREQ_BCN_TABLE 2 -+ -+/* Sub-element IDs for Beacon Request */ -+#define DOT11_RMREQ_BCN_SSID_ID 0 -+#define DOT11_RMREQ_BCN_REPINFO_ID 1 -+#define DOT11_RMREQ_BCN_REPDET_ID 2 -+#define DOT11_RMREQ_BCN_REQUEST_ID 10 -+#define DOT11_RMREQ_BCN_APCHREP_ID 51 -+ -+/* Reporting Detail element definition */ -+#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ -+#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ -+#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ -+ -+/* Sub-element IDs for Beacon Report */ -+#define DOT11_RMREP_BCN_FRM_BODY 1 -+ -+/* Neighbor measurement report */ -+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { -+ struct ether_addr bssid; -+ uint32 bssid_info; -+ uint8 reg; -+ uint8 channel; -+ uint8 phytype; -+ uchar sub_elements[1]; /* Variable size data */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; -+#define DOT11_RMREP_NBR_LEN 13 -+ -+/* MLME Enumerations */ -+#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ -+#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ -+#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ -+#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ -+#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ -+ -+/* Link Measurement */ -+BWL_PRE_PACKED_STRUCT struct dot11_lmreq { -+ uint8 category; /* category of action frame (5) */ -+ uint8 action; /* radio measurement action */ -+ uint8 token; /* dialog token */ -+ uint8 txpwr; /* Transmit Power Used */ -+ uint8 maxtxpwr; /* Max Transmit Power */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_lmreq dot11_lmreq_t; -+#define DOT11_LMREQ_LEN 5 -+ -+BWL_PRE_PACKED_STRUCT struct dot11_lmrep { -+ uint8 category; /* category of action frame (5) */ -+ uint8 action; /* radio measurement action */ -+ uint8 token; /* dialog token */ -+ dot11_tpc_rep_t tpc; /* TPC element */ -+ uint8 rxant; /* Receive Antenna ID */ -+ uint8 txant; /* Transmit Antenna ID */ -+ uint8 rcpi; /* RCPI */ -+ uint8 rsni; /* RSNI */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_lmrep dot11_lmrep_t; -+#define DOT11_LMREP_LEN 11 -+ -+/* 802.11 BRCM "Compromise" Pre N constants */ -+#define PREN_PREAMBLE 24 /* green field preamble time */ -+#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ -+#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ -+ -+/* 802.11N PHY constants */ -+#define RIFS_11N_TIME 2 /* NPHY RIFS time */ -+ -+/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 -+ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 -+ */ -+/* HT-SIG1 */ -+#define HT_SIG1_MCS_MASK 0x00007F -+#define HT_SIG1_CBW 0x000080 -+#define HT_SIG1_HT_LENGTH 0xFFFF00 -+ -+/* HT-SIG2 */ -+#define HT_SIG2_SMOOTHING 0x000001 -+#define HT_SIG2_NOT_SOUNDING 0x000002 -+#define HT_SIG2_RESERVED 0x000004 -+#define HT_SIG2_AGGREGATION 0x000008 -+#define HT_SIG2_STBC_MASK 0x000030 -+#define HT_SIG2_STBC_SHIFT 4 -+#define HT_SIG2_FEC_CODING 0x000040 -+#define HT_SIG2_SHORT_GI 0x000080 -+#define HT_SIG2_ESS_MASK 0x000300 -+#define HT_SIG2_ESS_SHIFT 8 -+#define HT_SIG2_CRC 0x03FC00 -+#define HT_SIG2_TAIL 0x1C0000 -+ -+/* 802.11 A PHY constants */ -+#define APHY_SLOT_TIME 9 /* APHY slot time */ -+#define APHY_SIFS_TIME 16 /* APHY SIFS time */ -+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ -+#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ -+#define APHY_SIGNAL_TIME 4 /* APHY signal time */ -+#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ -+#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ -+#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ -+#define APHY_CWMIN 15 /* APHY cwmin */ -+ -+/* 802.11 B PHY constants */ -+#define BPHY_SLOT_TIME 20 /* BPHY slot time */ -+#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ -+#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ -+#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ -+#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ -+#define BPHY_CWMIN 31 /* BPHY cwmin */ -+ -+/* 802.11 G constants */ -+#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ -+ -+#define PHY_CWMAX 1023 /* PHY cwmax */ -+ -+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ -+ -+/* 802.11 AC (VHT) constants */ -+ -+typedef int vht_group_id_t; -+ -+/* for VHT-A1 */ -+/* SIG-A1 reserved bits */ -+#define VHT_SIGA1_CONST_MASK 0x800004 -+ -+#define VHT_SIGA1_20MHZ_VAL 0x000000 -+#define VHT_SIGA1_40MHZ_VAL 0x000001 -+#define VHT_SIGA1_80MHZ_VAL 0x000002 -+#define VHT_SIGA1_160MHZ_VAL 0x000003 -+ -+#define VHT_SIGA1_STBC 0x000008 -+ -+#define VHT_SIGA1_GID_MAX_GID 0x3f -+#define VHT_SIGA1_GID_SHIFT 4 -+#define VHT_SIGA1_GID_TO_AP 0x00 -+#define VHT_SIGA1_GID_NOT_TO_AP 0x3f -+ -+#define VHT_SIGA1_NSTS_SHIFT 10 -+#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 -+ -+#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 -+ -+/* for VHT-A2 */ -+#define VHT_SIGA2_GI_NONE 0x000000 -+#define VHT_SIGA2_GI_SHORT 0x000001 -+#define VHT_SIGA2_GI_W_MOD10 0x000002 -+#define VHT_SIGA2_CODING_LDPC 0x000004 -+#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 -+#define VHT_SIGA2_MCS_SHIFT 4 -+ -+#define VHT_SIGA2_B9_RESERVED 0x000200 -+#define VHT_SIGA2_TAIL_MASK 0xfc0000 -+#define VHT_SIGA2_TAIL_VALUE 0x000000 -+ -+#define VHT_SIGA2_SVC_BITS 16 -+#define VHT_SIGA2_TAIL_BITS 6 -+ -+ -+/* dot11Counters Table - 802.11 spec., Annex D */ -+typedef struct d11cnt { -+ uint32 txfrag; /* dot11TransmittedFragmentCount */ -+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ -+ uint32 txfail; /* dot11FailedCount */ -+ uint32 txretry; /* dot11RetryCount */ -+ uint32 txretrie; /* dot11MultipleRetryCount */ -+ uint32 rxdup; /* dot11FrameduplicateCount */ -+ uint32 txrts; /* dot11RTSSuccessCount */ -+ uint32 txnocts; /* dot11RTSFailureCount */ -+ uint32 txnoack; /* dot11ACKFailureCount */ -+ uint32 rxfrag; /* dot11ReceivedFragmentCount */ -+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ -+ uint32 rxcrc; /* dot11FCSErrorCount */ -+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ -+ uint32 rxundec; /* dot11WEPUndecryptableCount */ -+} d11cnt_t; -+ -+/* OUI for BRCM proprietary IE */ -+#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* The following BRCM_PROP_OUI types are currently in use (defined in -+ * relevant subsections). Each of them will be in a separate proprietary(221) IE -+ * #define SES_VNDR_IE_TYPE 1 (defined in src/ses/shared/ses.h) -+ * #define DPT_IE_TYPE 2 -+ * #define HT_CAP_IE_TYPE 51 -+ * #define HT_ADD_IE_TYPE 52 -+ * #define BRCM_EXTCH_IE_TYPE 53 -+ */ -+ -+/* Following is the generic structure for brcm_prop_ie (uses BRCM_PROP_OUI). -+ * DPT uses this format with type set to DPT_IE_TYPE -+ */ -+BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s { -+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ -+ uint8 len; /* IE length */ -+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ -+ uint8 type; /* type of this IE */ -+ uint16 cap; /* DPT capabilities */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct brcm_prop_ie_s brcm_prop_ie_t; -+ -+#define BRCM_PROP_IE_LEN 6 /* len of fixed part of brcm_prop ie */ -+ -+#define DPT_IE_TYPE 2 -+#define WET_TUNNEL_IE_TYPE 3 -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ -+#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ -+ -+/* BRCM info element */ -+BWL_PRE_PACKED_STRUCT struct brcm_ie { -+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ -+ uint8 len; /* IE length */ -+ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ -+ uint8 ver; /* type/ver of this IE */ -+ uint8 assoc; /* # of assoc STAs */ -+ uint8 flags; /* misc flags */ -+ uint8 flags1; /* misc flags */ -+ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct brcm_ie brcm_ie_t; -+#define BRCM_IE_LEN 11 /* BRCM IE length */ -+#define BRCM_IE_VER 2 /* BRCM IE version */ -+#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ -+ -+/* brcm_ie flags */ -+#define BRF_LZWDS 0x4 /* lazy wds enabled */ -+#define BRF_BLOCKACK 0x8 /* BlockACK capable */ -+ -+/* brcm_ie flags1 */ -+#define BRF1_AMSDU 0x1 /* A-MSDU capable */ -+#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ -+#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ -+#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ -+#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ -+#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ -+ -+/* Vendor IE structure */ -+BWL_PRE_PACKED_STRUCT struct vndr_ie { -+ uchar id; -+ uchar len; -+ uchar oui [3]; -+ uchar data [1]; /* Variable size data */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct vndr_ie vndr_ie_t; -+ -+#define VNDR_IE_HDR_LEN 2 /* id + len field */ -+#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ -+#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ -+ -+/* ************* HT definitions. ************* */ -+#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ -+#define MAX_MCS_NUM (128) /* max mcs number = 128 */ -+ -+BWL_PRE_PACKED_STRUCT struct ht_cap_ie { -+ uint16 cap; -+ uint8 params; -+ uint8 supp_mcs[MCSSET_LEN]; -+ uint16 ext_htcap; -+ uint32 txbf_cap; -+ uint8 as_cap; -+} BWL_POST_PACKED_STRUCT; -+typedef struct ht_cap_ie ht_cap_ie_t; -+ -+/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ -+/* the capability IE is primarily used to convey this nodes abilities */ -+BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { -+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ -+ uint8 len; /* IE length */ -+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ -+ uint8 type; /* type inidicates what follows */ -+ ht_cap_ie_t cap_ie; -+} BWL_POST_PACKED_STRUCT; -+typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; -+ -+#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ -+#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ -+#define HT_CAP_IE_TYPE 51 -+ -+#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ -+#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ -+#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ -+#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ -+#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ -+#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ -+#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ -+#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ -+#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ -+#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ -+#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ -+#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ -+#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ -+#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ -+#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ -+ -+#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ -+#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ -+#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ -+#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ -+ -+#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ -+#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ -+#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ -+#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ -+ -+#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ -+#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ -+/* Max AMSDU len - per spec */ -+#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) -+ -+#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ -+#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ -+ -+#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ -+#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ -+#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ -+ -+/* HT/AMPDU specific define */ -+#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */ -+#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ -+#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ -+#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ -+#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ -+#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ -+ -+#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ -+#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ -+ -+#define HT_CAP_EXT_PCO 0x0001 -+#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 -+#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 -+#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 -+#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 -+#define HT_CAP_EXT_HTC 0x0400 -+#define HT_CAP_EXT_RD_RESP 0x0800 -+ -+BWL_PRE_PACKED_STRUCT struct ht_add_ie { -+ uint8 ctl_ch; /* control channel number */ -+ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ -+ uint16 opmode; /* operation mode */ -+ uint16 misc_bits; /* misc bits */ -+ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct ht_add_ie ht_add_ie_t; -+ -+/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ -+/* the additional IE is primarily used to convey the current BSS configuration */ -+BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { -+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ -+ uint8 len; /* IE length */ -+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ -+ uint8 type; /* indicates what follows */ -+ ht_add_ie_t add_ie; -+} BWL_POST_PACKED_STRUCT; -+typedef struct ht_prop_add_ie ht_prop_add_ie_t; -+ -+#define HT_ADD_IE_LEN 22 -+#define HT_ADD_IE_TYPE 52 -+ -+/* byte1 defn's */ -+#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ -+#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ -+ -+/* opmode defn's */ -+#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ -+#define HT_OPMODE_SHIFT 0 /* protection mode shift */ -+#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ -+#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ -+#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ -+#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ -+#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ -+#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ -+#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ -+ -+/* misc_bites defn's */ -+#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ -+#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ -+#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ -+#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ -+#define HT_PCO_ACTIVE 0x0400 /* PCO active */ -+#define HT_PCO_PHASE 0x0800 /* PCO phase */ -+#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ -+ -+/* Tx Burst Limits */ -+#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ -+#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ -+ -+/* Macros for opmode */ -+#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ -+ >> HT_OPMODE_SHIFT) -+#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ -+ == HT_OPMODE_MIXED) /* mixed mode present */ -+#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ -+ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ -+#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ -+ == HT_OPMODE_OPTIONAL) /* Optional protection present */ -+#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ -+ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ -+#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ -+ == HT_OPMODE_NONGF) /* non-GF present */ -+#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ -+ == DOT11N_TXBURST) /* Tx Burst present */ -+#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ -+ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ -+ -+BWL_PRE_PACKED_STRUCT struct obss_params { -+ uint16 passive_dwell; -+ uint16 active_dwell; -+ uint16 bss_widthscan_interval; -+ uint16 passive_total; -+ uint16 active_total; -+ uint16 chanwidth_transition_dly; -+ uint16 activity_threshold; -+} BWL_POST_PACKED_STRUCT; -+typedef struct obss_params obss_params_t; -+ -+BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { -+ uint8 id; -+ uint8 len; -+ obss_params_t obss_params; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_obss_ie dot11_obss_ie_t; -+#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ -+ -+/* HT control field */ -+#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ -+#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ -+#define HT_CTRL_LA_MAI_SHIFT 2 -+#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ -+#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ -+#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ -+#define HT_CTRL_LA_MFSI_SHIFT 6 -+#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ -+#define HT_CTRL_LA_MFB_ASELC_SH 9 -+#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ -+#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ -+#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ -+#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ -+#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ -+#define HT_CTRL_CSI_STEER_SHIFT 22 -+#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ -+#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ -+#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ -+#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ -+#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ -+#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ -+#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ -+ -+#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ -+#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ -+#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ -+#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ -+#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ -+#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ -+ -+/* ************* VHT definitions. ************* */ -+ -+BWL_PRE_PACKED_STRUCT struct vht_cap_ie { -+ uint32 vht_cap_info; -+ /* supported MCS set - 64 bit field */ -+ uint16 rx_mcs_map; -+ uint16 rx_max_rate; -+ uint16 tx_mcs_map; -+ uint16 tx_max_rate; -+} BWL_POST_PACKED_STRUCT; -+typedef struct vht_cap_ie vht_cap_ie_t; -+/* 4B cap_info + 8B supp_mcs */ -+#define VHT_CAP_IE_LEN 12 -+/* 32bit - cap info */ -+#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 -+#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c -+#define VHT_CAP_INFO_LDPC 0x00000010 -+#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 -+#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 -+#define VHT_CAP_INFO_TX_STBC 0x00000080 -+#define VHT_CAP_INFO_RX_STBC 0x00000700 -+ -+#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 -+#define VHT_CAP_INFO_RX_STBC_SHIFT 8 -+#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 -+#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 -+#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 -+#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 -+ -+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 -+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 -+#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 -+#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 -+#define VHT_CAP_INFO_TXOPPS 0x00200000 -+#define VHT_CAP_INFO_HTCVHT 0x00400000 -+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 -+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 -+ -+#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 -+#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 -+ -+/* 64-bit Supp MCS. */ -+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff -+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 -+ -+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff -+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 -+ -+#define VHT_CAP_MCS_MAP_0_7 0 -+#define VHT_CAP_MCS_MAP_0_8 1 -+#define VHT_CAP_MCS_MAP_0_9 2 -+#define VHT_CAP_MCS_MAP_NONE 3 -+ -+#define VHT_CAP_MCS_MAP_NSS_MAX 8 -+ -+/* VHT Capabilities Supported Channel Width */ -+typedef enum vht_cap_chan_width { -+ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, -+ VHT_CAP_CHAN_WIDTH_80 = 0x04, -+ VHT_CAP_CHAN_WIDTH_160 = 0x08 -+} vht_cap_chan_width_t; -+ -+/* VHT Capabilities Supported max MPDU LEN */ -+typedef enum vht_cap_max_mpdu_len { -+ VHT_CAP_MPDU_MAX_4K = 0x00, -+ VHT_CAP_MPDU_MAX_8K = 0x01, -+ VHT_CAP_MPDU_MAX_11K = 0x02 -+} vht_cap_max_mpdu_len_t; -+ -+/* VHT Operation Element */ -+BWL_PRE_PACKED_STRUCT struct vht_op_ie { -+ uint8 chan_width; -+ uint8 chan1; -+ uint8 chan2; -+ uint16 supp_mcs; /* same def as above in vht cap */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct vht_op_ie vht_op_ie_t; -+/* 3B VHT Op info + 2B Basic MCS */ -+#define VHT_OP_IE_LEN 5 -+ -+typedef enum vht_op_chan_width { -+ VHT_OP_CHAN_WIDTH_20_40 = 0, -+ VHT_OP_CHAN_WIDTH_80 = 1, -+ VHT_OP_CHAN_WIDTH_160 = 2, -+ VHT_OP_CHAN_WIDTH_80_80 = 3 -+} vht_op_chan_width_t; -+ -+/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ -+#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) -+#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ -+ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) -+#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ -+ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) -+ -+/* ************* WPA definitions. ************* */ -+#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ -+#define WPA_OUI_LEN 3 /* WPA OUI length */ -+#define WPA_OUI_TYPE 1 -+#define WPA_VERSION 1 /* WPA version */ -+#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ -+#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ -+#define WPA2_VERSION 1 /* WPA2 version */ -+#define WPA2_VERSION_LEN 2 /* WAP2 version length */ -+ -+/* ************* WPS definitions. ************* */ -+#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ -+#define WPS_OUI_LEN 3 /* WPS OUI length */ -+#define WPS_OUI_TYPE 4 -+ -+/* ************* WFA definitions. ************* */ -+#if defined(MACOSX) -+#define MAC_OUI "\x00\x17\xF2" /* MACOSX OUI */ -+#define MAC_OUI_TYPE_P2P 5 -+#endif /* MACOSX */ -+ -+#if defined(MACOSX) && !defined(WLP2P_NEW_WFA_OUI) -+#define WFA_OUI WPS_OUI /* WFA OUI */ -+#else -+#ifdef P2P_IE_OVRD -+#define WFA_OUI MAC_OUI -+#else -+#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ -+#endif /* P2P_IE_OVRD */ -+#endif /* MACOSX && !WLP2P_NEW_WFA_OUI */ -+#define WFA_OUI_LEN 3 /* WFA OUI length */ -+#ifdef P2P_IE_OVRD -+#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P -+#else -+#define WFA_OUI_TYPE_P2P 9 -+#endif -+ -+#define WFA_OUI_TYPE_TPC 8 -+ -+/* RSN authenticated key managment suite */ -+#define RSN_AKM_NONE 0 /* None (IBSS) */ -+#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ -+#define RSN_AKM_PSK 2 /* Pre-shared Key */ -+#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ -+#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ -+#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ -+#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ -+#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ -+ -+/* Key related defines */ -+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ -+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ -+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ -+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ -+#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ -+ -+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ -+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ -+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ -+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ -+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ -+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ -+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ -+#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ -+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ -+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ -+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ -+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ -+#define AES_KEY_SIZE 16 /* size of AES key */ -+#define AES_MIC_SIZE 8 /* size of AES MIC */ -+#define BIP_KEY_SIZE 16 /* size of BIP key */ -+ -+/* WCN */ -+#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ -+#define WCN_TYPE 4 /* WCN type */ -+ -+ -+/* 802.11r protocol definitions */ -+ -+/* Mobility Domain IE */ -+BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { -+ uint8 id; -+ uint8 len; -+ uint16 mdid; /* Mobility Domain Id */ -+ uint8 cap; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_mdid_ie dot11_mdid_ie_t; -+ -+#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ -+#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ -+ -+/* Fast Bss Transition IE */ -+BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { -+ uint8 id; -+ uint8 len; -+ uint16 mic_control; /* Mic Control */ -+ uint8 mic[16]; -+ uint8 anonce[32]; -+ uint8 snonce[32]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_ft_ie dot11_ft_ie_t; -+ -+#define TIE_TYPE_RESERVED 0 -+#define TIE_TYPE_REASSOC_DEADLINE 1 -+#define TIE_TYPE_KEY_LIEFTIME 2 -+#define TIE_TYPE_ASSOC_COMEBACK 3 -+BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { -+ uint8 id; -+ uint8 len; -+ uint8 type; /* timeout interval type */ -+ uint32 value; /* timeout interval value */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_timeout_ie dot11_timeout_ie_t; -+ -+/* GTK ie */ -+BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { -+ uint8 id; -+ uint8 len; -+ uint16 key_info; -+ uint8 key_len; -+ uint8 rsc[8]; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT; -+typedef struct dot11_gtk_ie dot11_gtk_ie_t; -+ -+#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" -+#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" -+ -+ -+/* ************* WMM Parameter definitions. ************* */ -+#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ -+#define WMM_OUI_LEN 3 /* WMM OUI length */ -+#define WMM_OUI_TYPE 2 /* WMM OUT type */ -+#define WMM_VERSION 1 -+#define WMM_VERSION_LEN 1 -+ -+/* WMM OUI subtype */ -+#define WMM_OUI_SUBTYPE_PARAMETER 1 -+#define WMM_PARAMETER_IE_LEN 24 -+ -+/* Link Identifier Element */ -+BWL_PRE_PACKED_STRUCT struct link_id_ie { -+ uint8 id; -+ uint8 len; -+ struct ether_addr bssid; -+ struct ether_addr tdls_init_mac; -+ struct ether_addr tdls_resp_mac; -+} BWL_POST_PACKED_STRUCT; -+typedef struct link_id_ie link_id_ie_t; -+#define TDLS_LINK_ID_IE_LEN 18 -+ -+/* Link Wakeup Schedule Element */ -+BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { -+ uint8 id; -+ uint8 len; -+ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ -+ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ -+ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ -+ uint32 max_wake_win; /* in ms, max duration of Awake Window */ -+ uint16 idle_cnt; /* number of consecutive Awake Windows */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct wakeup_sch_ie wakeup_sch_ie_t; -+#define TDLS_WAKEUP_SCH_IE_LEN 18 -+ -+/* Channel Switch Timing Element */ -+BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { -+ uint8 id; -+ uint8 len; -+ uint16 switch_time; /* in ms, time to switch channels */ -+ uint16 switch_timeout; /* in ms */ -+} BWL_POST_PACKED_STRUCT; -+typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; -+#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 -+ -+/* PTI Control Element */ -+BWL_PRE_PACKED_STRUCT struct pti_control_ie { -+ uint8 id; -+ uint8 len; -+ uint8 tid; -+ uint16 seq_control; -+} BWL_POST_PACKED_STRUCT; -+typedef struct pti_control_ie pti_control_ie_t; -+#define TDLS_PTI_CONTROL_IE_LEN 3 -+ -+/* PU Buffer Status Element */ -+BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { -+ uint8 id; -+ uint8 len; -+ uint8 status; -+} BWL_POST_PACKED_STRUCT; -+typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; -+#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 -+#define TDLS_PU_BUFFER_STATUS_AC_BK 1 -+#define TDLS_PU_BUFFER_STATUS_AC_BE 2 -+#define TDLS_PU_BUFFER_STATUS_AC_VI 4 -+#define TDLS_PU_BUFFER_STATUS_AC_VO 8 -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _802_11_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.1d.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.1d.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.1d.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/802.1d.h 2017-11-09 17:53:43.977301000 +0800 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Fundamental types and constants relating to 802.1D -+ * -+ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _802_1_D_ -+#define _802_1_D_ -+ -+/* 802.1D priority defines */ -+#define PRIO_8021D_NONE 2 /* None = - */ -+#define PRIO_8021D_BK 1 /* BK - Background */ -+#define PRIO_8021D_BE 0 /* BE - Best-effort */ -+#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ -+#define PRIO_8021D_CL 4 /* CL - Controlled Load */ -+#define PRIO_8021D_VI 5 /* Vi - Video */ -+#define PRIO_8021D_VO 6 /* Vo - Voice */ -+#define PRIO_8021D_NC 7 /* NC - Network Control */ -+#define MAXPRIO 7 /* 0-7 */ -+#define NUMPRIO (MAXPRIO + 1) -+ -+#define ALLPRIO -1 /* All prioirty */ -+ -+/* Converts prio to precedence since the numerical value of -+ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. -+ */ -+#define PRIO2PREC(prio) \ -+ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) -+ -+#endif /* _802_1_D__ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/BOM b/drivers/net/ethernet/broadcom/gmac/src/include/proto/BOM ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/BOM 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/BOM 2017-11-09 17:53:43.978294000 +0800 -@@ -0,0 +1,4 @@ -+# Created by mkbom -+# $Id: BOM,v 9.0 1998-07-30 23:19:02 $ -+ -+File 1.46 vip.h -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/Makefile b/drivers/net/ethernet/broadcom/gmac/src/include/proto/Makefile ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/Makefile 2017-11-09 17:53:43.979288000 +0800 -@@ -0,0 +1,21 @@ -+# -+# include/proto/Makefile -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+# $Id: Makefile 241182 2011-02-17 21:50:03Z $ -+# -+ -+# build etags -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmeth.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmeth.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmeth.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmeth.h 2017-11-09 17:53:43.979307000 +0800 -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Ethernettype protocol definitions -+ * -+ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ -+ */ -+ -+/* -+ * Broadcom Ethernet protocol defines -+ */ -+ -+#ifndef _BCMETH_H_ -+#define _BCMETH_H_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+/* ETHER_TYPE_BRCM is defined in ethernet.h */ -+ -+/* -+ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field -+ * in one of two formats: (only subtypes 32768-65535 are in use now) -+ * -+ * subtypes 0-32767: -+ * 8 bit subtype (0-127) -+ * 8 bit length in bytes (0-255) -+ * -+ * subtypes 32768-65535: -+ * 16 bit big-endian subtype -+ * 16 bit big-endian length in bytes (0-65535) -+ * -+ * length is the number of additional bytes beyond the 4 or 6 byte header -+ * -+ * Reserved values: -+ * 0 reserved -+ * 5-15 reserved for iLine protocol assignments -+ * 17-126 reserved, assignable -+ * 127 reserved -+ * 32768 reserved -+ * 32769-65534 reserved, assignable -+ * 65535 reserved -+ */ -+ -+/* -+ * While adding the subtypes and their specific processing code make sure -+ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition -+ */ -+ -+#define BCMILCP_SUBTYPE_RATE 1 -+#define BCMILCP_SUBTYPE_LINK 2 -+#define BCMILCP_SUBTYPE_CSA 3 -+#define BCMILCP_SUBTYPE_LARQ 4 -+#define BCMILCP_SUBTYPE_VENDOR 5 -+#define BCMILCP_SUBTYPE_FLH 17 -+ -+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 -+#define BCMILCP_SUBTYPE_CERT 32770 -+#define BCMILCP_SUBTYPE_SES 32771 -+ -+ -+#define BCMILCP_BCM_SUBTYPE_RESERVED 0 -+#define BCMILCP_BCM_SUBTYPE_EVENT 1 -+#define BCMILCP_BCM_SUBTYPE_SES 2 -+/* -+ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded -+ * within BCMILCP_BCM_SUBTYPE_EVENT type messages -+ */ -+/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ -+#define BCMILCP_BCM_SUBTYPE_DPT 4 -+ -+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 -+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 -+ -+/* These fields are stored in network order */ -+typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr -+{ -+ uint16 subtype; /* Vendor specific..32769 */ -+ uint16 length; -+ uint8 version; /* Version is 0 */ -+ uint8 oui[3]; /* Broadcom OUI */ -+ /* user specific Data */ -+ uint16 usr_subtype; -+} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; -+ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _BCMETH_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmevent.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmevent.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmevent.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmevent.h 2017-11-09 17:53:43.988295000 +0800 -@@ -0,0 +1,313 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Event protocol definitions -+ * -+ * Dependencies: proto/bcmeth.h -+ * -+ * $Id: bcmevent.h 315348 2012-02-16 07:32:51Z $ -+ * -+ */ -+ -+/* -+ * Broadcom Ethernet Events protocol defines -+ * -+ */ -+ -+#ifndef _BCMEVENT_H_ -+#define _BCMEVENT_H_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ -+#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ -+ -+/* flags */ -+#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ -+#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ -+#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ -+#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ -+#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ -+ -+/* these fields are stored in network order */ -+ -+/* version 1 */ -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ uint16 version; -+ uint16 flags; /* see flags below */ -+ uint32 event_type; /* Message (see below) */ -+ uint32 status; /* Status code (see below) */ -+ uint32 reason; /* Reason code (if applicable) */ -+ uint32 auth_type; /* WLC_E_AUTH */ -+ uint32 datalen; /* data buf */ -+ struct ether_addr addr; /* Station address (if applicable) */ -+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ -+} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; -+ -+/* the current version */ -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ uint16 version; -+ uint16 flags; /* see flags below */ -+ uint32 event_type; /* Message (see below) */ -+ uint32 status; /* Status code (see below) */ -+ uint32 reason; /* Reason code (if applicable) */ -+ uint32 auth_type; /* WLC_E_AUTH */ -+ uint32 datalen; /* data buf */ -+ struct ether_addr addr; /* Station address (if applicable) */ -+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ -+ uint8 ifidx; /* destination OS i/f index */ -+ uint8 bsscfgidx; /* source bsscfg index */ -+} BWL_POST_PACKED_STRUCT wl_event_msg_t; -+ -+/* used by driver msgs */ -+typedef BWL_PRE_PACKED_STRUCT struct bcm_event { -+ struct ether_header eth; -+ bcmeth_hdr_t bcm_hdr; -+ wl_event_msg_t event; -+ /* data portion follows */ -+} BWL_POST_PACKED_STRUCT bcm_event_t; -+ -+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) -+ -+/* Event messages */ -+#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ -+#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ -+#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ -+#define WLC_E_AUTH 3 /* 802.11 AUTH request */ -+#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ -+#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ -+#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ -+#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ -+#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ -+#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ -+#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ -+#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ -+#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ -+#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ -+#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ -+#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ -+#define WLC_E_LINK 16 /* generic link indication */ -+#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ -+#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ -+#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ -+#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ -+#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ -+#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ -+#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ -+#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ -+#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ -+#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ -+#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ -+#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ -+#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ -+#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ -+#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ -+#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ -+#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ -+#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ -+#define WLC_E_RESET_COMPLETE 35 -+#define WLC_E_JOIN_START 36 -+#define WLC_E_ROAM_START 37 -+#define WLC_E_ASSOC_START 38 -+#define WLC_E_IBSS_ASSOC 39 -+#define WLC_E_RADIO 40 -+#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ -+#define WLC_E_PROBREQ_MSG 44 /* probe request received */ -+#define WLC_E_SCAN_CONFIRM_IND 45 -+#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ -+#define WLC_E_COUNTRY_CODE_CHANGED 47 -+#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ -+#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ -+#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ -+#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ -+#define WLC_E_TRACE 52 -+#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ -+#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ -+#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ -+#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ -+#define WLC_E_EXTLOG_MSG 58 -+#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ -+#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ -+#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ -+#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ -+#define WLC_E_CHANNEL_ADOPTED 63 -+#define WLC_E_AP_STARTED 64 /* AP started */ -+#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ -+#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ -+#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ -+#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ -+#define WLC_E_ESCAN_RESULT 69 /* escan result event */ -+#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ -+#define WLC_E_PROBRESP_MSG 71 /* probe response received */ -+#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ -+#define WLC_E_DCS_REQUEST 73 -+ -+#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ -+ -+#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH -+ * wl_event_rx_frame_data_t header -+ */ -+#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ -+#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ -+#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ -+#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ -+#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ -+#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ -+#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ -+#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ -+#define WLC_E_GTK_PLUMBED 84 -+#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ -+#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ -+#define WLC_E_ASSOC_REQ_IE 87 -+#define WLC_E_ASSOC_RESP_IE 88 -+ -+#define WLC_E_LAST 89 /* highest val + 1 for range checking */ -+ -+/* Table of event name strings for UIs and debugging dumps */ -+typedef struct { -+ uint event; -+ const char *name; -+} bcmevent_name_t; -+ -+extern const bcmevent_name_t bcmevent_names[]; -+extern const int bcmevent_names_size; -+ -+/* Event status codes */ -+#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ -+#define WLC_E_STATUS_FAIL 1 /* operation failed */ -+#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ -+#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ -+#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ -+#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ -+#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ -+#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ -+#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ -+#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ -+#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ -+#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ -+#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ -+#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ -+#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ -+#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ -+ -+/* roam reason codes */ -+#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ -+#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ -+#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ -+#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ -+#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ -+#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ -+#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ -+ -+/* Roam codes used primarily by CCX */ -+#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ -+#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ -+#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ -+#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ -+ -+#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ -+ -+/* prune reason codes */ -+#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ -+#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ -+#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ -+#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ -+#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ -+#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ -+#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ -+#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ -+#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ -+#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ -+#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ -+#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ -+#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ -+#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ -+#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ -+ -+/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ -+#define WLC_E_SUP_OTHER 0 /* Other reason */ -+#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ -+#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ -+#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ -+#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ -+#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ -+#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ -+#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ -+#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ -+#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ -+#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ -+#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ -+#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ -+#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ -+#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ -+#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ -+ -+/* Event data for events that include frames received over the air */ -+/* WLC_E_PROBRESP_MSG -+ * WLC_E_P2P_PROBREQ_MSG -+ * WLC_E_ACTION_FRAME_RX -+ */ -+typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { -+ uint16 version; -+ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ -+ int32 rssi; -+ uint32 mactime; -+ uint32 rate; -+} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; -+ -+#define BCM_RX_FRAME_DATA_VERSION 1 -+ -+/* WLC_E_IF event data */ -+typedef struct wl_event_data_if { -+ uint8 ifidx; /* RTE virtual device index (for dongle) */ -+ uint8 opcode; /* see I/F opcode */ -+ uint8 reserved; -+ uint8 bssidx; /* bsscfg index */ -+ uint8 role; /* see I/F role */ -+} wl_event_data_if_t; -+ -+/* opcode in WLC_E_IF event */ -+#define WLC_E_IF_ADD 1 /* bsscfg add */ -+#define WLC_E_IF_DEL 2 /* bsscfg delete */ -+#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ -+ -+/* I/F role code in WLC_E_IF event */ -+#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ -+#define WLC_E_IF_ROLE_AP 1 /* Access Point */ -+#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ -+#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ -+#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ -+ -+/* Reason codes for LINK */ -+#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ -+#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ -+#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ -+#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ -+ -+/* reason codes for WLC_E_OVERLAY_REQ event */ -+#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ -+#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _BCMEVENT_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmip.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmip.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmip.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmip.h 2017-11-09 17:53:43.989292000 +0800 -@@ -0,0 +1,205 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Fundamental constants relating to IP Protocol -+ * -+ * $Id: bcmip.h 324300 2012-03-28 20:29:37Z $ -+ */ -+ -+#ifndef _bcmip_h_ -+#define _bcmip_h_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+ -+/* IPV4 and IPV6 common */ -+#define IP_VER_OFFSET 0x0 /* offset to version field */ -+#define IP_VER_MASK 0xf0 /* version mask */ -+#define IP_VER_SHIFT 4 /* version shift */ -+#define IP_VER_4 4 /* version number for IPV4 */ -+#define IP_VER_6 6 /* version number for IPV6 */ -+ -+#define IP_VER(ip_body) \ -+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) -+ -+#define IP_PROT_ICMP 0x1 /* ICMP protocol */ -+#define IP_PROT_IGMP 0x2 /* IGMP protocol */ -+#define IP_PROT_TCP 0x6 /* TCP protocol */ -+#define IP_PROT_UDP 0x11 /* UDP protocol type */ -+#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ -+ -+/* IPV4 field offsets */ -+#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ -+#define IPV4_TOS_OFFSET 1 /* type of service offset */ -+#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ -+#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ -+#define IPV4_PROT_OFFSET 9 /* protocol type offset */ -+#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ -+#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ -+#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ -+#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ -+#define IPV4_MIN_HEADER_LEN 20 /* Minimum size for an IP header (no options) */ -+ -+/* IPV4 field decodes */ -+#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ -+#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ -+ -+#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ -+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) -+ -+#define IPV4_ADDR_LEN 4 /* IPV4 address length */ -+ -+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ -+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) -+ -+#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ -+ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) -+ -+#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ -+#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ -+ -+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) -+ -+#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ -+#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ -+ -+#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ -+#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ -+#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ -+ -+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) -+ -+#define IPV4_FRAG_RESV 0x8000 /* Reserved */ -+#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ -+#define IPV4_FRAG_MORE 0x2000 /* More fragments */ -+#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ -+ -+#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ -+ -+/* IPV4 packet formats */ -+BWL_PRE_PACKED_STRUCT struct ipv4_addr { -+ uint8 addr[IPV4_ADDR_LEN]; -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct ipv4_hdr { -+ uint8 version_ihl; /* Version and Internet Header Length */ -+ uint8 tos; /* Type Of Service */ -+ uint16 tot_len; /* Number of bytes in packet (max 65535) */ -+ uint16 id; -+ uint16 frag; /* 3 flag bits and fragment offset */ -+ uint8 ttl; /* Time To Live */ -+ uint8 prot; /* Protocol */ -+ uint16 hdr_chksum; /* IP header checksum */ -+ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ -+ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ -+} BWL_POST_PACKED_STRUCT; -+ -+/* IPV6 field offsets */ -+#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ -+#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ -+#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ -+#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ -+#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ -+ -+/* IPV6 field decodes */ -+#define IPV6_TRAFFIC_CLASS(ipv6_body) \ -+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ -+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) -+ -+#define IPV6_FLOW_LABEL(ipv6_body) \ -+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ -+ (((uint8 *)(ipv6_body))[2] << 8) | \ -+ (((uint8 *)(ipv6_body))[3])) -+ -+#define IPV6_PAYLOAD_LEN(ipv6_body) \ -+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ -+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) -+ -+#define IPV6_NEXT_HDR(ipv6_body) \ -+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) -+ -+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) -+ -+#define IPV6_ADDR_LEN 16 /* IPV6 address length */ -+ -+/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ -+#define IP_TOS46(ip_body) \ -+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ -+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) -+ -+/* IPV6 extension headers (options) */ -+#define IPV6_EXTHDR_HOP 0 -+#define IPV6_EXTHDR_ROUTING 43 -+#define IPV6_EXTHDR_FRAGMENT 44 -+#define IPV6_EXTHDR_AUTH 51 -+#define IPV6_EXTHDR_NONE 59 -+#define IPV6_EXTHDR_DEST 60 -+ -+#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ -+ ((prot) == IPV6_EXTHDR_ROUTING) || \ -+ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ -+ ((prot) == IPV6_EXTHDR_AUTH) || \ -+ ((prot) == IPV6_EXTHDR_NONE) || \ -+ ((prot) == IPV6_EXTHDR_DEST)) -+ -+#define IPV6_MIN_HLEN 40 -+ -+#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) -+ -+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { -+ uint8 nexthdr; -+ uint8 hdrlen; -+} BWL_POST_PACKED_STRUCT; -+ -+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { -+ uint8 nexthdr; -+ uint8 rsvd; -+ uint16 frag_off; -+ uint32 ident; -+} BWL_POST_PACKED_STRUCT; -+ -+static INLINE int32 -+ipv6_exthdr_len(uint8 *h, uint8 *proto) -+{ -+ uint16 len = 0, hlen; -+ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; -+ -+ while (IPV6_EXTHDR(eh->nexthdr)) { -+ if (eh->nexthdr == IPV6_EXTHDR_NONE) -+ return -1; -+ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) -+ hlen = 8; -+ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) -+ hlen = (eh->hdrlen + 2) << 2; -+ else -+ hlen = IPV6_EXTHDR_LEN(eh); -+ -+ len += hlen; -+ eh = (struct ipv6_exthdr *)(h + len); -+ } -+ -+ *proto = eh->nexthdr; -+ return len; -+} -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _bcmip_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmipv6.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmipv6.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmipv6.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/bcmipv6.h 2017-11-09 17:53:43.990289000 +0800 -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Fundamental constants relating to Neighbor Discovery Protocol -+ * -+ * $Id: bcmipv6.h 305568 2011-12-29 20:21:17Z $ -+ */ -+ -+#ifndef _bcmipv6_h_ -+#define _bcmipv6_h_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+#define ICMPV6_HEADER_TYPE 0x3A -+#define ICMPV6_PKT_TYPE_NS 135 -+#define ICMPV6_PKT_TYPE_NA 136 -+ -+#define ICMPV6_ND_OPT_TYPE_TARGET_MAC 2 -+#define ICMPV6_ND_OPT_TYPE_SRC_MAC 1 -+ -+#define IPV6_VERSION 6 -+#define IPV6_HOP_LIMIT 255 -+ -+#define IPV6_ADDR_NULL(a) ((a[0] | a[1] | a[2] | a[3] | a[4] | \ -+ a[5] | a[6] | a[7] | a[8] | a[9] | \ -+ a[10] | a[11] | a[12] | a[13] | \ -+ a[14] | a[15]) == 0) -+ -+/* IPV6 address */ -+BWL_PRE_PACKED_STRUCT struct ipv6_addr { -+ uint8 addr[16]; -+} BWL_POST_PACKED_STRUCT; -+ -+#ifndef IL_BIGENDIAN -+ -+/* ICMPV6 Header */ -+BWL_PRE_PACKED_STRUCT struct icmp6_hdr { -+ uint8 icmp6_type; -+ uint8 icmp6_code; -+ uint16 icmp6_cksum; -+ BWL_PRE_PACKED_STRUCT union { -+ uint32 reserved; -+ BWL_PRE_PACKED_STRUCT struct nd_advt { -+ uint32 reserved1:5, -+ override:1, -+ solicited:1, -+ router:1, -+ reserved2:24; -+ } BWL_POST_PACKED_STRUCT nd_advt; -+ } BWL_POST_PACKED_STRUCT opt; -+} BWL_POST_PACKED_STRUCT; -+ -+/* Ipv6 Header Format */ -+BWL_PRE_PACKED_STRUCT struct ipv6_hdr { -+ uint8 priority:4, -+ version:4; -+ uint8 flow_lbl[3]; -+ uint16 payload_len; -+ uint8 nexthdr; -+ uint8 hop_limit; -+ struct ipv6_addr saddr; -+ struct ipv6_addr daddr; -+} BWL_POST_PACKED_STRUCT; -+ -+/* Neighbor Advertisement/Solicitation Packet Structure */ -+BWL_PRE_PACKED_STRUCT struct nd_msg { -+ struct icmp6_hdr icmph; -+ struct ipv6_addr target; -+} BWL_POST_PACKED_STRUCT; -+ -+ -+/* Neighibor Solicitation/Advertisement Optional Structure */ -+BWL_PRE_PACKED_STRUCT struct nd_msg_opt { -+ uint8 type; -+ uint8 len; -+ uint8 mac_addr[ETHER_ADDR_LEN]; -+} BWL_POST_PACKED_STRUCT; -+ -+#endif /* IL_BIGENDIAN */ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* !defined(_bcmipv6_h_) */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/ethernet.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/ethernet.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/ethernet.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/ethernet.h 2017-11-09 17:53:43.991291000 +0800 -@@ -0,0 +1,202 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. -+ * -+ * $Id: ethernet.h 316696 2012-02-23 03:29:35Z $ -+ */ -+ -+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ -+#define _NET_ETHERNET_H_ -+ -+#ifndef _TYPEDEFS_H_ -+#include "typedefs.h" -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+ -+/* -+ * The number of bytes in an ethernet (MAC) address. -+ */ -+#define ETHER_ADDR_LEN 6 -+ -+/* -+ * The number of bytes in the type field. -+ */ -+#define ETHER_TYPE_LEN 2 -+ -+/* -+ * The number of bytes in the trailing CRC field. -+ */ -+#define ETHER_CRC_LEN 4 -+ -+/* -+ * The length of the combined header. -+ */ -+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) -+ -+/* -+ * The minimum packet length. -+ */ -+#define ETHER_MIN_LEN 64 -+ -+/* -+ * The minimum packet user data length. -+ */ -+#define ETHER_MIN_DATA 46 -+ -+/* -+ * The maximum packet length. -+ */ -+#define ETHER_MAX_LEN 1518 -+ -+/* -+ * The maximum packet user data length. -+ */ -+#define ETHER_MAX_DATA 1500 -+ -+/* ether types */ -+#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ -+#define ETHER_TYPE_IP 0x0800 /* IP */ -+#define ETHER_TYPE_ARP 0x0806 /* ARP */ -+#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ -+#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ -+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ -+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ -+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ -+#define ETHER_TYPE_WAI 0x88b4 /* WAI */ -+#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ -+ -+#define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */ -+ -+/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ -+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ -+ -+/* ether header */ -+#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ -+#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ -+#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ -+ -+/* -+ * A macro to validate a length with -+ */ -+#define ETHER_IS_VALID_LEN(foo) \ -+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) -+ -+#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ -+ ((uint8 *)ea)[0] = 0x01; \ -+ ((uint8 *)ea)[1] = 0x00; \ -+ ((uint8 *)ea)[2] = 0x5e; \ -+ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ -+ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ -+ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ -+} -+ -+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ -+/* -+ * Structure of a 10Mb/s Ethernet header. -+ */ -+BWL_PRE_PACKED_STRUCT struct ether_header { -+ uint8 ether_dhost[ETHER_ADDR_LEN]; -+ uint8 ether_shost[ETHER_ADDR_LEN]; -+ uint16 ether_type; -+} BWL_POST_PACKED_STRUCT; -+ -+/* -+ * Structure of a 48-bit Ethernet address. -+ */ -+BWL_PRE_PACKED_STRUCT struct ether_addr { -+ uint8 octet[ETHER_ADDR_LEN]; -+} BWL_POST_PACKED_STRUCT; -+#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ -+ -+/* -+ * Takes a pointer, set, test, clear, toggle locally admininistered -+ * address bit in the 48-bit Ethernet address. -+ */ -+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) -+#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) -+#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) -+#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) -+ -+/* Takes a pointer, marks unicast address bit in the MAC address */ -+#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) -+ -+/* -+ * Takes a pointer, returns true if a 48-bit multicast address -+ * (including broadcast, since it is all ones) -+ */ -+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) -+ -+/* Copy an ethernet address in reverse order */ -+#define ether_rcopy(s, d) \ -+do { \ -+ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ -+ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ -+ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ -+} while (0) -+ -+/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ -+#define eacmp(a, b) ((((uint16 *)(a))[0] ^ ((uint16 *)(b))[0]) | \ -+ (((uint16 *)(a))[1] ^ ((uint16 *)(b))[1]) | \ -+ (((uint16 *)(a))[2] ^ ((uint16 *)(b))[2])) -+ -+#define ether_cmp(a, b) eacmp(a, b) -+ -+/* copy an ethernet address - assumes the pointers can be referenced as shorts */ -+#define eacopy(s, d) \ -+do { \ -+ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ -+ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ -+ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ -+} while (0) -+ -+#define ether_copy(s, d) eacopy(s, d) -+ -+ -+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; -+static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; -+ -+#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \ -+ ((const uint8 *)(ea))[1] & \ -+ ((const uint8 *)(ea))[2] & \ -+ ((const uint8 *)(ea))[3] & \ -+ ((const uint8 *)(ea))[4] & \ -+ ((const uint8 *)(ea))[5]) == 0xff) -+#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \ -+ ((const uint8 *)(ea))[1] | \ -+ ((const uint8 *)(ea))[2] | \ -+ ((const uint8 *)(ea))[3] | \ -+ ((const uint8 *)(ea))[4] | \ -+ ((const uint8 *)(ea))[5]) == 0) -+ -+#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ -+ ((const uint16 *)(da))[1] | \ -+ ((const uint16 *)(da))[2]) == 0) -+ -+ -+#define ETHER_MOVE_HDR(d, s) \ -+do { \ -+ struct ether_header t; \ -+ t = *(struct ether_header *)(s); \ -+ *(struct ether_header *)(d) = t; \ -+} while (0) -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _NET_ETHERNET_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/vlan.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/vlan.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/vlan.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/vlan.h 2017-11-09 17:53:43.991302000 +0800 -@@ -0,0 +1,67 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * 802.1Q VLAN protocol definitions -+ * -+ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _vlan_h_ -+#define _vlan_h_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+#ifndef VLAN_VID_MASK -+#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ -+#endif -+#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ -+#define VLAN_PRI_SHIFT 13 /* user priority */ -+ -+#define VLAN_PRI_MASK 7 /* 3 bits of priority */ -+ -+#define VLAN_TCI_OFFSET 14 /* offset of tag ctrl info field */ -+ -+#define VLAN_TAG_LEN 4 -+#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ -+ -+#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ -+ -+struct ethervlan_header { -+ uint8 ether_dhost[ETHER_ADDR_LEN]; -+ uint8 ether_shost[ETHER_ADDR_LEN]; -+ uint16 vlan_type; /* 0x8100 */ -+ uint16 vlan_tag; /* priority, cfi and vid */ -+ uint16 ether_type; -+}; -+ -+#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) -+ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#define ETHERVLAN_MOVE_HDR(d, s) \ -+do { \ -+ struct ethervlan_header t; \ -+ t = *(struct ethervlan_header *)(s); \ -+ *(struct ethervlan_header *)(d) = t; \ -+} while (0) -+ -+#endif /* _vlan_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/proto/wpa.h b/drivers/net/ethernet/broadcom/gmac/src/include/proto/wpa.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/proto/wpa.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/proto/wpa.h 2017-11-09 17:53:43.992308000 +0800 -@@ -0,0 +1,169 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Fundamental types and constants relating to WPA -+ * -+ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ -+ */ -+ -+#ifndef _proto_wpa_h_ -+#define _proto_wpa_h_ -+ -+#include -+#include -+ -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+/* Reason Codes */ -+ -+/* 13 through 23 taken from IEEE Std 802.11i-2004 */ -+#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ -+#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ -+#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ -+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ -+#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from -+ * (re-)assoc. request/probe response -+ */ -+#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ -+#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ -+#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ -+#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ -+#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ -+#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ -+ -+#define WPA2_PMKID_LEN 16 -+ -+/* WPA IE fixed portion */ -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ uint8 tag; /* TAG */ -+ uint8 length; /* TAG length */ -+ uint8 oui[3]; /* IE OUI */ -+ uint8 oui_type; /* OUI type */ -+ BWL_PRE_PACKED_STRUCT struct { -+ uint8 low; -+ uint8 high; -+ } BWL_POST_PACKED_STRUCT version; /* IE version */ -+} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; -+#define WPA_IE_OUITYPE_LEN 4 -+#define WPA_IE_FIXED_LEN 8 -+#define WPA_IE_TAG_FIXED_LEN 6 -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ uint8 tag; /* TAG */ -+ uint8 length; /* TAG length */ -+ BWL_PRE_PACKED_STRUCT struct { -+ uint8 low; -+ uint8 high; -+ } BWL_POST_PACKED_STRUCT version; /* IE version */ -+} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; -+#define WPA_RSN_IE_FIXED_LEN 4 -+#define WPA_RSN_IE_TAG_FIXED_LEN 2 -+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; -+ -+/* WPA suite/multicast suite */ -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ uint8 oui[3]; -+ uint8 type; -+} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; -+#define WPA_SUITE_LEN 4 -+ -+/* WPA unicast suite list/key management suite list */ -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ BWL_PRE_PACKED_STRUCT struct { -+ uint8 low; -+ uint8 high; -+ } BWL_POST_PACKED_STRUCT count; -+ wpa_suite_t list[1]; -+} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; -+#define WPA_IE_SUITE_COUNT_LEN 2 -+typedef BWL_PRE_PACKED_STRUCT struct -+{ -+ BWL_PRE_PACKED_STRUCT struct { -+ uint8 low; -+ uint8 high; -+ } BWL_POST_PACKED_STRUCT count; -+ wpa_pmkid_t list[1]; -+} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; -+ -+/* WPA cipher suites */ -+#define WPA_CIPHER_NONE 0 /* None */ -+#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ -+#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ -+#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ -+#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ -+#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ -+#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ -+#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ -+ -+ -+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ -+ (cipher) == WPA_CIPHER_WEP_40 || \ -+ (cipher) == WPA_CIPHER_WEP_104 || \ -+ (cipher) == WPA_CIPHER_TKIP || \ -+ (cipher) == WPA_CIPHER_AES_OCB || \ -+ (cipher) == WPA_CIPHER_AES_CCM || \ -+ (cipher) == WPA_CIPHER_TPK) -+ -+ -+/* WPA TKIP countermeasures parameters */ -+#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ -+#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ -+ -+/* RSN IE defines */ -+#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ -+ -+/* RSN Capabilities defined in 802.11i */ -+#define RSN_CAP_PREAUTH 0x0001 -+#define RSN_CAP_NOPAIRWISE 0x0002 -+#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C -+#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 -+#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 -+#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 -+#define RSN_CAP_1_REPLAY_CNTR 0 -+#define RSN_CAP_2_REPLAY_CNTRS 1 -+#define RSN_CAP_4_REPLAY_CNTRS 2 -+#define RSN_CAP_16_REPLAY_CNTRS 3 -+#ifdef MFP -+#define RSN_CAP_MFPR 0x0040 -+#define RSN_CAP_MFPC 0x0080 -+#endif -+ -+/* WPA capabilities defined in 802.11i */ -+#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS -+#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS -+#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT -+#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK -+ -+/* WPA capabilities defined in 802.11zD9.0 */ -+#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ -+ -+/* WPA Specific defines */ -+#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ -+#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ -+ -+#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH -+ -+#define WPA2_PMKID_COUNT_LEN 2 -+ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _proto_wpa_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sbchipc.h b/drivers/net/ethernet/broadcom/gmac/src/include/sbchipc.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sbchipc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sbchipc.h 2017-11-09 17:53:44.004291000 +0800 -@@ -0,0 +1,2515 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * SiliconBackplane Chipcommon core hardware definitions. -+ * -+ * The chipcommon core provides chip identification, SB control, -+ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, -+ * GPIO interface, extbus, and support for serial and parallel flashes. -+ * -+ * $Id: sbchipc.h 328955 2012-04-23 09:06:12Z $ -+ */ -+ -+#ifndef _SBCHIPC_H -+#define _SBCHIPC_H -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+typedef struct eci_prerev35 { -+ uint32 eci_output; -+ uint32 eci_control; -+ uint32 eci_inputlo; -+ uint32 eci_inputmi; -+ uint32 eci_inputhi; -+ uint32 eci_inputintpolaritylo; -+ uint32 eci_inputintpolaritymi; -+ uint32 eci_inputintpolarityhi; -+ uint32 eci_intmasklo; -+ uint32 eci_intmaskmi; -+ uint32 eci_intmaskhi; -+ uint32 eci_eventlo; -+ uint32 eci_eventmi; -+ uint32 eci_eventhi; -+ uint32 eci_eventmasklo; -+ uint32 eci_eventmaskmi; -+ uint32 eci_eventmaskhi; -+ uint32 PAD[3]; -+} eci_prerev35_t; -+ -+typedef struct eci_rev35 { -+ uint32 eci_outputlo; -+ uint32 eci_outputhi; -+ uint32 eci_controllo; -+ uint32 eci_controlhi; -+ uint32 eci_inputlo; -+ uint32 eci_inputhi; -+ uint32 eci_inputintpolaritylo; -+ uint32 eci_inputintpolarityhi; -+ uint32 eci_intmasklo; -+ uint32 eci_intmaskhi; -+ uint32 eci_eventlo; -+ uint32 eci_eventhi; -+ uint32 eci_eventmasklo; -+ uint32 eci_eventmaskhi; -+ uint32 eci_auxtx; -+ uint32 eci_auxrx; -+ uint32 eci_datatag; -+ uint32 eci_uartescvalue; -+ uint32 eci_autobaudctr; -+ uint32 eci_uartfifolevel; -+} eci_rev35_t; -+ -+typedef struct flash_config { -+ uint32 PAD[19]; -+ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */ -+ uint32 flashstrconfig; -+} flash_config_t; -+ -+typedef volatile struct { -+ uint32 chipid; /* 0x0 */ -+ uint32 capabilities; -+ uint32 corecontrol; /* corerev >= 1 */ -+ uint32 bist; -+ -+ /* OTP */ -+ uint32 otpstatus; /* 0x10, corerev >= 10 */ -+ uint32 otpcontrol; -+ uint32 otpprog; -+ uint32 otplayout; /* corerev >= 23 */ -+ -+ /* Interrupt control */ -+ uint32 intstatus; /* 0x20 */ -+ uint32 intmask; -+ -+ /* Chip specific regs */ -+ uint32 chipcontrol; /* 0x28, rev >= 11 */ -+ uint32 chipstatus; /* 0x2c, rev >= 11 */ -+ -+ /* Jtag Master */ -+ uint32 jtagcmd; /* 0x30, rev >= 10 */ -+ uint32 jtagir; -+ uint32 jtagdr; -+ uint32 jtagctrl; -+ -+ /* serial flash interface registers */ -+ uint32 flashcontrol; /* 0x40 */ -+ uint32 flashaddress; -+ uint32 flashdata; -+ uint32 otplayoutextension; /* rev >= 35 */ -+ -+ /* Silicon backplane configuration broadcast control */ -+ uint32 broadcastaddress; /* 0x50 */ -+ uint32 broadcastdata; -+ -+ /* gpio - cleared only by power-on-reset */ -+ uint32 gpiopullup; /* 0x58, corerev >= 20 */ -+ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ -+ uint32 gpioin; /* 0x60 */ -+ uint32 gpioout; /* 0x64 */ -+ uint32 gpioouten; /* 0x68 */ -+ uint32 gpiocontrol; /* 0x6C */ -+ uint32 gpiointpolarity; /* 0x70 */ -+ uint32 gpiointmask; /* 0x74 */ -+ -+ /* GPIO events corerev >= 11 */ -+ uint32 gpioevent; -+ uint32 gpioeventintmask; -+ -+ /* Watchdog timer */ -+ uint32 watchdog; /* 0x80 */ -+ -+ /* GPIO events corerev >= 11 */ -+ uint32 gpioeventintpolarity; -+ -+ /* GPIO based LED powersave registers corerev >= 16 */ -+ uint32 gpiotimerval; /* 0x88 */ -+ uint32 gpiotimeroutmask; -+ -+ /* clock control */ -+ uint32 clockcontrol_n; /* 0x90 */ -+ uint32 clockcontrol_sb; /* aka m0 */ -+ uint32 clockcontrol_pci; /* aka m1 */ -+ uint32 clockcontrol_m2; /* mii/uart/mipsref */ -+ uint32 clockcontrol_m3; /* cpu */ -+ uint32 clkdiv; /* corerev >= 3 */ -+ uint32 gpiodebugsel; /* corerev >= 28 */ -+ uint32 capabilities_ext; /* 0xac */ -+ -+ /* pll delay registers (corerev >= 4) */ -+ uint32 pll_on_delay; /* 0xb0 */ -+ uint32 fref_sel_delay; -+ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ -+ uint32 PAD; -+ -+ /* Instaclock registers (corerev >= 10) */ -+ uint32 system_clk_ctl; /* 0xc0 */ -+ uint32 clkstatestretch; -+ uint32 PAD[2]; -+ -+ /* Indirect backplane access (corerev >= 22) */ -+ uint32 bp_addrlow; /* 0xd0 */ -+ uint32 bp_addrhigh; -+ uint32 bp_data; -+ uint32 PAD; -+ uint32 bp_indaccess; -+ /* SPI registers, corerev >= 37 */ -+ uint32 gsioctrl; -+ uint32 gsioaddress; -+ uint32 gsiodata; -+ -+ /* More clock dividers (corerev >= 32) */ -+ uint32 clkdiv2; -+ /* FAB ID (corerev >= 40) */ -+ uint32 otpcontrol1; -+ uint32 fabid; /* 0xf8 */ -+ -+ /* In AI chips, pointer to erom */ -+ uint32 eromptr; /* 0xfc */ -+ -+ /* ExtBus control registers (corerev >= 3) */ -+ uint32 pcmcia_config; /* 0x100 */ -+ uint32 pcmcia_memwait; -+ uint32 pcmcia_attrwait; -+ uint32 pcmcia_iowait; -+ uint32 ide_config; -+ uint32 ide_memwait; -+ uint32 ide_attrwait; -+ uint32 ide_iowait; -+ uint32 prog_config; -+ uint32 prog_waitcount; -+ uint32 flash_config; -+ uint32 flash_waitcount; -+ uint32 SECI_config; /* 0x130 SECI configuration */ -+ uint32 SECI_status; -+ uint32 SECI_statusmask; -+ uint32 SECI_rxnibchanged; -+ -+ union { /* 0x140 */ -+ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ -+ struct eci_prerev35 lt35; -+ struct eci_rev35 ge35; -+ /* Other interfaces */ -+ struct flash_config flashconf; -+ uint32 PAD[20]; -+ } eci; -+ -+ /* SROM interface (corerev >= 32) */ -+ uint32 sromcontrol; /* 0x190 */ -+ uint32 sromaddress; -+ uint32 sromdata; -+ uint32 PAD[1]; /* 0x19C */ -+ /* NAND flash registers for BCM4706 (corerev = 31) */ -+ uint32 nflashctrl; /* 0x1a0 */ -+ uint32 nflashconf; -+ uint32 nflashcoladdr; -+ uint32 nflashrowaddr; -+ uint32 nflashdata; -+ uint32 nflashwaitcnt0; /* 0x1b4 */ -+ uint32 PAD[2]; -+ -+ uint32 seci_uart_data; /* 0x1C0 */ -+ uint32 seci_uart_bauddiv; -+ uint32 seci_uart_fcr; -+ uint32 seci_uart_lcr; -+ uint32 seci_uart_mcr; -+ uint32 seci_uart_lsr; -+ uint32 seci_uart_msr; -+ uint32 seci_uart_baudadj; -+ /* Clock control and hardware workarounds (corerev >= 20) */ -+ uint32 clk_ctl_st; /* 0x1e0 */ -+ uint32 hw_war; -+ uint32 PAD[70]; -+ -+ /* UARTs */ -+ uint8 uart0data; /* 0x300 */ -+ uint8 uart0imr; -+ uint8 uart0fcr; -+ uint8 uart0lcr; -+ uint8 uart0mcr; -+ uint8 uart0lsr; -+ uint8 uart0msr; -+ uint8 uart0scratch; -+ uint8 PAD[248]; /* corerev >= 1 */ -+ -+ uint8 uart1data; /* 0x400 */ -+ uint8 uart1imr; -+ uint8 uart1fcr; -+ uint8 uart1lcr; -+ uint8 uart1mcr; -+ uint8 uart1lsr; -+ uint8 uart1msr; -+ uint8 uart1scratch; -+ uint32 PAD[126]; -+ -+ /* PMU registers (corerev >= 20) */ -+ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP. -+ * The CPU must read them twice, compare, and retry if different. -+ */ -+ uint32 pmucontrol; /* 0x600 */ -+ uint32 pmucapabilities; -+ uint32 pmustatus; -+ uint32 res_state; -+ uint32 res_pending; -+ uint32 pmutimer; -+ uint32 min_res_mask; -+ uint32 max_res_mask; -+ uint32 res_table_sel; -+ uint32 res_dep_mask; -+ uint32 res_updn_timer; -+ uint32 res_timer; -+ uint32 clkstretch; -+ uint32 pmuwatchdog; -+ uint32 gpiosel; /* 0x638, rev >= 1 */ -+ uint32 gpioenable; /* 0x63c, rev >= 1 */ -+ uint32 res_req_timer_sel; -+ uint32 res_req_timer; -+ uint32 res_req_mask; -+ uint32 PAD; -+ uint32 chipcontrol_addr; /* 0x650 */ -+ uint32 chipcontrol_data; /* 0x654 */ -+ uint32 regcontrol_addr; -+ uint32 regcontrol_data; -+ uint32 pllcontrol_addr; -+ uint32 pllcontrol_data; -+ uint32 pmustrapopt; /* 0x668, corerev >= 28 */ -+ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ -+ uint32 PAD[100]; -+ uint16 sromotp[512]; /* 0x800 */ -+#ifdef NFLASH_SUPPORT -+ /* Nand flash MLC controller registers (corerev >= 38) */ -+ uint32 nand_revision; /* 0xC00 */ -+ uint32 nand_cmd_start; -+ uint32 nand_cmd_addr_x; -+ uint32 nand_cmd_addr; -+ uint32 nand_cmd_end_addr; -+ uint32 nand_cs_nand_select; -+ uint32 nand_cs_nand_xor; -+ uint32 PAD; -+ uint32 nand_spare_rd0; -+ uint32 nand_spare_rd4; -+ uint32 nand_spare_rd8; -+ uint32 nand_spare_rd12; -+ uint32 nand_spare_wr0; -+ uint32 nand_spare_wr4; -+ uint32 nand_spare_wr8; -+ uint32 nand_spare_wr12; -+ uint32 nand_acc_control; -+ uint32 PAD; -+ uint32 nand_config; -+ uint32 PAD; -+ uint32 nand_timing_1; -+ uint32 nand_timing_2; -+ uint32 nand_semaphore; -+ uint32 PAD; -+ uint32 nand_devid; -+ uint32 nand_devid_x; -+ uint32 nand_block_lock_status; -+ uint32 nand_intfc_status; -+ uint32 nand_ecc_corr_addr_x; -+ uint32 nand_ecc_corr_addr; -+ uint32 nand_ecc_unc_addr_x; -+ uint32 nand_ecc_unc_addr; -+ uint32 nand_read_error_count; -+ uint32 nand_corr_stat_threshold; -+ uint32 PAD[2]; -+ uint32 nand_read_addr_x; -+ uint32 nand_read_addr; -+ uint32 nand_page_program_addr_x; -+ uint32 nand_page_program_addr; -+ uint32 nand_copy_back_addr_x; -+ uint32 nand_copy_back_addr; -+ uint32 nand_block_erase_addr_x; -+ uint32 nand_block_erase_addr; -+ uint32 nand_inv_read_addr_x; -+ uint32 nand_inv_read_addr; -+ uint32 PAD[2]; -+ uint32 nand_blk_wr_protect; -+ uint32 PAD[3]; -+ uint32 nand_acc_control_cs1; -+ uint32 nand_config_cs1; -+ uint32 nand_timing_1_cs1; -+ uint32 nand_timing_2_cs1; -+ uint32 PAD[20]; -+ uint32 nand_spare_rd16; -+ uint32 nand_spare_rd20; -+ uint32 nand_spare_rd24; -+ uint32 nand_spare_rd28; -+ uint32 nand_cache_addr; -+ uint32 nand_cache_data; -+ uint32 nand_ctrl_config; -+ uint32 nand_ctrl_status; -+#endif /* NFLASH_SUPPORT */ -+ uint32 gci_corecaps0; /* GCI starting at 0xC00 */ -+ uint32 gci_corecaps1; -+ uint32 gci_corecaps2; -+ uint32 gci_corectrl; -+ uint32 gci_corestat; /* 0xC10 */ -+ uint32 PAD[11]; -+ uint32 gci_indirect_addr; /* 0xC40 */ -+ uint32 PAD[111]; -+ uint32 gci_chipctrl; /* 0xE00 */ -+} chipcregs_t; -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+#if defined(IL_BIGENDIAN) && defined(BCMHND74K) -+/* Selective swapped defines for those registers we need in -+ * big-endian code. -+ */ -+#define CC_CHIPID 4 -+#define CC_CAPABILITIES 0 -+#define CC_CHIPST 0x28 -+#define CC_EROMPTR 0xf8 -+ -+#else /* !IL_BIGENDIAN || !BCMHND74K */ -+ -+#define CC_CHIPID 0 -+#define CC_CAPABILITIES 4 -+#define CC_CHIPST 0x2c -+#define CC_EROMPTR 0xfc -+ -+#endif /* IL_BIGENDIAN && BCMHND74K */ -+ -+#define CC_OTPST 0x10 -+#define CC_JTAGCMD 0x30 -+#define CC_JTAGIR 0x34 -+#define CC_JTAGDR 0x38 -+#define CC_JTAGCTRL 0x3c -+#define CC_GPIOPU 0x58 -+#define CC_GPIOPD 0x5c -+#define CC_GPIOIN 0x60 -+#define CC_GPIOOUT 0x64 -+#define CC_GPIOOUTEN 0x68 -+#define CC_GPIOCTRL 0x6c -+#define CC_GPIOPOL 0x70 -+#define CC_GPIOINTM 0x74 -+#define CC_WATCHDOG 0x80 -+#define CC_CLKC_N 0x90 -+#define CC_CLKC_M0 0x94 -+#define CC_CLKC_M1 0x98 -+#define CC_CLKC_M2 0x9c -+#define CC_CLKC_M3 0xa0 -+#define CC_CLKDIV 0xa4 -+#define CC_SYS_CLK_CTL 0xc0 -+#define CC_CLK_CTL_ST SI_CLK_CTL_ST -+#define PMU_CTL 0x600 -+#define PMU_CAP 0x604 -+#define PMU_ST 0x608 -+#define PMU_RES_STATE 0x60c -+#define PMU_TIMER 0x614 -+#define PMU_MIN_RES_MASK 0x618 -+#define PMU_MAX_RES_MASK 0x61c -+#define CC_CHIPCTL_ADDR 0x650 -+#define CC_CHIPCTL_DATA 0x654 -+#define PMU_REG_CONTROL_ADDR 0x658 -+#define PMU_REG_CONTROL_DATA 0x65C -+#define PMU_PLL_CONTROL_ADDR 0x660 -+#define PMU_PLL_CONTROL_DATA 0x664 -+#define CC_SROM_CTRL 0x190 -+#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ -+#define CC_GCI_INDIRECT_ADDR_REG 0xC40 -+#define CC_GCI_CHIP_CTRL_REG 0xE00 -+#define CC_GCI_CC_OFFSET_2 2 -+#define CC_GCI_CC_OFFSET_5 5 -+ -+#ifdef NFLASH_SUPPORT -+/* NAND flash support */ -+#define CC_NAND_REVISION 0xC00 -+#define CC_NAND_CMD_START 0xC04 -+#define CC_NAND_CMD_ADDR 0xC0C -+#define CC_NAND_SPARE_RD_0 0xC20 -+#define CC_NAND_SPARE_RD_4 0xC24 -+#define CC_NAND_SPARE_RD_8 0xC28 -+#define CC_NAND_SPARE_RD_C 0xC2C -+#define CC_NAND_CONFIG 0xC48 -+#define CC_NAND_DEVID 0xC60 -+#define CC_NAND_DEVID_EXT 0xC64 -+#define CC_NAND_INTFC_STATUS 0xC6C -+#endif /* NFLASH_SUPPORT */ -+ -+/* chipid */ -+#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ -+#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ -+#define CID_REV_SHIFT 16 /* Chip Revision shift */ -+#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ -+#define CID_PKG_SHIFT 20 /* Package Option shift */ -+#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ -+#define CID_CC_SHIFT 24 -+#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ -+#define CID_TYPE_SHIFT 28 -+ -+/* capabilities */ -+#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ -+#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ -+#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -+#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ -+#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ -+#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ -+#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ -+#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ -+#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ -+#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ -+#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ -+#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ -+#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ -+#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ -+#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ -+#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ -+#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ -+#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ -+#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ -+#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ -+#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ -+#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ -+ -+#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ -+#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ -+ -+/* capabilities extension */ -+#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ -+ -+/* PLL type */ -+#define PLL_NONE 0x00000000 -+#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ -+#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */ -+#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */ -+#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */ -+#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */ -+#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ -+#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */ -+ -+/* ILP clock */ -+#define ILP_CLOCK 32000 -+ -+/* ALP clock on pre-PMU chips */ -+#define ALP_CLOCK 20000000 -+#define NS_ALP_CLOCK 125000000 -+#define NS_SLOW_ALP_CLOCK 100000000 -+#define NS_CPU_CLOCK 1000000000 -+#define NS_SLOW_CPU_CLOCK 800000000 -+#define NS_SI_CLOCK 250000000 -+#define NS_SLOW_SI_CLOCK 200000000 -+#define NS_FAST_MEM_CLOCK 800000000 -+#define NS_MEM_CLOCK 533000000 -+#define NS_SLOW_MEM_CLOCK 400000000 -+ -+/* HT clock */ -+#define HT_CLOCK 80000000 -+ -+/* corecontrol */ -+#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ -+#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ -+#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */ -+#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ -+ -+/* 4321 chipcontrol */ -+#define CHIPCTRL_4321A0_DEFAULT 0x3a4 -+#define CHIPCTRL_4321A1_DEFAULT 0x0a4 -+#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ -+ -+/* Fields in the otpstatus register in rev >= 21 */ -+#define OTPS_OL_MASK 0x000000ff -+#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ -+#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ -+#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ -+#define OTPS_OL_GU 0x00000008 /* general use region is locked */ -+#define OTPS_GUP_MASK 0x00000f00 -+#define OTPS_GUP_SHIFT 8 -+#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ -+#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ -+#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ -+#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ -+#define OTPS_READY 0x00001000 -+#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */ -+#define OTPS_RV_MASK 0x0fff0000 -+#define OTPS_PROGOK 0x40000000 -+ -+/* Fields in the otpcontrol register in rev >= 21 */ -+#define OTPC_PROGSEL 0x00000001 -+#define OTPC_PCOUNT_MASK 0x0000000e -+#define OTPC_PCOUNT_SHIFT 1 -+#define OTPC_VSEL_MASK 0x000000f0 -+#define OTPC_VSEL_SHIFT 4 -+#define OTPC_TMM_MASK 0x00000700 -+#define OTPC_TMM_SHIFT 8 -+#define OTPC_ODM 0x00000800 -+#define OTPC_PROGEN 0x80000000 -+ -+/* Fields in the 40nm otpcontrol register in rev >= 40 */ -+#define OTPC_40NM_PROGSEL_SHIFT 0 -+#define OTPC_40NM_PCOUNT_SHIFT 1 -+#define OTPC_40NM_PCOUNT_WR 0xA -+#define OTPC_40NM_PCOUNT_V1X 0xB -+#define OTPC_40NM_REGCSEL_SHIFT 5 -+#define OTPC_40NM_REGCSEL_DEF 0x4 -+#define OTPC_40NM_PROGIN_SHIFT 8 -+#define OTPC_40NM_R2X_SHIFT 10 -+#define OTPC_40NM_ODM_SHIFT 11 -+#define OTPC_40NM_DF_SHIFT 15 -+#define OTPC_40NM_VSEL_SHIFT 16 -+#define OTPC_40NM_VSEL_WR 0xA -+#define OTPC_40NM_VSEL_V1X 0xA -+#define OTPC_40NM_VSEL_R1X 0x5 -+#define OTPC_40NM_COFAIL_SHIFT 30 -+ -+#define OTPC1_CPCSEL_SHIFT 0 -+#define OTPC1_CPCSEL_DEF 6 -+#define OTPC1_TM_SHIFT 8 -+#define OTPC1_TM_WR 0x84 -+#define OTPC1_TM_V1X 0x84 -+#define OTPC1_TM_R1X 0x4 -+ -+/* Fields in otpprog in rev >= 21 and HND OTP */ -+#define OTPP_COL_MASK 0x000000ff -+#define OTPP_COL_SHIFT 0 -+#define OTPP_ROW_MASK 0x0000ff00 -+#define OTPP_ROW_SHIFT 8 -+#define OTPP_OC_MASK 0x0f000000 -+#define OTPP_OC_SHIFT 24 -+#define OTPP_READERR 0x10000000 -+#define OTPP_VALUE_MASK 0x20000000 -+#define OTPP_VALUE_SHIFT 29 -+#define OTPP_START_BUSY 0x80000000 -+#define OTPP_READ 0x40000000 /* HND OTP */ -+ -+/* Fields in otplayout register */ -+#define OTPL_HWRGN_OFF_MASK 0x00000FFF -+#define OTPL_HWRGN_OFF_SHIFT 0 -+#define OTPL_WRAP_REVID_MASK 0x00F80000 -+#define OTPL_WRAP_REVID_SHIFT 19 -+#define OTPL_WRAP_TYPE_MASK 0x00070000 -+#define OTPL_WRAP_TYPE_SHIFT 16 -+#define OTPL_WRAP_TYPE_65NM 0 -+#define OTPL_WRAP_TYPE_40NM 1 -+ -+/* otplayout reg corerev >= 36 */ -+#define OTP_CISFORMAT_NEW 0x80000000 -+ -+/* Opcodes for OTPP_OC field */ -+#define OTPPOC_READ 0 -+#define OTPPOC_BIT_PROG 1 -+#define OTPPOC_VERIFY 3 -+#define OTPPOC_INIT 4 -+#define OTPPOC_SET 5 -+#define OTPPOC_RESET 6 -+#define OTPPOC_OCST 7 -+#define OTPPOC_ROW_LOCK 8 -+#define OTPPOC_PRESCN_TEST 9 -+ -+/* Opcodes for OTPP_OC field (40NM) */ -+#define OTPPOC_READ_40NM 0 -+#define OTPPOC_PROG_ENABLE_40NM 1 -+#define OTPPOC_PROG_DISABLE_40NM 2 -+#define OTPPOC_VERIFY_40NM 3 -+#define OTPPOC_WORD_VERIFY_1_40NM 4 -+#define OTPPOC_ROW_LOCK_40NM 5 -+#define OTPPOC_STBY_40NM 6 -+#define OTPPOC_WAKEUP_40NM 7 -+#define OTPPOC_WORD_VERIFY_0_40NM 8 -+#define OTPPOC_PRESCN_TEST_40NM 9 -+#define OTPPOC_BIT_PROG_40NM 10 -+#define OTPPOC_WORDPROG_40NM 11 -+#define OTPPOC_BURNIN_40NM 12 -+#define OTPPOC_AUTORELOAD_40NM 13 -+#define OTPPOC_OVST_READ_40NM 14 -+#define OTPPOC_OVST_PROG_40NM 15 -+ -+/* Fields in otplayoutextension */ -+#define OTPLAYOUTEXT_FUSE_MASK 0x3FF -+ -+ -+/* Jtagm characteristics that appeared at a given corerev */ -+#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */ -+#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */ -+#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */ -+ -+/* jtagcmd */ -+#define JCMD_START 0x80000000 -+#define JCMD_BUSY 0x80000000 -+#define JCMD_STATE_MASK 0x60000000 -+#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */ -+#define JCMD_STATE_PIR 0x20000000 /* Pause IR */ -+#define JCMD_STATE_PDR 0x40000000 /* Pause DR */ -+#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */ -+#define JCMD0_ACC_MASK 0x0000f000 -+#define JCMD0_ACC_IRDR 0x00000000 -+#define JCMD0_ACC_DR 0x00001000 -+#define JCMD0_ACC_IR 0x00002000 -+#define JCMD0_ACC_RESET 0x00003000 -+#define JCMD0_ACC_IRPDR 0x00004000 -+#define JCMD0_ACC_PDR 0x00005000 -+#define JCMD0_IRW_MASK 0x00000f00 -+#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ -+#define JCMD_ACC_IRDR 0x00000000 -+#define JCMD_ACC_DR 0x00010000 -+#define JCMD_ACC_IR 0x00020000 -+#define JCMD_ACC_RESET 0x00030000 -+#define JCMD_ACC_IRPDR 0x00040000 -+#define JCMD_ACC_PDR 0x00050000 -+#define JCMD_ACC_PIR 0x00060000 -+#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */ -+#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */ -+#define JCMD_IRW_MASK 0x00001f00 -+#define JCMD_IRW_SHIFT 8 -+#define JCMD_DRW_MASK 0x0000003f -+ -+/* jtagctrl */ -+#define JCTRL_FORCE_CLK 4 /* Force clock */ -+#define JCTRL_EXT_EN 2 /* Enable external targets */ -+#define JCTRL_EN 1 /* Enable Jtag master */ -+ -+/* Fields in clkdiv */ -+#define CLKD_SFLASH 0x0f000000 -+#define CLKD_SFLASH_SHIFT 24 -+#define CLKD_OTP 0x000f0000 -+#define CLKD_OTP_SHIFT 16 -+#define CLKD_JTAG 0x00000f00 -+#define CLKD_JTAG_SHIFT 8 -+#define CLKD_UART 0x000000ff -+ -+#define CLKD2_SROM 0x00000003 -+ -+/* intstatus/intmask */ -+#define CI_GPIO 0x00000001 /* gpio intr */ -+#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ -+#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ -+#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ -+#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ -+#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ -+#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ -+#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ -+ -+/* slow_clk_ctl */ -+#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ -+#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ -+#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ -+#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ -+#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ -+#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, -+ * 0: LPO is enabled -+ */ -+#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, -+ * 0: power logic control -+ */ -+#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors -+ * PLL clock disable requests from core -+ */ -+#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't -+ * disable crystal when appropriate -+ */ -+#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ -+#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ -+#define SCC_CD_SHIFT 16 -+ -+/* system_clk_ctl */ -+#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ -+#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ -+#define SYCC_FP 0x00000004 /* ForcePLLOn */ -+#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ -+#define SYCC_HR 0x00000010 /* Force HT */ -+#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ -+#define SYCC_CD_SHIFT 16 -+ -+/* Indirect backplane access */ -+#define BPIA_BYTEEN 0x0000000f -+#define BPIA_SZ1 0x00000001 -+#define BPIA_SZ2 0x00000003 -+#define BPIA_SZ4 0x00000007 -+#define BPIA_SZ8 0x0000000f -+#define BPIA_WRITE 0x00000100 -+#define BPIA_START 0x00000200 -+#define BPIA_BUSY 0x00000200 -+#define BPIA_ERROR 0x00000400 -+ -+/* pcmcia/prog/flash_config */ -+#define CF_EN 0x00000001 /* enable */ -+#define CF_EM_MASK 0x0000000e /* mode */ -+#define CF_EM_SHIFT 1 -+#define CF_EM_FLASH 0 /* flash/asynchronous mode */ -+#define CF_EM_SYNC 2 /* synchronous mode */ -+#define CF_EM_PCMCIA 4 /* pcmcia mode */ -+#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */ -+#define CF_BS 0x00000020 /* byteswap */ -+#define CF_CD_MASK 0x000000c0 /* clock divider */ -+#define CF_CD_SHIFT 6 -+#define CF_CD_DIV2 0x00000000 /* backplane/2 */ -+#define CF_CD_DIV3 0x00000040 /* backplane/3 */ -+#define CF_CD_DIV4 0x00000080 /* backplane/4 */ -+#define CF_CE 0x00000100 /* clock enable */ -+#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */ -+ -+/* pcmcia_memwait */ -+#define PM_W0_MASK 0x0000003f /* waitcount0 */ -+#define PM_W1_MASK 0x00001f00 /* waitcount1 */ -+#define PM_W1_SHIFT 8 -+#define PM_W2_MASK 0x001f0000 /* waitcount2 */ -+#define PM_W2_SHIFT 16 -+#define PM_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PM_W3_SHIFT 24 -+ -+/* pcmcia_attrwait */ -+#define PA_W0_MASK 0x0000003f /* waitcount0 */ -+#define PA_W1_MASK 0x00001f00 /* waitcount1 */ -+#define PA_W1_SHIFT 8 -+#define PA_W2_MASK 0x001f0000 /* waitcount2 */ -+#define PA_W2_SHIFT 16 -+#define PA_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PA_W3_SHIFT 24 -+ -+/* pcmcia_iowait */ -+#define PI_W0_MASK 0x0000003f /* waitcount0 */ -+#define PI_W1_MASK 0x00001f00 /* waitcount1 */ -+#define PI_W1_SHIFT 8 -+#define PI_W2_MASK 0x001f0000 /* waitcount2 */ -+#define PI_W2_SHIFT 16 -+#define PI_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PI_W3_SHIFT 24 -+ -+/* prog_waitcount */ -+#define PW_W0_MASK 0x0000001f /* waitcount0 */ -+#define PW_W1_MASK 0x00001f00 /* waitcount1 */ -+#define PW_W1_SHIFT 8 -+#define PW_W2_MASK 0x001f0000 /* waitcount2 */ -+#define PW_W2_SHIFT 16 -+#define PW_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PW_W3_SHIFT 24 -+ -+#define PW_W0 0x0000000c -+#define PW_W1 0x00000a00 -+#define PW_W2 0x00020000 -+#define PW_W3 0x01000000 -+ -+/* flash_waitcount */ -+#define FW_W0_MASK 0x0000003f /* waitcount0 */ -+#define FW_W1_MASK 0x00001f00 /* waitcount1 */ -+#define FW_W1_SHIFT 8 -+#define FW_W2_MASK 0x001f0000 /* waitcount2 */ -+#define FW_W2_SHIFT 16 -+#define FW_W3_MASK 0x1f000000 /* waitcount3 */ -+#define FW_W3_SHIFT 24 -+ -+/* When Srom support present, fields in sromcontrol */ -+#define SRC_START 0x80000000 -+#define SRC_BUSY 0x80000000 -+#define SRC_OPCODE 0x60000000 -+#define SRC_OP_READ 0x00000000 -+#define SRC_OP_WRITE 0x20000000 -+#define SRC_OP_WRDIS 0x40000000 -+#define SRC_OP_WREN 0x60000000 -+#define SRC_OTPSEL 0x00000010 -+#define SRC_LOCK 0x00000008 -+#define SRC_SIZE_MASK 0x00000006 -+#define SRC_SIZE_1K 0x00000000 -+#define SRC_SIZE_4K 0x00000002 -+#define SRC_SIZE_16K 0x00000004 -+#define SRC_SIZE_SHIFT 1 -+#define SRC_PRESENT 0x00000001 -+ -+/* Fields in pmucontrol */ -+#define PCTL_ILP_DIV_MASK 0xffff0000 -+#define PCTL_ILP_DIV_SHIFT 16 -+#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ -+#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ -+#define PCTL_HT_REQ_EN 0x00000100 -+#define PCTL_ALP_REQ_EN 0x00000080 -+#define PCTL_XTALFREQ_MASK 0x0000007c -+#define PCTL_XTALFREQ_SHIFT 2 -+#define PCTL_ILP_DIV_EN 0x00000002 -+#define PCTL_LPO_SEL 0x00000001 -+ -+/* Fields in clkstretch */ -+#define CSTRETCH_HT 0xffff0000 -+#define CSTRETCH_ALP 0x0000ffff -+ -+/* gpiotimerval */ -+#define GPIO_ONTIME_SHIFT 16 -+ -+/* clockcontrol_n */ -+#define CN_N1_MASK 0x3f /* n1 control */ -+#define CN_N2_MASK 0x3f00 /* n2 control */ -+#define CN_N2_SHIFT 8 -+#define CN_PLLC_MASK 0xf0000 /* pll control */ -+#define CN_PLLC_SHIFT 16 -+ -+/* clockcontrol_sb/pci/uart */ -+#define CC_M1_MASK 0x3f /* m1 control */ -+#define CC_M2_MASK 0x3f00 /* m2 control */ -+#define CC_M2_SHIFT 8 -+#define CC_M3_MASK 0x3f0000 /* m3 control */ -+#define CC_M3_SHIFT 16 -+#define CC_MC_MASK 0x1f000000 /* mux control */ -+#define CC_MC_SHIFT 24 -+ -+/* N3M Clock control magic field values */ -+#define CC_F6_2 0x02 /* A factor of 2 in */ -+#define CC_F6_3 0x03 /* 6-bit fields like */ -+#define CC_F6_4 0x05 /* N1, M1 or M3 */ -+#define CC_F6_5 0x09 -+#define CC_F6_6 0x11 -+#define CC_F6_7 0x21 -+ -+#define CC_F5_BIAS 5 /* 5-bit fields get this added */ -+ -+#define CC_MC_BYPASS 0x08 -+#define CC_MC_M1 0x04 -+#define CC_MC_M1M2 0x02 -+#define CC_MC_M1M2M3 0x01 -+#define CC_MC_M1M3 0x11 -+ -+/* Type 2 Clock control magic field values */ -+#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ -+#define CC_T2M2_BIAS 3 /* m2 bias */ -+ -+#define CC_T2MC_M1BYP 1 -+#define CC_T2MC_M2BYP 2 -+#define CC_T2MC_M3BYP 4 -+ -+/* Type 6 Clock control magic field values */ -+#define CC_T6_MMASK 1 /* bits of interest in m */ -+#define CC_T6_M0 120000000 /* sb clock for m = 0 */ -+#define CC_T6_M1 100000000 /* sb clock for m = 1 */ -+#define SB2MIPS_T6(sb) (2 * (sb)) -+ -+/* Common clock base */ -+#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ -+#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */ -+ -+/* Clock control values for 200MHz in 5350 */ -+#define CLKC_5350_N 0x0311 -+#define CLKC_5350_M 0x04020009 -+ -+/* Flash types in the chipcommon capabilities register */ -+#define FLASH_NONE 0x000 /* No flash */ -+#define SFLASH_ST 0x100 /* ST serial flash */ -+#define SFLASH_AT 0x200 /* Atmel serial flash */ -+#define NFLASH 0x300 -+#define PFLASH 0x700 /* Parallel flash */ -+#define QSPIFLASH_ST 0x800 -+#define QSPIFLASH_AT 0x900 -+ -+/* Bits in the ExtBus config registers */ -+#define CC_CFG_EN 0x0001 /* Enable */ -+#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ -+#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ -+#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ -+#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ -+#define CC_CFG_EM_IDE 0x0006 /* IDE */ -+#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ -+#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ -+#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ -+#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ -+#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ -+ -+/* ExtBus address space */ -+#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ -+#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ -+#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ -+#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ -+#define CC_EB_IDE 0x1a800000 /* IDE memory base */ -+#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ -+#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ -+#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ -+#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ -+ -+ -+/* Start/busy bit in flashcontrol */ -+#define SFLASH_OPCODE 0x000000ff -+#define SFLASH_ACTION 0x00000700 -+#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ -+#define SFLASH_START 0x80000000 -+#define SFLASH_BUSY SFLASH_START -+ -+/* flashcontrol action codes */ -+#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ -+#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ -+#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */ -+#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */ -+#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */ -+#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */ -+#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */ -+ -+/* flashcontrol action+opcodes for ST flashes */ -+#define SFLASH_ST_WREN 0x0006 /* Write Enable */ -+#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ -+#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ -+#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ -+#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ -+#define SFLASH_ST_PP 0x0302 /* Page Program */ -+#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ -+#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ -+#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ -+#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ -+#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ -+#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */ -+ -+#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */ -+#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */ -+ -+/* Status register bits for ST flashes */ -+#define SFLASH_ST_WIP 0x01 /* Write In Progress */ -+#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ -+#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ -+#define SFLASH_ST_BP_SHIFT 2 -+#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ -+ -+/* flashcontrol action+opcodes for Atmel flashes */ -+#define SFLASH_AT_READ 0x07e8 -+#define SFLASH_AT_PAGE_READ 0x07d2 -+#define SFLASH_AT_BUF1_READ -+#define SFLASH_AT_BUF2_READ -+#define SFLASH_AT_STATUS 0x01d7 -+#define SFLASH_AT_BUF1_WRITE 0x0384 -+#define SFLASH_AT_BUF2_WRITE 0x0387 -+#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 -+#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 -+#define SFLASH_AT_BUF1_PROGRAM 0x0288 -+#define SFLASH_AT_BUF2_PROGRAM 0x0289 -+#define SFLASH_AT_PAGE_ERASE 0x0281 -+#define SFLASH_AT_BLOCK_ERASE 0x0250 -+#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 -+#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 -+#define SFLASH_AT_BUF1_LOAD 0x0253 -+#define SFLASH_AT_BUF2_LOAD 0x0255 -+#define SFLASH_AT_BUF1_COMPARE 0x0260 -+#define SFLASH_AT_BUF2_COMPARE 0x0261 -+#define SFLASH_AT_BUF1_REPROGRAM 0x0258 -+#define SFLASH_AT_BUF2_REPROGRAM 0x0259 -+ -+/* Status register bits for Atmel flashes */ -+#define SFLASH_AT_READY 0x80 -+#define SFLASH_AT_MISMATCH 0x40 -+#define SFLASH_AT_ID_MASK 0x38 -+#define SFLASH_AT_ID_SHIFT 3 -+ -+/* SPI register bits, corerev >= 37 */ -+#define GSIO_START 0x80000000 -+#define GSIO_BUSY GSIO_START -+ -+/* -+ * These are the UART port assignments, expressed as offsets from the base -+ * register. These assignments should hold for any serial port based on -+ * a 8250, 16450, or 16550(A). -+ */ -+ -+#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ -+#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ -+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ -+#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ -+#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ -+#define UART_IIR 2 /* In: Interrupt Identity Register */ -+#define UART_FCR 2 /* Out: FIFO Control Register */ -+#define UART_LCR 3 /* Out: Line Control Register */ -+#define UART_MCR 4 /* Out: Modem Control Register */ -+#define UART_LSR 5 /* In: Line Status Register */ -+#define UART_MSR 6 /* In: Modem Status Register */ -+#define UART_SCR 7 /* I/O: Scratch Register */ -+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ -+#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */ -+#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ -+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ -+#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */ -+#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */ -+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -+#define UART_LSR_BREAK 0x10 /* Break interrupt */ -+#define UART_LSR_FRAMING 0x08 /* Framing error */ -+#define UART_LSR_PARITY 0x04 /* Parity error */ -+#define UART_LSR_OVERRUN 0x02 /* Overrun error */ -+#define UART_LSR_RXRDY 0x01 /* Receiver ready */ -+#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ -+ -+/* Interrupt Identity Register (IIR) bits */ -+#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ -+#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ -+#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ -+#define UART_IIR_NOINT 0x1 /* No interrupt pending */ -+#define UART_IIR_THRE 0x2 /* THR empty */ -+#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ -+#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ -+#define UART_IIR_CHAR_TIME 0xc /* Character time */ -+ -+/* Interrupt Enable Register (IER) bits */ -+#define UART_IER_EDSSI 8 /* enable modem status interrupt */ -+#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ -+#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ -+#define UART_IER_ERBFI 1 /* enable data available interrupt */ -+ -+/* pmustatus */ -+#define PST_EXTLPOAVAIL 0x0100 -+#define PST_WDRESET 0x0080 -+#define PST_INTPEND 0x0040 -+#define PST_SBCLKST 0x0030 -+#define PST_SBCLKST_ILP 0x0010 -+#define PST_SBCLKST_ALP 0x0020 -+#define PST_SBCLKST_HT 0x0030 -+#define PST_ALPAVAIL 0x0008 -+#define PST_HTAVAIL 0x0004 -+#define PST_RESINIT 0x0003 -+ -+/* pmucapabilities */ -+#define PCAP_REV_MASK 0x000000ff -+#define PCAP_RC_MASK 0x00001f00 -+#define PCAP_RC_SHIFT 8 -+#define PCAP_TC_MASK 0x0001e000 -+#define PCAP_TC_SHIFT 13 -+#define PCAP_PC_MASK 0x001e0000 -+#define PCAP_PC_SHIFT 17 -+#define PCAP_VC_MASK 0x01e00000 -+#define PCAP_VC_SHIFT 21 -+#define PCAP_CC_MASK 0x1e000000 -+#define PCAP_CC_SHIFT 25 -+#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ -+#define PCAP5_PC_SHIFT 17 -+#define PCAP5_VC_MASK 0x07c00000 -+#define PCAP5_VC_SHIFT 22 -+#define PCAP5_CC_MASK 0xf8000000 -+#define PCAP5_CC_SHIFT 27 -+ -+/* PMU Resource Request Timer registers */ -+/* This is based on PmuRev0 */ -+#define PRRT_TIME_MASK 0x03ff -+#define PRRT_INTEN 0x0400 -+#define PRRT_REQ_ACTIVE 0x0800 -+#define PRRT_ALP_REQ 0x1000 -+#define PRRT_HT_REQ 0x2000 -+#define PRRT_HQ_REQ 0x4000 -+ -+/* PMU resource bit position */ -+#define PMURES_BIT(bit) (1 << (bit)) -+ -+/* PMU resource number limit */ -+#define PMURES_MAX_RESNUM 30 -+ -+/* PMU chip control0 register */ -+#define PMU_CHIPCTL0 0 -+ -+/* clock req types */ -+#define PMU_CC1_CLKREQ_TYPE_SHIFT 19 -+#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT) -+ -+#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 -+#define CLKREQ_TYPE_CONFIG_PUSHPULL 1 -+ -+/* PMU chip control1 register */ -+#define PMU_CHIPCTL1 1 -+#define PMU_CC1_RXC_DLL_BYPASS 0x00010000 -+ -+#define PMU_CC1_IF_TYPE_MASK 0x00000030 -+#define PMU_CC1_IF_TYPE_RMII 0x00000000 -+#define PMU_CC1_IF_TYPE_MII 0x00000010 -+#define PMU_CC1_IF_TYPE_RGMII 0x00000020 -+ -+#define PMU_CC1_SW_TYPE_MASK 0x000000c0 -+#define PMU_CC1_SW_TYPE_EPHY 0x00000000 -+#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040 -+#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080 -+#define PMU_CC1_SW_TYPE_RGMII 0x000000c0 -+ -+/* PMU chip control2 register */ -+#define PMU_CHIPCTL2 2 -+ -+/* PMU chip control3 register */ -+#define PMU_CHIPCTL3 3 -+ -+#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 -+#define PMU_CC3_ENABLE_RF_SHIFT 22 -+#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 -+ -+ -+/* PMU corerev and chip specific PLL controls. -+ * PMU_PLL_XX where is PMU corerev and is an arbitrary number -+ * to differentiate different PLLs controlled by the same PMU rev. -+ */ -+/* pllcontrol registers */ -+/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ -+#define PMU0_PLL0_PLLCTL0 0 -+#define PMU0_PLL0_PC0_PDIV_MASK 1 -+#define PMU0_PLL0_PC0_PDIV_FREQ 25000 -+#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 -+#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 -+#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 -+ -+/* PC0_DIV_ARM for PLLOUT_ARM */ -+#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 -+#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 -+#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 -+#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ -+#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 -+#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 -+#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 -+#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 -+ -+/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ -+#define PMU0_PLL0_PLLCTL1 1 -+#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 -+#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 -+#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 -+#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 -+#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 -+ -+/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ -+#define PMU0_PLL0_PLLCTL2 2 -+#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf -+#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 -+ -+/* pllcontrol registers */ -+/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ -+#define PMU1_PLL0_PLLCTL0 0 -+#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 -+#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 -+#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 -+#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 -+ -+/* mdiv */ -+#define PMU1_PLL0_PLLCTL1 1 -+#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff -+#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 -+#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 -+#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 -+#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 -+#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 -+#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 -+#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 -+#define PMU1_PLL0_PC1_M4DIV_BY_9 9 -+#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 -+#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 -+ -+#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 -+#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) -+#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) -+ -+/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ -+#define PMU1_PLL0_PLLCTL2 2 -+#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff -+#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 -+#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc -+#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12 -+#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24 -+#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 -+#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 -+#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12 -+#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24 -+#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 -+#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 -+#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 -+#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */ -+#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 -+#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 -+ -+/* ndiv_frac */ -+#define PMU1_PLL0_PLLCTL3 3 -+#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff -+#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 -+ -+/* pll_ctrl */ -+#define PMU1_PLL0_PLLCTL4 4 -+ -+/* pll_ctrl, vco_rng, clkdrive_ch */ -+#define PMU1_PLL0_PLLCTL5 5 -+#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 -+#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 -+ -+/* PMU rev 2 control words */ -+#define PMU2_PHY_PLL_PLLCTL 4 -+#define PMU2_SI_PLL_PLLCTL 10 -+ -+/* PMU rev 2 */ -+/* pllcontrol registers */ -+/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ -+#define PMU2_PLL_PLLCTL0 0 -+#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000 -+#define PMU2_PLL_PC0_P1DIV_SHIFT 20 -+#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000 -+#define PMU2_PLL_PC0_P2DIV_SHIFT 24 -+ -+/* mdiv */ -+#define PMU2_PLL_PLLCTL1 1 -+#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff -+#define PMU2_PLL_PC1_M1DIV_SHIFT 0 -+#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00 -+#define PMU2_PLL_PC1_M2DIV_SHIFT 8 -+#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000 -+#define PMU2_PLL_PC1_M3DIV_SHIFT 16 -+#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000 -+#define PMU2_PLL_PC1_M4DIV_SHIFT 24 -+ -+/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ -+#define PMU2_PLL_PLLCTL2 2 -+#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff -+#define PMU2_PLL_PC2_M5DIV_SHIFT 0 -+#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00 -+#define PMU2_PLL_PC2_M6DIV_SHIFT 8 -+#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000 -+#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17 -+#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000 -+#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20 -+ -+/* ndiv_frac */ -+#define PMU2_PLL_PLLCTL3 3 -+#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff -+#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0 -+ -+/* pll_ctrl */ -+#define PMU2_PLL_PLLCTL4 4 -+ -+/* pll_ctrl, vco_rng, clkdrive_ch */ -+#define PMU2_PLL_PLLCTL5 5 -+#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00 -+#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8 -+#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000 -+#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12 -+#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000 -+#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16 -+#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000 -+#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20 -+#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000 -+#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24 -+#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000 -+#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28 -+ -+/* PMU rev 5 (& 6) */ -+#define PMU5_PLL_P1P2_OFF 0 -+#define PMU5_PLL_P1_MASK 0x0f000000 -+#define PMU5_PLL_P1_SHIFT 24 -+#define PMU5_PLL_P2_MASK 0x00f00000 -+#define PMU5_PLL_P2_SHIFT 20 -+#define PMU5_PLL_M14_OFF 1 -+#define PMU5_PLL_MDIV_MASK 0x000000ff -+#define PMU5_PLL_MDIV_WIDTH 8 -+#define PMU5_PLL_NM5_OFF 2 -+#define PMU5_PLL_NDIV_MASK 0xfff00000 -+#define PMU5_PLL_NDIV_SHIFT 20 -+#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000 -+#define PMU5_PLL_NDIV_MODE_SHIFT 17 -+#define PMU5_PLL_FMAB_OFF 3 -+#define PMU5_PLL_MRAT_MASK 0xf0000000 -+#define PMU5_PLL_MRAT_SHIFT 28 -+#define PMU5_PLL_ABRAT_MASK 0x08000000 -+#define PMU5_PLL_ABRAT_SHIFT 27 -+#define PMU5_PLL_FDIV_MASK 0x07ffffff -+#define PMU5_PLL_PLLCTL_OFF 4 -+#define PMU5_PLL_PCHI_OFF 5 -+#define PMU5_PLL_PCHI_MASK 0x0000003f -+ -+/* pmu XtalFreqRatio */ -+#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF -+#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 -+#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 -+ -+/* Divider allocation in 4716/47162/5356/5357 */ -+#define PMU5_MAINPLL_CPU 1 -+#define PMU5_MAINPLL_MEM 2 -+#define PMU5_MAINPLL_SI 3 -+ -+/* 4706 PMU */ -+#define PMU4706_MAINPLL_PLL0 0 -+#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ -+#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 -+#define PMU6_4706_PROC_P2DIV_SHIFT 16 -+#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 -+#define PMU6_4706_PROC_P1DIV_SHIFT 12 -+#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 -+#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 -+#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 -+#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 -+ -+#define PMU7_PLL_PLLCTL7 7 -+#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 -+#define PMU7_PLL_CTL7_M4DIV_SHIFT 24 -+#define PMU7_PLL_CTL7_M4DIV_BY_6 6 -+#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc -+#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18 -+#define PMU7_PLL_PLLCTL8 8 -+#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff -+#define PMU7_PLL_CTL8_M5DIV_SHIFT 0 -+#define PMU7_PLL_CTL8_M5DIV_BY_8 8 -+#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc -+#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18 -+#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00 -+#define PMU7_PLL_CTL8_M6DIV_SHIFT 8 -+#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc -+#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18 -+#define PMU7_PLL_PLLCTL11 11 -+#define PMU7_PLL_PLLCTL11_MASK 0xffffff00 -+#define PMU7_PLL_PLLCTL11_VAL 0x22222200 -+ -+/* PMU rev 15 */ -+#define PMU15_PLL_PLLCTL0 0 -+#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 -+#define PMU15_PLL_PC0_CLKSEL_SHIFT 0 -+#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC -+#define PMU15_PLL_PC0_FREQTGT_SHIFT 2 -+#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 -+#define PMU15_PLL_PC0_PRESCALE_SHIFT 22 -+#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 -+#define PMU15_PLL_PC0_KPCTRL_SHIFT 24 -+#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 -+#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 -+#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 -+#define PMU15_PLL_PC0_FDCMODE_SHIFT 30 -+#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 -+#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 -+ -+#define PMU15_PLL_PLLCTL1 1 -+#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060 -+#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5 -+#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040 -+#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6 -+#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80 -+#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7 -+#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000 -+#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17 -+#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000 -+#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26 -+#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000 -+#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28 -+#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000 -+#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30 -+ -+#define PMU15_PLL_PLLCTL2 2 -+#define PMU15_PLL_PC2_CTEN_MASK 0x00000001 -+#define PMU15_PLL_PC2_CTEN_SHIFT 0 -+ -+#define PMU15_PLL_PLLCTL3 3 -+#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001 -+#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0 -+#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000 -+#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25 -+#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01 -+#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0 -+#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02 -+#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1 -+#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04 -+#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2 -+#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18 -+#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3 -+#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60 -+#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5 -+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0 -+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1 -+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2 -+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3 -+ -+#define PMU15_PLL_PLLCTL4 4 -+#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007 -+#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0 -+#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038 -+#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3 -+#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0 -+#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6 -+#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00 -+#define PMU15_PLL_PC4_DBGMODE_SHIFT 9 -+#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000 -+#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12 -+#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000 -+#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13 -+#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000 -+#define PMU15_PLL_PC4_DINPOL_SHIFT 20 -+#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000 -+#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21 -+#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000 -+#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22 -+#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000 -+#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23 -+#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000 -+#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24 -+#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000 -+#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25 -+#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000 -+#define PMU15_PLL_PC4_TEST_EN_SHIFT 26 -+ -+#define PMU15_PLL_PLLCTL5 5 -+#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF -+#define PMU15_PLL_PC5_FREQTGT_SHIFT 0 -+#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000 -+#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20 -+#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000 -+#define PMU15_PLL_PC5_PRESCALE_SHIFT 27 -+ -+#define PMU15_PLL_PLLCTL6 6 -+#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF -+#define PMU15_PLL_PC6_FREQTGT_SHIFT 0 -+#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000 -+#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20 -+#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000 -+#define PMU15_PLL_PC6_PRESCALE_SHIFT 27 -+ -+#define PMU15_FREQTGT_480_DEFAULT 0x19AB1 -+#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5 -+#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */ -+#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */ -+#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */ -+ -+ -+#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 -+#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 -+ -+#define PMU17_PLLCTL2_NDIV_MODE_INT 0 -+#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1 -+#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2 -+#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3 -+ -+#define PMU17_PLLCTL0_BBPLL_PWRDWN 0 -+#define PMU17_PLLCTL0_BBPLL_DRST 3 -+#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8 -+ -+/* PLL usage in 4716/47162 */ -+#define PMU4716_MAINPLL_PLL0 12 -+ -+/* PLL usage in 5356/5357 */ -+#define PMU5356_MAINPLL_PLL0 0 -+#define PMU5357_MAINPLL_PLL0 0 -+ -+/* 4716/47162 resources */ -+#define RES4716_PROC_PLL_ON 0x00000040 -+#define RES4716_PROC_HT_AVAIL 0x00000080 -+ -+/* 4716/4717/4718 Chip specific ChipControl register bits */ -+#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ -+ -+/* 5357 Chip specific ChipControl register bits */ -+/* 2nd - 32-bit reg */ -+#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ -+#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ -+ -+/* 5354 resources */ -+#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ -+#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ -+#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ -+#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ -+#define RES5354_ILP_REQUEST 4 /* 0x00010 */ -+#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ -+#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ -+#define RES5354_ROM_SWITCH 7 /* 0x00080 */ -+#define RES5354_PA_REF_LDO 8 /* 0x00100 */ -+#define RES5354_RADIO_LDO 9 /* 0x00200 */ -+#define RES5354_AFE_LDO 10 /* 0x00400 */ -+#define RES5354_PLL_LDO 11 /* 0x00800 */ -+#define RES5354_BG_FILTBYP 12 /* 0x01000 */ -+#define RES5354_TX_FILTBYP 13 /* 0x02000 */ -+#define RES5354_RX_FILTBYP 14 /* 0x04000 */ -+#define RES5354_XTAL_PU 15 /* 0x08000 */ -+#define RES5354_XTAL_EN 16 /* 0x10000 */ -+#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ -+#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ -+#define RES5354_BB_PLL_PU 19 /* 0x80000 */ -+ -+/* 5357 Chip specific ChipControl register bits */ -+#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ -+#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ -+#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ -+ -+/* 4328 resources */ -+#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ -+#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ -+#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ -+#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ -+#define RES4328_ILP_REQUEST 4 /* 0x00010 */ -+#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ -+#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ -+#define RES4328_ROM_SWITCH 7 /* 0x00080 */ -+#define RES4328_PA_REF_LDO 8 /* 0x00100 */ -+#define RES4328_RADIO_LDO 9 /* 0x00200 */ -+#define RES4328_AFE_LDO 10 /* 0x00400 */ -+#define RES4328_PLL_LDO 11 /* 0x00800 */ -+#define RES4328_BG_FILTBYP 12 /* 0x01000 */ -+#define RES4328_TX_FILTBYP 13 /* 0x02000 */ -+#define RES4328_RX_FILTBYP 14 /* 0x04000 */ -+#define RES4328_XTAL_PU 15 /* 0x08000 */ -+#define RES4328_XTAL_EN 16 /* 0x10000 */ -+#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ -+#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ -+#define RES4328_BB_PLL_PU 19 /* 0x80000 */ -+ -+/* 4325 A0/A1 resources */ -+#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ -+#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ -+#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ -+#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ -+#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ -+#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ -+#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ -+#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ -+#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ -+#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ -+#define RES4325_OTP_PU 10 /* 0x00000400 */ -+#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ -+#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ -+#define RES4325_XTAL_PU 13 /* 0x00002000 */ -+#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ -+#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ -+#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ -+#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ -+#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ -+#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ -+#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ -+#define RES4325_HT_AVAIL 21 /* 0x00200000 */ -+ -+/* 4325 B0/C0 resources */ -+#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */ -+#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */ -+#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */ -+#define RES4325B0_CLDO_PU 4 /* 0x00000010 */ -+ -+/* 4325 C1 resources */ -+#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */ -+ -+/* 4325 chip-specific ChipStatus register bits */ -+#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 -+#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ -+#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ -+#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ -+#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ -+#define CST4325_SDIO_USB_MODE_MASK 0x00000004 -+#define CST4325_SDIO_USB_MODE_SHIFT 2 -+#define CST4325_RCAL_VALID_MASK 0x00000008 -+#define CST4325_RCAL_VALID_SHIFT 3 -+#define CST4325_RCAL_VALUE_MASK 0x000001f0 -+#define CST4325_RCAL_VALUE_SHIFT 4 -+#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ -+#define CST4325_PMUTOP_2B_SHIFT 9 -+ -+#define RES4329_RESERVED0 0 /* 0x00000001 */ -+#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */ -+#define RES4329_CBUCK_BURST 2 /* 0x00000004 */ -+#define RES4329_CBUCK_PWM 3 /* 0x00000008 */ -+#define RES4329_CLDO_PU 4 /* 0x00000010 */ -+#define RES4329_PALDO_PU 5 /* 0x00000020 */ -+#define RES4329_ILP_REQUEST 6 /* 0x00000040 */ -+#define RES4329_RESERVED7 7 /* 0x00000080 */ -+#define RES4329_RESERVED8 8 /* 0x00000100 */ -+#define RES4329_LNLDO1_PU 9 /* 0x00000200 */ -+#define RES4329_OTP_PU 10 /* 0x00000400 */ -+#define RES4329_RESERVED11 11 /* 0x00000800 */ -+#define RES4329_LNLDO2_PU 12 /* 0x00001000 */ -+#define RES4329_XTAL_PU 13 /* 0x00002000 */ -+#define RES4329_ALP_AVAIL 14 /* 0x00004000 */ -+#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */ -+#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */ -+#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */ -+#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */ -+#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */ -+#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */ -+#define RES4329_HT_AVAIL 21 /* 0x00200000 */ -+ -+#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 -+#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ -+#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ -+#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ -+#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ -+#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 -+#define CST4329_SPI_SDIO_MODE_SHIFT 2 -+ -+/* 4312 chip-specific ChipStatus register bits */ -+#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 -+#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ -+#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ -+#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */ -+#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */ -+ -+/* 4312 resources (all PMU chips with little memory constraint) */ -+#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ -+#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ -+#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ -+#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ -+#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ -+#define RES4312_RADIO_LDO 5 /* 0x00000020 */ -+#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ -+#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ -+#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ -+#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ -+#define RES4312_XTAL_PU 10 /* 0x00000400 */ -+#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ -+#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ -+#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ -+#define RES4312_HT_AVAIL 14 /* 0x00004000 */ -+ -+/* 4322 resources */ -+#define RES4322_RF_LDO 0 -+#define RES4322_ILP_REQUEST 1 -+#define RES4322_XTAL_PU 2 -+#define RES4322_ALP_AVAIL 3 -+#define RES4322_SI_PLL_ON 4 -+#define RES4322_HT_SI_AVAIL 5 -+#define RES4322_PHY_PLL_ON 6 -+#define RES4322_HT_PHY_AVAIL 7 -+#define RES4322_OTP_PU 8 -+ -+/* 4322 chip-specific ChipStatus register bits */ -+#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 -+#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 -+#define CST4322_SPROM_OTP_SEL_SHIFT 6 -+#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */ -+#define CST4322_SPROM_PRESENT 1 /* SPROM is present */ -+#define CST4322_OTP_PRESENT 2 /* OTP is present */ -+#define CST4322_PCI_OR_USB 0x00000100 -+#define CST4322_BOOT_MASK 0x00000600 -+#define CST4322_BOOT_SHIFT 9 -+#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ -+#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */ -+#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */ -+#define CST4322_BOOT_FROM_INVALID 3 -+#define CST4322_ILP_DIV_EN 0x00000800 -+#define CST4322_FLASH_TYPE_MASK 0x00001000 -+#define CST4322_FLASH_TYPE_SHIFT 12 -+#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */ -+#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */ -+#define CST4322_ARM_TAP_SEL 0x00002000 -+#define CST4322_RES_INIT_MODE_MASK 0x0000c000 -+#define CST4322_RES_INIT_MODE_SHIFT 14 -+#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */ -+#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */ -+#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */ -+#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */ -+#define CST4322_PCIPLLCLK_GATING 0x00010000 -+#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 -+#define CST4322_PCI_CARDBUS_MODE 0x00040000 -+ -+/* 43224 chip-specific ChipControl register bits */ -+#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ -+#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ -+#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ -+ -+/* 43236 resources */ -+#define RES43236_REGULATOR 0 -+#define RES43236_ILP_REQUEST 1 -+#define RES43236_XTAL_PU 2 -+#define RES43236_ALP_AVAIL 3 -+#define RES43236_SI_PLL_ON 4 -+#define RES43236_HT_SI_AVAIL 5 -+ -+/* 43236 chip-specific ChipControl register bits */ -+#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */ -+#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ -+#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */ -+#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ -+#define CCTRL43236_GSIO (1<<4) /* 0 disable */ -+ -+/* 43236 Chip specific ChipStatus register bits */ -+#define CST43236_SFLASH_MASK 0x00000040 -+#define CST43236_OTP_SEL_MASK 0x00000080 -+#define CST43236_OTP_SEL_SHIFT 7 -+#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ -+#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ -+#define CST43236_BOOT_MASK 0x00001800 -+#define CST43236_BOOT_SHIFT 11 -+#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ -+#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ -+#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ -+#define CST43236_BOOT_FROM_INVALID 3 -+ -+/* 43237 resources */ -+#define RES43237_REGULATOR 0 -+#define RES43237_ILP_REQUEST 1 -+#define RES43237_XTAL_PU 2 -+#define RES43237_ALP_AVAIL 3 -+#define RES43237_SI_PLL_ON 4 -+#define RES43237_HT_SI_AVAIL 5 -+ -+/* 43237 chip-specific ChipControl register bits */ -+#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */ -+#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ -+#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */ -+#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ -+#define CCTRL43237_GSIO (1<<4) /* 0 disable */ -+ -+/* 43237 Chip specific ChipStatus register bits */ -+#define CST43237_SFLASH_MASK 0x00000040 -+#define CST43237_OTP_SEL_MASK 0x00000080 -+#define CST43237_OTP_SEL_SHIFT 7 -+#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */ -+#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */ -+#define CST43237_BOOT_MASK 0x00001800 -+#define CST43237_BOOT_SHIFT 11 -+#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ -+#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */ -+#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */ -+#define CST43237_BOOT_FROM_INVALID 3 -+ -+/* 43239 resources */ -+#define RES43239_OTP_PU 9 -+#define RES43239_MACPHY_CLKAVAIL 23 -+#define RES43239_HT_AVAIL 24 -+ -+/* 43239 Chip specific ChipStatus register bits */ -+#define CST43239_SPROM_MASK 0x00000002 -+#define CST43239_SFLASH_MASK 0x00000004 -+#define CST43239_RES_INIT_MODE_SHIFT 7 -+#define CST43239_RES_INIT_MODE_MASK 0x000001f0 -+#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */ -+#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */ -+#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */ -+#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ -+ -+/* 4324 resources */ -+#define RES4324_OTP_PU 10 -+#define RES4324_HT_AVAIL 29 -+#define RES4324_MACPHY_CLKAVAIL 30 -+ -+/* 4324 Chip specific ChipStatus register bits */ -+#define CST4324_SPROM_MASK 0x00000080 -+#define CST4324_SFLASH_MASK 0x00400000 -+#define CST4324_RES_INIT_MODE_SHIFT 10 -+#define CST4324_RES_INIT_MODE_MASK 0x00000c00 -+#define CST4324_CHIPMODE_MASK 0x7 -+#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ -+#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ -+ -+/* 4331 resources */ -+#define RES4331_REGULATOR 0 -+#define RES4331_ILP_REQUEST 1 -+#define RES4331_XTAL_PU 2 -+#define RES4331_ALP_AVAIL 3 -+#define RES4331_SI_PLL_ON 4 -+#define RES4331_HT_SI_AVAIL 5 -+ -+/* 4331 chip-specific ChipControl register bits */ -+#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ -+#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ -+#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */ -+#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ -+#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ -+#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ -+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ -+#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ -+#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ -+#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ -+#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ -+#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ -+#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */ -+#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */ -+#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ -+#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ -+#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */ -+ -+/* 4331 Chip specific ChipStatus register bits */ -+#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ -+#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 -+#define CST4331_SPROM_OTP_SEL_SHIFT 1 -+#define CST4331_SPROM_PRESENT 0x00000002 -+#define CST4331_OTP_PRESENT 0x00000004 -+#define CST4331_LDO_RF 0x00000008 -+#define CST4331_LDO_PAR 0x00000010 -+ -+/* 4315 resource */ -+#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */ -+#define RES4315_CBUCK_BURST 2 /* 0x00000004 */ -+#define RES4315_CBUCK_PWM 3 /* 0x00000008 */ -+#define RES4315_CLDO_PU 4 /* 0x00000010 */ -+#define RES4315_PALDO_PU 5 /* 0x00000020 */ -+#define RES4315_ILP_REQUEST 6 /* 0x00000040 */ -+#define RES4315_LNLDO1_PU 9 /* 0x00000200 */ -+#define RES4315_OTP_PU 10 /* 0x00000400 */ -+#define RES4315_LNLDO2_PU 12 /* 0x00001000 */ -+#define RES4315_XTAL_PU 13 /* 0x00002000 */ -+#define RES4315_ALP_AVAIL 14 /* 0x00004000 */ -+#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */ -+#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */ -+#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */ -+#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */ -+#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */ -+#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */ -+#define RES4315_HT_AVAIL 21 /* 0x00200000 */ -+ -+/* 4315 chip-specific ChipStatus register bits */ -+#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */ -+#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ -+#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */ -+#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */ -+#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */ -+#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */ -+#define CST4315_RCAL_VALID 0x00000008 -+#define CST4315_RCAL_VALUE_MASK 0x000001f0 -+#define CST4315_RCAL_VALUE_SHIFT 4 -+#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */ -+#define CST4315_CBUCK_MODE_MASK 0x00000c00 -+#define CST4315_CBUCK_MODE_BURST 0x00000400 -+#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 -+ -+/* 4319 resources */ -+#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */ -+#define RES4319_CBUCK_BURST 2 /* 0x00000004 */ -+#define RES4319_CBUCK_PWM 3 /* 0x00000008 */ -+#define RES4319_CLDO_PU 4 /* 0x00000010 */ -+#define RES4319_PALDO_PU 5 /* 0x00000020 */ -+#define RES4319_ILP_REQUEST 6 /* 0x00000040 */ -+#define RES4319_LNLDO1_PU 9 /* 0x00000200 */ -+#define RES4319_OTP_PU 10 /* 0x00000400 */ -+#define RES4319_LNLDO2_PU 12 /* 0x00001000 */ -+#define RES4319_XTAL_PU 13 /* 0x00002000 */ -+#define RES4319_ALP_AVAIL 14 /* 0x00004000 */ -+#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */ -+#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */ -+#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */ -+#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */ -+#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */ -+#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */ -+#define RES4319_HT_AVAIL 21 /* 0x00200000 */ -+ -+/* 4319 chip-specific ChipStatus register bits */ -+#define CST4319_SPI_CPULESSUSB 0x00000001 -+#define CST4319_SPI_CLK_POL 0x00000002 -+#define CST4319_SPI_CLK_PH 0x00000008 -+#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ -+#define CST4319_SPROM_OTP_SEL_SHIFT 6 -+#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ -+#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ -+#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ -+#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ -+#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ -+#define CST4319_REMAP_SEL_MASK 0x00000600 -+#define CST4319_ILPDIV_EN 0x00000800 -+#define CST4319_XTAL_PD_POL 0x00001000 -+#define CST4319_LPO_SEL 0x00002000 -+#define CST4319_RES_INIT_MODE 0x0000c000 -+#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ -+#define CST4319_CBUCK_MODE_MASK 0x00060000 -+#define CST4319_CBUCK_MODE_BURST 0x00020000 -+#define CST4319_CBUCK_MODE_LPBURST 0x00060000 -+#define CST4319_RCAL_VALID 0x01000000 -+#define CST4319_RCAL_VALUE_MASK 0x3e000000 -+#define CST4319_RCAL_VALUE_SHIFT 25 -+ -+#define PMU1_PLL0_CHIPCTL0 0 -+#define PMU1_PLL0_CHIPCTL1 1 -+#define PMU1_PLL0_CHIPCTL2 2 -+#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 -+#define CCTL_4319USB_XTAL_SEL_SHIFT 19 -+#define CCTL_4319USB_48MHZ_PLL_SEL 1 -+#define CCTL_4319USB_24MHZ_PLL_SEL 2 -+ -+/* PMU resources for 4336 */ -+#define RES4336_CBUCK_LPOM 0 -+#define RES4336_CBUCK_BURST 1 -+#define RES4336_CBUCK_LP_PWM 2 -+#define RES4336_CBUCK_PWM 3 -+#define RES4336_CLDO_PU 4 -+#define RES4336_DIS_INT_RESET_PD 5 -+#define RES4336_ILP_REQUEST 6 -+#define RES4336_LNLDO_PU 7 -+#define RES4336_LDO3P3_PU 8 -+#define RES4336_OTP_PU 9 -+#define RES4336_XTAL_PU 10 -+#define RES4336_ALP_AVAIL 11 -+#define RES4336_RADIO_PU 12 -+#define RES4336_BG_PU 13 -+#define RES4336_VREG1p4_PU_PU 14 -+#define RES4336_AFE_PWRSW_PU 15 -+#define RES4336_RX_PWRSW_PU 16 -+#define RES4336_TX_PWRSW_PU 17 -+#define RES4336_BB_PWRSW_PU 18 -+#define RES4336_SYNTH_PWRSW_PU 19 -+#define RES4336_MISC_PWRSW_PU 20 -+#define RES4336_LOGEN_PWRSW_PU 21 -+#define RES4336_BBPLL_PWRSW_PU 22 -+#define RES4336_MACPHY_CLKAVAIL 23 -+#define RES4336_HT_AVAIL 24 -+#define RES4336_RSVD 25 -+ -+/* 4336 chip-specific ChipStatus register bits */ -+#define CST4336_SPI_MODE_MASK 0x00000001 -+#define CST4336_SPROM_PRESENT 0x00000002 -+#define CST4336_OTP_PRESENT 0x00000004 -+#define CST4336_ARMREMAP_0 0x00000008 -+#define CST4336_ILPDIV_EN_MASK 0x00000010 -+#define CST4336_ILPDIV_EN_SHIFT 4 -+#define CST4336_XTAL_PD_POL_MASK 0x00000020 -+#define CST4336_XTAL_PD_POL_SHIFT 5 -+#define CST4336_LPO_SEL_MASK 0x00000040 -+#define CST4336_LPO_SEL_SHIFT 6 -+#define CST4336_RES_INIT_MODE_MASK 0x00000180 -+#define CST4336_RES_INIT_MODE_SHIFT 7 -+#define CST4336_CBUCK_MODE_MASK 0x00000600 -+#define CST4336_CBUCK_MODE_SHIFT 9 -+ -+/* 4336 Chip specific PMU ChipControl register bits */ -+#define PCTL_4336_SERIAL_ENAB (1 << 24) -+ -+/* 4330 resources */ -+#define RES4330_CBUCK_LPOM 0 -+#define RES4330_CBUCK_BURST 1 -+#define RES4330_CBUCK_LP_PWM 2 -+#define RES4330_CBUCK_PWM 3 -+#define RES4330_CLDO_PU 4 -+#define RES4330_DIS_INT_RESET_PD 5 -+#define RES4330_ILP_REQUEST 6 -+#define RES4330_LNLDO_PU 7 -+#define RES4330_LDO3P3_PU 8 -+#define RES4330_OTP_PU 9 -+#define RES4330_XTAL_PU 10 -+#define RES4330_ALP_AVAIL 11 -+#define RES4330_RADIO_PU 12 -+#define RES4330_BG_PU 13 -+#define RES4330_VREG1p4_PU_PU 14 -+#define RES4330_AFE_PWRSW_PU 15 -+#define RES4330_RX_PWRSW_PU 16 -+#define RES4330_TX_PWRSW_PU 17 -+#define RES4330_BB_PWRSW_PU 18 -+#define RES4330_SYNTH_PWRSW_PU 19 -+#define RES4330_MISC_PWRSW_PU 20 -+#define RES4330_LOGEN_PWRSW_PU 21 -+#define RES4330_BBPLL_PWRSW_PU 22 -+#define RES4330_MACPHY_CLKAVAIL 23 -+#define RES4330_HT_AVAIL 24 -+#define RES4330_5gRX_PWRSW_PU 25 -+#define RES4330_5gTX_PWRSW_PU 26 -+#define RES4330_5g_LOGEN_PWRSW_PU 27 -+ -+/* 4330 chip-specific ChipStatus register bits */ -+#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ -+#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ -+#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ -+#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ -+#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ -+#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ -+#define CST4330_OTP_PRESENT 0x00000010 -+#define CST4330_LPO_AUTODET_EN 0x00000020 -+#define CST4330_ARMREMAP_0 0x00000040 -+#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ -+#define CST4330_ILPDIV_EN 0x00000100 -+#define CST4330_LPO_SEL 0x00000200 -+#define CST4330_RES_INIT_MODE_SHIFT 10 -+#define CST4330_RES_INIT_MODE_MASK 0x00000c00 -+#define CST4330_CBUCK_MODE_SHIFT 12 -+#define CST4330_CBUCK_MODE_MASK 0x00003000 -+#define CST4330_CBUCK_POWER_OK 0x00004000 -+#define CST4330_BB_PLL_LOCKED 0x00008000 -+#define SOCDEVRAM_BP_ADDR 0x1E000000 -+#define SOCDEVRAM_ARM_ADDR 0x00800000 -+ -+/* 4330 Chip specific PMU ChipControl register bits */ -+#define PCTL_4330_SERIAL_ENAB (1 << 24) -+ -+/* 4330 Chip specific ChipControl register bits */ -+#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ -+#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ -+#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ -+#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ -+ -+/* 4334 resources */ -+#define RES4334_LPLDO_PU 0 -+#define RES4334_RESET_PULLDN_DIS 1 -+#define RES4334_PMU_BG_PU 2 -+#define RES4334_HSIC_LDO_PU 3 -+#define RES4334_CBUCK_LPOM_PU 4 -+#define RES4334_CBUCK_PFM_PU 5 -+#define RES4334_CLDO_PU 6 -+#define RES4334_LPLDO2_LVM 7 -+#define RES4334_LNLDO_PU 8 -+#define RES4334_LDO3P3_PU 9 -+#define RES4334_OTP_PU 10 -+#define RES4334_XTAL_PU 11 -+#define RES4334_WL_PWRSW_PU 12 -+#define RES4334_LQ_AVAIL 13 -+#define RES4334_LOGIC_RET 14 -+#define RES4334_MEM_SLEEP 15 -+#define RES4334_MACPHY_RET 16 -+#define RES4334_WL_CORE_READY 17 -+#define RES4334_ILP_REQ 18 -+#define RES4334_ALP_AVAIL 19 -+#define RES4334_MISC_PWRSW_PU 20 -+#define RES4334_SYNTH_PWRSW_PU 21 -+#define RES4334_RX_PWRSW_PU 22 -+#define RES4334_RADIO_PU 23 -+#define RES4334_WL_PMU_PU 24 -+#define RES4334_VCO_LDO_PU 25 -+#define RES4334_AFE_LDO_PU 26 -+#define RES4334_RX_LDO_PU 27 -+#define RES4334_TX_LDO_PU 28 -+#define RES4334_HT_AVAIL 29 -+#define RES4334_MACPHY_CLK_AVAIL 30 -+ -+/* 4334 chip-specific ChipStatus register bits */ -+#define CST4334_CHIPMODE_MASK 7 -+#define CST4334_SDIO_MODE 0x00000000 -+#define CST4334_SPI_MODE 0x00000004 -+#define CST4334_HSIC_MODE 0x00000006 -+#define CST4334_BLUSB_MODE 0x00000007 -+#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) -+#define CST4334_OTP_PRESENT 0x00000010 -+#define CST4334_LPO_AUTODET_EN 0x00000020 -+#define CST4334_ARMREMAP_0 0x00000040 -+#define CST4334_SPROM_PRESENT 0x00000080 -+#define CST4334_ILPDIV_EN_MASK 0x00000100 -+#define CST4334_ILPDIV_EN_SHIFT 8 -+#define CST4334_LPO_SEL_MASK 0x00000200 -+#define CST4334_LPO_SEL_SHIFT 9 -+#define CST4334_RES_INIT_MODE_MASK 0x00000C00 -+#define CST4334_RES_INIT_MODE_SHIFT 10 -+ -+/* 4334 Chip specific PMU ChipControl register bits */ -+#define PCTL_4334_GPIO3_ENAB (1 << 3) -+ -+/* 4334 Chip control */ -+#define CCTRL4334_HSIC_LDO_PU (1 << 23) -+ -+/* 4324 Chip specific ChipControl1 register bits */ -+#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ -+#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ -+ -+ -+/* 4313 resources */ -+#define RES4313_BB_PU_RSRC 0 -+#define RES4313_ILP_REQ_RSRC 1 -+#define RES4313_XTAL_PU_RSRC 2 -+#define RES4313_ALP_AVAIL_RSRC 3 -+#define RES4313_RADIO_PU_RSRC 4 -+#define RES4313_BG_PU_RSRC 5 -+#define RES4313_VREG1P4_PU_RSRC 6 -+#define RES4313_AFE_PWRSW_RSRC 7 -+#define RES4313_RX_PWRSW_RSRC 8 -+#define RES4313_TX_PWRSW_RSRC 9 -+#define RES4313_BB_PWRSW_RSRC 10 -+#define RES4313_SYNTH_PWRSW_RSRC 11 -+#define RES4313_MISC_PWRSW_RSRC 12 -+#define RES4313_BB_PLL_PWRSW_RSRC 13 -+#define RES4313_HT_AVAIL_RSRC 14 -+#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 -+ -+/* 4313 chip-specific ChipStatus register bits */ -+#define CST4313_SPROM_PRESENT 1 -+#define CST4313_OTP_PRESENT 2 -+#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 -+#define CST4313_SPROM_OTP_SEL_SHIFT 0 -+ -+/* 4313 Chip specific ChipControl register bits */ -+#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ -+ -+/* PMU respources for 4314 */ -+#define RES4314_LPLDO_PU 0 -+#define RES4314_PMU_SLEEP_DIS 1 -+#define RES4314_PMU_BG_PU 2 -+#define RES4314_CBUCK_LPOM_PU 3 -+#define RES4314_CBUCK_PFM_PU 4 -+#define RES4314_CLDO_PU 5 -+#define RES4314_LPLDO2_LVM 6 -+#define RES4314_WL_PMU_PU 7 -+#define RES4314_LNLDO_PU 8 -+#define RES4314_LDO3P3_PU 9 -+#define RES4314_OTP_PU 10 -+#define RES4314_XTAL_PU 11 -+#define RES4314_WL_PWRSW_PU 12 -+#define RES4314_LQ_AVAIL 13 -+#define RES4314_LOGIC_RET 14 -+#define RES4314_MEM_SLEEP 15 -+#define RES4314_MACPHY_RET 16 -+#define RES4314_WL_CORE_READY 17 -+#define RES4314_ILP_REQ 18 -+#define RES4314_ALP_AVAIL 19 -+#define RES4314_MISC_PWRSW_PU 20 -+#define RES4314_SYNTH_PWRSW_PU 21 -+#define RES4314_RX_PWRSW_PU 22 -+#define RES4314_RADIO_PU 23 -+#define RES4314_VCO_LDO_PU 24 -+#define RES4314_AFE_LDO_PU 25 -+#define RES4314_RX_LDO_PU 26 -+#define RES4314_TX_LDO_PU 27 -+#define RES4314_HT_AVAIL 28 -+#define RES4314_MACPHY_CLK_AVAIL 29 -+ -+/* 4314 chip-specific ChipStatus register bits */ -+#define CST4314_OTP_ENABLED 0x00200000 -+ -+/* 43228 resources */ -+#define RES43228_NOT_USED 0 -+#define RES43228_ILP_REQUEST 1 -+#define RES43228_XTAL_PU 2 -+#define RES43228_ALP_AVAIL 3 -+#define RES43228_PLL_EN 4 -+#define RES43228_HT_PHY_AVAIL 5 -+ -+/* 43228 chipstatus reg bits */ -+#define CST43228_ILP_DIV_EN 0x1 -+#define CST43228_OTP_PRESENT 0x2 -+#define CST43228_SERDES_REFCLK_PADSEL 0x4 -+#define CST43228_SDIO_MODE 0x8 -+#define CST43228_SDIO_OTP_PRESENT 0x10 -+#define CST43228_SDIO_RESET 0x20 -+ -+/* 4706 chipstatus reg bits */ -+#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ -+#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ -+#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ -+#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ -+#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ -+ -+/* 4706 flashstrconfig reg bits */ -+#define FLSTRCF4706_MASK 0x000000ff -+#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */ -+#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */ -+#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ -+#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */ -+#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */ -+#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ -+#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ -+ -+/* 4360 Chip specific ChipControl register bits */ -+#define CCTRL4360_SECI_MODE (1 << 2) -+#define CCTRL4360_BTSWCTRL_MODE (1 << 3) -+#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) -+#define CCTRL4360_BT_LGCY_MODE (1 << 9) -+#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) -+ -+/* 4360 PMU resources and chip status bits */ -+#define RES4360_REGULATOR 0 -+#define RES4360_ILP_AVAIL 1 -+#define RES4360_ILP_REQ 2 -+#define RES4360_XTAL_PU 3 -+#define RES4360_ALP_AVAIL 4 -+#define RES4360_BBPLLPWRSW_PU 5 -+#define RES4360_HT_AVAIL 6 -+#define RES4360_OTP_PU 7 -+#define RES4360_USBLDO_PU 8 -+#define RES4360_USBPLL_PWRSW_PU 9 -+#define RES4360_LQ_AVAIL 10 -+ -+#define CST4360_XTAL_40MZ 0x00000001 -+#define CST4360_SFLASH 0x00000002 -+#define CST4360_SPROM_PRESENT 0x00000004 -+#define CST4360_SFLASH_TYPE 0x00000004 -+#define CST4360_OTP_ENABLED 0x00000008 -+#define CST4360_REMAP_ROM 0x00000010 -+#define CST4360_RSRC_INIT_MODE_MASK 0x00000060 -+#define CST4360_RSRC_INIT_MODE_SHIFT 5 -+#define CST4360_ILP_DIVEN 0x00000080 -+#define CST4360_MODE_USB 0x00000100 -+#define CST4360_SPROM_SIZE_MASK 0x00000600 -+#define CST4360_SPROM_SIZE_SHIFT 9 -+#define CST4360_BBPLL_LOCK 0x00000800 -+#define CST4360_AVBBPLL_LOCK 0x00001000 -+#define CST4360_USBBBPLL_LOCK 0x00002000 -+ -+#define CCTL_4360_UART_SEL 2 -+ -+/* 4335 resources */ -+#define RES4335_LPLDO_PO 0 -+#define RES4335_PMU_BG_PU 1 -+#define RES4335_PMU_SLEEP 2 -+#define RES4335_RSVD_3 3 -+#define RES4335_CBUCK_LPOM_PU 4 -+#define RES4335_CBUCK_PFM_PU 5 -+#define RES4335_RSVD_6 6 -+#define RES4335_RSVD_7 7 -+#define RES4335_LNLDO_PU 8 -+#define RES4335_XTALLDO_PU 9 -+#define RES4335_LDO3P3_PU 10 -+#define RES4335_OTP_PU 11 -+#define RES4335_XTAL_PU 12 -+#define RES4335_SR_CLK_START 13 -+#define RES4335_LQ_AVAIL 14 -+#define RES4335_LQ_START 15 -+#define RES4335_RSVD_16 16 -+#define RES4335_WL_CORE_RDY 17 -+#define RES4335_ILP_REQ 18 -+#define RES4335_ALP_AVAIL 19 -+#define RES4335_MINI_PMU 20 -+#define RES4335_RADIO_PU 21 -+#define RES4335_SR_CLK_STABLE 22 -+#define RES4335_SR_SAVE_RESTORE 23 -+#define RES4335_SR_PHY_PWRSW 24 -+#define RES4335_SR_VDDM_PWRSW 25 -+#define RES4335_SR_SUBCORE_PWRSW 26 -+#define RES4335_SR_SLEEP 27 -+#define RES4335_HT_START 28 -+#define RES4335_HT_AVAIL 29 -+#define RES4335_MACPHY_CLKAVAIL 30 -+ -+/* 4335 Chip specific ChipStatus register bits */ -+#define CST4335_SPROM_MASK 0x00000020 -+#define CST4335_SFLASH_MASK 0x00000040 -+#define CST4335_RES_INIT_MODE_SHIFT 7 -+#define CST4335_RES_INIT_MODE_MASK 0x00000180 -+#define CST4335_CHIPMODE_MASK 0xF -+#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */ -+#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */ -+#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* USB || USBDA */ -+#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */ -+ -+/* 4335 Chip specific ChipControl1 register bits */ -+#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ -+#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ -+ -+ -+#define CR4_RAM_BASE (0x180000) -+#define PATCHTBL_SIZE (0x800) -+ -+ -+/* 4335 resources--END */ -+ -+/* GCI chipcontrol register indices */ -+#define CC_GCI_CHIPCTRL_00 (0) -+#define CC_GCI_CHIPCTRL_01 (1) -+#define CC_GCI_CHIPCTRL_02 (2) -+#define CC_GCI_CHIPCTRL_03 (3) -+#define CC_GCI_CHIPCTRL_04 (4) -+#define CC_GCI_CHIPCTRL_05 (5) -+#define CC_GCI_CHIPCTRL_06 (6) -+#define CC_GCI_CHIPCTRL_07 (7) -+#define CC_GCI_CHIPCTRL_08 (8) -+ -+#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) -+ -+/* 4335 pins -+* note: only the values set as default/used are added here. -+*/ -+#define CC4335_PIN_GPIO_00 (0) -+#define CC4335_PIN_GPIO_01 (1) -+#define CC4335_PIN_GPIO_02 (2) -+#define CC4335_PIN_GPIO_03 (3) -+#define CC4335_PIN_GPIO_04 (4) -+#define CC4335_PIN_GPIO_05 (5) -+#define CC4335_PIN_GPIO_06 (6) -+#define CC4335_PIN_GPIO_07 (7) -+#define CC4335_PIN_GPIO_08 (8) -+#define CC4335_PIN_GPIO_09 (9) -+#define CC4335_PIN_GPIO_10 (10) -+#define CC4335_PIN_GPIO_11 (11) -+#define CC4335_PIN_GPIO_12 (12) -+#define CC4335_PIN_GPIO_13 (13) -+#define CC4335_PIN_GPIO_14 (14) -+#define CC4335_PIN_GPIO_15 (15) -+#define CC4335_PIN_SDIO_CLK (16) -+#define CC4335_PIN_SDIO_CMD (17) -+#define CC4335_PIN_SDIO_DATA0 (18) -+#define CC4335_PIN_SDIO_DATA1 (19) -+#define CC4335_PIN_SDIO_DATA2 (20) -+#define CC4335_PIN_SDIO_DATA3 (21) -+#define CC4335_PIN_RF_SW_CTRL_0 (22) -+#define CC4335_PIN_RF_SW_CTRL_1 (23) -+#define CC4335_PIN_RF_SW_CTRL_2 (24) -+#define CC4335_PIN_RF_SW_CTRL_3 (25) -+#define CC4335_PIN_RF_SW_CTRL_4 (26) -+#define CC4335_PIN_RF_SW_CTRL_5 (27) -+#define CC4335_PIN_RF_SW_CTRL_6 (28) -+#define CC4335_PIN_RF_SW_CTRL_7 (29) -+#define CC4335_PIN_RF_SW_CTRL_8 (30) -+#define CC4335_PIN_RF_SW_CTRL_9 (31) -+ -+/* 4335 GCI function sel values -+*/ -+#define CC4335_FNSEL_HWDEF (0) -+#define CC4335_FNSEL_SAMEASPIN (1) -+#define CC4335_FNSEL_GPIO0 (2) -+#define CC4335_FNSEL_GPIO1 (3) -+#define CC4335_FNSEL_GCI0 (4) -+#define CC4335_FNSEL_GCI1 (5) -+#define CC4335_FNSEL_UART (6) -+#define CC4335_FNSEL_SFLASH (7) -+#define CC4335_FNSEL_SPROM (8) -+#define CC4335_FNSEL_MISC0 (9) -+#define CC4335_FNSEL_MISC1 (10) -+#define CC4335_FNSEL_MISC2 (11) -+#define CC4335_FNSEL_IND (12) -+#define CC4335_FNSEL_PDN (13) -+#define CC4335_FNSEL_PUP (14) -+#define CC4335_FNSEL_TRI (15) -+ -+/* find the 4 bit mask given the bit position */ -+#define GCIMASK(pos) (((uint32)0xF) << pos) -+ -+/* get the value which can be used to directly OR with chipcontrol reg */ -+#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos)) -+ -+/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic -+* for now only UART for bootloader. -+*/ -+#define MUXENAB4335_UART_MASK (0x0000000f) -+ -+ -+/* defines to detect active host interface in use */ -+#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) -+ -+/* -+* Maximum delay for the PMU state transition in us. -+* This is an upper bound intended for spinwaits etc. -+*/ -+#define PMU_MAX_TRANSITION_DLY 20000 -+ -+/* PMU resource up transition time in ILP cycles */ -+#define PMURES_UP_TRANSITION 2 -+ -+/* -+* Information from BT to WLAN over eci_inputlo, eci_inputmi & -+* eci_inputhi register. Rev >=21 -+*/ -+/* Fields in eci_inputlo register - [0:31] */ -+#define ECI_INLO_TASKTYPE_MASK 0x0000000f /* [3:0] - 4 bits */ -+#define ECI_INLO_TASKTYPE_SHIFT 0 -+#define ECI_INLO_PKTDUR_MASK 0x000000f0 /* [7:4] - 4 bits */ -+#define ECI_INLO_PKTDUR_SHIFT 4 -+#define ECI_INLO_ROLE_MASK 0x00000100 /* [8] - 1 bits */ -+#define ECI_INLO_ROLE_SHIFT 8 -+#define ECI_INLO_MLP_MASK 0x00000e00 /* [11:9] - 3 bits */ -+#define ECI_INLO_MLP_SHIFT 9 -+#define ECI_INLO_TXPWR_MASK 0x000ff000 /* [19:12] - 8 bits */ -+#define ECI_INLO_TXPWR_SHIFT 12 -+#define ECI_INLO_RSSI_MASK 0x0ff00000 /* [27:20] - 8 bits */ -+#define ECI_INLO_RSSI_SHIFT 20 -+#define ECI_INLO_VAD_MASK 0x10000000 /* [28] - 1 bits */ -+#define ECI_INLO_VAD_SHIFT 28 -+ -+/* -+* Register eci_inputlo bitfield values. -+* - BT packet type information bits [7:0] -+*/ -+/* [3:0] - Task (link) type */ -+#define BT_ACL 0x00 -+#define BT_SCO 0x01 -+#define BT_eSCO 0x02 -+#define BT_A2DP 0x03 -+#define BT_SNIFF 0x04 -+#define BT_PAGE_SCAN 0x05 -+#define BT_INQUIRY_SCAN 0x06 -+#define BT_PAGE 0x07 -+#define BT_INQUIRY 0x08 -+#define BT_MSS 0x09 -+#define BT_PARK 0x0a -+#define BT_RSSISCAN 0x0b -+#define BT_MD_ACL 0x0c -+#define BT_MD_eSCO 0x0d -+#define BT_SCAN_WITH_SCO_LINK 0x0e -+#define BT_SCAN_WITHOUT_SCO_LINK 0x0f -+/* [7:4] = packet duration code */ -+/* [8] - Master / Slave */ -+#define BT_MASTER 0 -+#define BT_SLAVE 1 -+/* [11:9] - multi-level priority */ -+#define BT_LOWEST_PRIO 0x0 -+#define BT_HIGHEST_PRIO 0x3 -+/* [19:12] - BT transmit power */ -+/* [27:20] - BT RSSI */ -+/* [28] - VAD silence */ -+/* [31:29] - Undefined */ -+/* Register eci_inputmi values - [32:63] - none defined */ -+/* [63:32] - Undefined */ -+ -+/* Information from WLAN to BT over eci_output register. */ -+/* Fields in eci_output register - [0:31] */ -+#define ECI48_OUT_MASKMAGIC_HIWORD 0x55550000 -+#define ECI_OUT_CHANNEL_MASK(ccrev) ((ccrev) < 35 ? 0xf : (ECI48_OUT_MASKMAGIC_HIWORD | 0xf000)) -+#define ECI_OUT_CHANNEL_SHIFT(ccrev) ((ccrev) < 35 ? 0 : 12) -+#define ECI_OUT_BW_MASK(ccrev) ((ccrev) < 35 ? 0x70 : (ECI48_OUT_MASKMAGIC_HIWORD | 0xe00)) -+#define ECI_OUT_BW_SHIFT(ccrev) ((ccrev) < 35 ? 4 : 9) -+#define ECI_OUT_ANTENNA_MASK(ccrev) ((ccrev) < 35 ? 0x80 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x100)) -+#define ECI_OUT_ANTENNA_SHIFT(ccrev) ((ccrev) < 35 ? 7 : 8) -+#define ECI_OUT_SIMUL_TXRX_MASK(ccrev) \ -+ ((ccrev) < 35 ? 0x10000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x80)) -+#define ECI_OUT_SIMUL_TXRX_SHIFT(ccrev) ((ccrev) < 35 ? 16 : 7) -+#define ECI_OUT_FM_DISABLE_MASK(ccrev) \ -+ ((ccrev) < 35 ? 0x40000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x40)) -+#define ECI_OUT_FM_DISABLE_SHIFT(ccrev) ((ccrev) < 35 ? 18 : 6) -+ -+/* Indicate control of ECI bits between s/w and dot11mac. -+ * 0 => FW control, 1=> MAC/ucode control -+ -+ * Current assignment (ccrev >= 35): -+ * 0 - TxConf (ucode) -+ * 38 - FM disable (wl) -+ * 39 - Allow sim rx (ucode) -+ * 40 - Num antennas (wl) -+ * 43:41 - WLAN channel exclusion BW (wl) -+ * 47:44 - WLAN channel (wl) -+ * -+ * (ccrev < 35) -+ * 15:0 - wl -+ * 16 - -+ * 18 - FM disable -+ * 30 - wl interrupt -+ * 31 - ucode interrupt -+ * others - unassigned (presumed to be with dot11mac/ucode) -+ */ -+#define ECI_MACCTRL_BITS 0xbffb0000 -+#define ECI_MACCTRLLO_BITS 0x1 -+#define ECI_MACCTRLHI_BITS 0xFF -+ -+/* SECI configuration */ -+#define SECI_MODE_UART 0x0 -+#define SECI_MODE_SECI 0x1 -+#define SECI_MODE_LEGACY_3WIRE_BT 0x2 -+#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 -+#define SECI_MODE_HALF_SECI 0x4 -+ -+#define SECI_RESET (1 << 0) -+#define SECI_RESET_BAR_UART (1 << 1) -+#define SECI_ENAB_SECI_ECI (1 << 2) -+#define SECI_ENAB_SECIOUT_DIS (1 << 3) -+#define SECI_MODE_MASK 0x7 -+#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ -+#define SECI_UPD_SECI (1 << 7) -+ -+#define SECI_SIGNOFF_0 0xDB -+#define SECI_SIGNOFF_1 0 -+ -+/* seci clk_ctl_st bits */ -+#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) -+#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) -+ -+#define SECI_UART_MSR_CTS_STATE (1 << 0) -+#define SECI_UART_MSR_RTS_STATE (1 << 1) -+#define SECI_UART_SECI_IN_STATE (1 << 2) -+#define SECI_UART_SECI_IN2_STATE (1 << 3) -+ -+/* SECI UART LCR/MCR register bits */ -+#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */ -+#define SECI_UART_LCR_PARITY_EN (1 << 1) -+#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */ -+#define SECI_UART_LCR_RX_EN (1 << 3) -+#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */ -+#define SECI_UART_LCR_TXO_EN (1 << 5) -+#define SECI_UART_LCR_RTSO_EN (1 << 6) -+#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) -+#define SECI_UART_LCR_RXCRC_CHK (1 << 8) -+#define SECI_UART_LCR_TXCRC_INV (1 << 9) -+#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) -+#define SECI_UART_LCR_TXCRC_EN (1 << 11) -+ -+#define SECI_UART_MCR_TX_EN (1 << 0) -+#define SECI_UART_MCR_PRTS (1 << 1) -+#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) -+#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) -+#define SECI_UART_MCR_LOOPBK_EN (1 << 4) -+#define SECI_UART_MCR_AUTO_RTS (1 << 5) -+#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) -+#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) -+#define SECI_UART_MCR_XONOFF_RPT (1 << 9) -+ -+/* WLAN channel numbers - used from wifi.h */ -+ -+/* WLAN BW */ -+#define ECI_BW_20 0x0 -+#define ECI_BW_25 0x1 -+#define ECI_BW_30 0x2 -+#define ECI_BW_35 0x3 -+#define ECI_BW_40 0x4 -+#define ECI_BW_45 0x5 -+#define ECI_BW_50 0x6 -+#define ECI_BW_ALL 0x7 -+ -+/* WLAN - number of antenna */ -+#define WLAN_NUM_ANT1 TXANT_0 -+#define WLAN_NUM_ANT2 TXANT_1 -+ -+#endif /* _SBCHIPC_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sbconfig.h b/drivers/net/ethernet/broadcom/gmac/src/include/sbconfig.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sbconfig.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sbconfig.h 2017-11-09 17:53:44.005292000 +0800 -@@ -0,0 +1,276 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom SiliconBackplane hardware register definitions. -+ * -+ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $ -+ */ -+ -+#ifndef _SBCONFIG_H -+#define _SBCONFIG_H -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif -+ -+/* enumeration in SB is based on the premise that cores are contiguos in the -+ * enumeration space. -+ */ -+#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */ -+#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) -+#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */ -+ -+/* -+ * Sonics Configuration Space Registers. -+ */ -+#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ -+#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ -+ -+#define SBIPSFLAG 0x08 -+#define SBTPSFLAG 0x18 -+#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ -+#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ -+#define SBADMATCH3 0x60 -+#define SBADMATCH2 0x68 -+#define SBADMATCH1 0x70 -+#define SBIMSTATE 0x90 -+#define SBINTVEC 0x94 -+#define SBTMSTATELOW 0x98 -+#define SBTMSTATEHIGH 0x9c -+#define SBBWA0 0xa0 -+#define SBIMCONFIGLOW 0xa8 -+#define SBIMCONFIGHIGH 0xac -+#define SBADMATCH0 0xb0 -+#define SBTMCONFIGLOW 0xb8 -+#define SBTMCONFIGHIGH 0xbc -+#define SBBCONFIG 0xc0 -+#define SBBSTATE 0xc8 -+#define SBACTCNFG 0xd8 -+#define SBFLAGST 0xe8 -+#define SBIDLOW 0xf8 -+#define SBIDHIGH 0xfc -+ -+/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have -+ * a few registers *below* that line. I think it would be very confusing to try -+ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, -+ */ -+ -+#define SBIMERRLOGA 0xea8 -+#define SBIMERRLOG 0xeb0 -+#define SBTMPORTCONNID0 0xed8 -+#define SBTMPORTLOCK0 0xef8 -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+typedef volatile struct _sbconfig { -+ uint32 PAD[2]; -+ uint32 sbipsflag; /* initiator port ocp slave flag */ -+ uint32 PAD[3]; -+ uint32 sbtpsflag; /* target port ocp slave flag */ -+ uint32 PAD[11]; -+ uint32 sbtmerrloga; /* (sonics >= 2.3) */ -+ uint32 PAD; -+ uint32 sbtmerrlog; /* (sonics >= 2.3) */ -+ uint32 PAD[3]; -+ uint32 sbadmatch3; /* address match3 */ -+ uint32 PAD; -+ uint32 sbadmatch2; /* address match2 */ -+ uint32 PAD; -+ uint32 sbadmatch1; /* address match1 */ -+ uint32 PAD[7]; -+ uint32 sbimstate; /* initiator agent state */ -+ uint32 sbintvec; /* interrupt mask */ -+ uint32 sbtmstatelow; /* target state */ -+ uint32 sbtmstatehigh; /* target state */ -+ uint32 sbbwa0; /* bandwidth allocation table0 */ -+ uint32 PAD; -+ uint32 sbimconfiglow; /* initiator configuration */ -+ uint32 sbimconfighigh; /* initiator configuration */ -+ uint32 sbadmatch0; /* address match0 */ -+ uint32 PAD; -+ uint32 sbtmconfiglow; /* target configuration */ -+ uint32 sbtmconfighigh; /* target configuration */ -+ uint32 sbbconfig; /* broadcast configuration */ -+ uint32 PAD; -+ uint32 sbbstate; /* broadcast state */ -+ uint32 PAD[3]; -+ uint32 sbactcnfg; /* activate configuration */ -+ uint32 PAD[3]; -+ uint32 sbflagst; /* current sbflags */ -+ uint32 PAD[3]; -+ uint32 sbidlow; /* identification */ -+ uint32 sbidhigh; /* identification */ -+} sbconfig_t; -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+/* sbipsflag */ -+#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ -+#define SBIPS_INT1_SHIFT 0 -+#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ -+#define SBIPS_INT2_SHIFT 8 -+#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ -+#define SBIPS_INT3_SHIFT 16 -+#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ -+#define SBIPS_INT4_SHIFT 24 -+ -+/* sbtpsflag */ -+#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ -+#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ -+ -+/* sbtmerrlog */ -+#define SBTMEL_CM 0x00000007 /* command */ -+#define SBTMEL_CI 0x0000ff00 /* connection id */ -+#define SBTMEL_EC 0x0f000000 /* error code */ -+#define SBTMEL_ME 0x80000000 /* multiple error */ -+ -+/* sbimstate */ -+#define SBIM_PC 0xf /* pipecount */ -+#define SBIM_AP_MASK 0x30 /* arbitration policy */ -+#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ -+#define SBIM_AP_TS 0x10 /* use timesliaces only */ -+#define SBIM_AP_TK 0x20 /* use token only */ -+#define SBIM_AP_RSV 0x30 /* reserved */ -+#define SBIM_IBE 0x20000 /* inbanderror */ -+#define SBIM_TO 0x40000 /* timeout */ -+#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ -+#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ -+ -+/* sbtmstatelow */ -+#define SBTML_RESET 0x0001 /* reset */ -+#define SBTML_REJ_MASK 0x0006 /* reject field */ -+#define SBTML_REJ 0x0002 /* reject */ -+#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ -+ -+#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ -+ -+/* sbtmstatehigh */ -+#define SBTMH_SERR 0x0001 /* serror */ -+#define SBTMH_INT 0x0002 /* interrupt */ -+#define SBTMH_BUSY 0x0004 /* busy */ -+#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ -+ -+#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ -+ -+/* sbbwa0 */ -+#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ -+#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ -+#define SBBWA_TAB1_SHIFT 16 -+ -+/* sbimconfiglow */ -+#define SBIMCL_STO_MASK 0x7 /* service timeout */ -+#define SBIMCL_RTO_MASK 0x70 /* request timeout */ -+#define SBIMCL_RTO_SHIFT 4 -+#define SBIMCL_CID_MASK 0xff0000 /* connection id */ -+#define SBIMCL_CID_SHIFT 16 -+ -+/* sbimconfighigh */ -+#define SBIMCH_IEM_MASK 0xc /* inband error mode */ -+#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ -+#define SBIMCH_TEM_SHIFT 4 -+#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ -+#define SBIMCH_BEM_SHIFT 6 -+ -+/* sbadmatch0 */ -+#define SBAM_TYPE_MASK 0x3 /* address type */ -+#define SBAM_AD64 0x4 /* reserved */ -+#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ -+#define SBAM_ADINT0_SHIFT 3 -+#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ -+#define SBAM_ADINT1_SHIFT 3 -+#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ -+#define SBAM_ADINT2_SHIFT 3 -+#define SBAM_ADEN 0x400 /* enable */ -+#define SBAM_ADNEG 0x800 /* negative decode */ -+#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ -+#define SBAM_BASE0_SHIFT 8 -+#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ -+#define SBAM_BASE1_SHIFT 12 -+#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ -+#define SBAM_BASE2_SHIFT 16 -+ -+/* sbtmconfiglow */ -+#define SBTMCL_CD_MASK 0xff /* clock divide */ -+#define SBTMCL_CO_MASK 0xf800 /* clock offset */ -+#define SBTMCL_CO_SHIFT 11 -+#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ -+#define SBTMCL_IF_SHIFT 18 -+#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ -+#define SBTMCL_IM_SHIFT 24 -+ -+/* sbtmconfighigh */ -+#define SBTMCH_BM_MASK 0x3 /* busy mode */ -+#define SBTMCH_RM_MASK 0x3 /* retry mode */ -+#define SBTMCH_RM_SHIFT 2 -+#define SBTMCH_SM_MASK 0x30 /* stop mode */ -+#define SBTMCH_SM_SHIFT 4 -+#define SBTMCH_EM_MASK 0x300 /* sb error mode */ -+#define SBTMCH_EM_SHIFT 8 -+#define SBTMCH_IM_MASK 0xc00 /* int mode */ -+#define SBTMCH_IM_SHIFT 10 -+ -+/* sbbconfig */ -+#define SBBC_LAT_MASK 0x3 /* sb latency */ -+#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ -+#define SBBC_MAX0_SHIFT 16 -+#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ -+#define SBBC_MAX1_SHIFT 20 -+ -+/* sbbstate */ -+#define SBBS_SRD 0x1 /* st reg disable */ -+#define SBBS_HRD 0x2 /* hold reg disable */ -+ -+/* sbidlow */ -+#define SBIDL_CS_MASK 0x3 /* config space */ -+#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ -+#define SBIDL_AR_SHIFT 3 -+#define SBIDL_SYNCH 0x40 /* sync */ -+#define SBIDL_INIT 0x80 /* initiator */ -+#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ -+#define SBIDL_MINLAT_SHIFT 8 -+#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ -+#define SBIDL_MAXLAT_SHIFT 12 -+#define SBIDL_FIRST 0x10000 /* this initiator is first */ -+#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ -+#define SBIDL_CW_SHIFT 18 -+#define SBIDL_TP_MASK 0xf00000 /* target ports */ -+#define SBIDL_TP_SHIFT 20 -+#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ -+#define SBIDL_IP_SHIFT 24 -+#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ -+#define SBIDL_RV_SHIFT 28 -+#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ -+#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ -+ -+/* sbidhigh */ -+#define SBIDH_RC_MASK 0x000f /* revision code */ -+#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ -+#define SBIDH_RCE_SHIFT 8 -+#define SBCOREREV(sbidh) \ -+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) -+#define SBIDH_CC_MASK 0x8ff0 /* core code */ -+#define SBIDH_CC_SHIFT 4 -+#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ -+#define SBIDH_VC_SHIFT 16 -+ -+#define SB_COMMIT 0xfd8 /* update buffered registers value */ -+ -+/* vendor codes */ -+#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ -+ -+#endif /* _SBCONFIG_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sbhndarm.h b/drivers/net/ethernet/broadcom/gmac/src/include/sbhndarm.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sbhndarm.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sbhndarm.h 2017-11-09 17:53:44.005307000 +0800 -@@ -0,0 +1,293 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom SiliconBackplane ARM definitions -+ * -+ * $Id: sbhndarm.h 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#ifndef _sbhndarm_h_ -+#define _sbhndarm_h_ -+ -+#include -+#include -+ -+/* register offsets */ -+#define ARM7_CORECTL 0 -+ -+/* bits in corecontrol */ -+#define ACC_FORCED_RST 0x1 -+#define ACC_SERRINT 0x2 -+#define ACC_NOTSLEEPINGCLKREQ_SHIFT 24 -+ -+/* arm resetlog */ -+#define SBRESETLOG 0x1 -+#define SERRORLOG 0x2 -+ -+/* arm core-specific control flags */ -+#define SICF_REMAP_MSK 0x001c -+#define SICF_REMAP_NONE 0 -+#define SICF_REMAP_ROM 0x0004 -+#define SIFC_REMAP_FLASH 0x0008 -+ -+/* misc core-specific defines */ -+#if defined(__ARM_ARCH_4T__) -+/* arm7tdmi-s */ -+/* backplane related stuff */ -+#define ARM_CORE_ID ARM7S_CORE_ID /* arm coreid */ -+#define SI_ARM_ROM SI_ARM7S_ROM /* ROM backplane/system address */ -+#define SI_ARM_SRAM2 SI_ARM7S_SRAM2 /* RAM backplane address when remap is 1 or 2 */ -+#elif defined(__ARM_ARCH_7M__) -+/* cortex-m3 */ -+/* backplane related stuff */ -+#define ARM_CORE_ID ARMCM3_CORE_ID /* arm coreid */ -+#define SI_ARM_ROM SI_ARMCM3_ROM /* ROM backplane/system address */ -+#define SI_ARM_SRAM2 SI_ARMCM3_SRAM2 /* RAM backplane address when remap is 1 or 2 */ -+/* core registers offsets */ -+#define ARMCM3_CYCLECNT 0x90 /* Cortex-M3 core registers offsets */ -+#define ARMCM3_INTTIMER 0x94 -+#define ARMCM3_INTMASK 0x98 -+#define ARMCM3_INTSTATUS 0x9c -+/* interrupt/exception */ -+#define ARMCM3_NUMINTS 16 /* # of external interrupts */ -+#define ARMCM3_INTALL ((1 << ARMCM3_NUMINTS) - 1) /* Interrupt mask */ -+#define ARMCM3_FAULTMASK 0x40000000 /* Master fault enable/disable */ -+#define ARMCM3_PRIMASK 0x80000000 /* Master interrupt enable/disable */ -+#define ARMCM3_SHARED_INT 0 /* Interrupt shared by multiple cores */ -+#define ARMCM3_INT(i) (1 << (i)) /* Individual interrupt enable/disable */ -+/* compatible with arm7tdmi-s */ -+#define PS_I ARMCM3_PRIMASK -+#define PS_F ARMCM3_FAULTMASK -+/* intmask/intstatus bits */ -+#define ARMCM3_INTMASK_TIMER 0x1 -+#define ARMCM3_INTMASK_SYSRESET 0x4 -+#define ARMCM3_INTMASK_LOCKUP 0x8 -+ -+/* -+ * Overlay Support in Rev 5 -+ */ -+#define ARMCM3_OVL_VALID_SHIFT 0 -+#define ARMCM3_OVL_VALID 1 -+#define ARMCM3_OVL_SZ_SHIFT 1 -+#define ARMCM3_OVL_SZ_MASK 0x0000000e -+#define ARMCM3_OVL_SZ_512B 0 /* 512B */ -+#define ARMCM3_OVL_SZ_1KB 1 /* 1KB */ -+#define ARMCM3_OVL_SZ_2KB 2 /* 2KB */ -+#define ARMCM3_OVL_SZ_4KB 3 /* 4KB */ -+#define ARMCM3_OVL_SZ_8KB 4 /* 8KB */ -+#define ARMCM3_OVL_SZ_16KB 5 /* 16KB */ -+#define ARMCM3_OVL_SZ_32KB 6 /* 32KB */ -+#define ARMCM3_OVL_SZ_64KB 7 /* 64KB */ -+#define ARMCM3_OVL_ADDR_SHIFT 9 -+#define ARMCM3_OVL_ADDR_MASK 0x003FFE00 -+#define ARMCM3_OVL_MAX 16 -+ -+#elif defined(__ARM_ARCH_7R__) -+/* cortex-r4 */ -+/* backplane related stuff */ -+#define ARM_CORE_ID ARMCR4_CORE_ID /* arm coreid */ -+#define SI_ARM_ROM SI_ARMCR4_ROM /* ROM backplane/system address */ -+#define SI_ARM_SRAM2 0x0 /* In the cr4 the RAM is just not available -+ * when remap is 1 -+ */ -+ -+/* core registers offsets */ -+#define ARMCR4_CORECTL 0 -+#define ARMCR4_CORECAP 4 -+#define ARMCR4_COREST 8 -+ -+#define ARMCR4_FIQRSTATUS 0x10 -+#define ARMCR4_FIQMASK 0x14 -+#define ARMCR4_IRQMASK 0x18 -+ -+#define ARMCR4_INTSTATUS 0x20 -+#define ARMCR4_INTMASK 0x24 -+#define ARMCR4_CYCLECNT 0x28 -+#define ARMCR4_INTTIMER 0x2c -+ -+#define ARMCR4_GPIOSEL 0x30 -+#define ARMCR4_GPIOEN 0x34 -+ -+#define ARMCR4_BANKIDX 0x40 -+#define ARMCR4_BANKINFO 0x44 -+#define ARMCR4_BANKSTBY 0x48 -+#define ARMCR4_BANKPDA 0x4c -+ -+#define ARMCR4_TCAMPATCHCTRL 0x68 -+#define ARMCR4_TCAMPATCHTBLBASEADDR 0x6C -+#define ARMCR4_TCAMCMDREG 0x70 -+#define ARMCR4_TCAMDATAREG 0x74 -+#define ARMCR4_TCAMBANKXMASKREG 0x78 -+ -+#define ARMCR4_ROMNB_MASK 0xf00 -+#define ARMCR4_ROMNB_SHIFT 8 -+#define ARMCR4_TCBBNB_MASK 0xf0 -+#define ARMCR4_TCBBNB_SHIFT 4 -+#define ARMCR4_TCBANB_MASK 0xf -+#define ARMCR4_TCBANB_SHIFT 0 -+ -+#define ARMCR4_MT_MASK 0x300 -+#define ARMCR4_MT_SHIFT 8 -+#define ARMCR4_MT_ROM 0x100 -+#define ARMCR4_MT_RAM 0 -+ -+#define ARMCR4_BSZ_MASK 0x3f -+#define ARMCR4_BSZ_MULT 8192 -+ -+#define ARMCR4_TCAM_ENABLE (1 << 31) -+#define ARMCR4_TCAM_CLKENAB (1 << 30) -+#define ARMCR4_TCAM_PATCHCNT_MASK 0xf -+ -+#define ARMCR4_TCAM_CMD_DONE (1 << 31) -+#define ARMCR4_TCAM_MATCH (1 << 24) -+#define ARMCR4_TCAM_OPCODE_MASK (3 << 16) -+#define ARMCR4_TCAM_OPCODE_SHIFT 16 -+#define ARMCR4_TCAM_ADDR_MASK 0xffff -+#define ARMCR4_TCAM_NONE (0 << ARMCR4_TCAM_OPCODE_SHIFT) -+#define ARMCR4_TCAM_READ (1 << ARMCR4_TCAM_OPCODE_SHIFT) -+#define ARMCR4_TCAM_WRITE (2 << ARMCR4_TCAM_OPCODE_SHIFT) -+#define ARMCR4_TCAM_COMPARE (3 << ARMCR4_TCAM_OPCODE_SHIFT) -+#define ARMCR4_TCAM_CMD_DONE_DLY 1000 -+ -+#define ARMCR4_DATA_MASK (~0x7) -+#define ARMCR4_DATA_VALID (1 << 0) -+ -+ -+/* arm core-specific conrol flags */ -+#define SICF_CPUHALT 0x0020 -+#define SICF_UPDATEFW 0x0040 -+ -+/* arm core-specific status flags */ -+#define SISF_SDRENABLE 0x0001 -+#define SISF_TCMPROT 0x0002 -+ -+#define CHIP_SDRENABLE(sih) (sih->boardflags2 & BFL2_SDR_EN) -+#define CHIP_TCMPROTENAB(sih) (si_arm_sflags(sih) & SISF_TCMPROT) -+ -+#elif defined(__ARM_ARCH_7A__) -+/* backplane related stuff */ -+#define ARM_CORE_ID ARMCA9_CORE_ID /* arm coreid */ -+ -+#else /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ -+#error Unrecognized ARM Architecture -+#endif /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+#if defined(__ARM_ARCH_4T__) -+/* arm7tdmi-s */ -+typedef volatile struct { -+ uint32 corecontrol; /* 0 */ -+ uint32 sleepcontrol; /* 4 */ -+ uint32 PAD; -+ uint32 biststatus; /* 0xc */ -+ uint32 firqstatus; /* 0x10 */ -+ uint32 fiqmask; /* 0x14 */ -+ uint32 irqmask; /* 0x18 */ -+ uint32 PAD; -+ uint32 resetlog; /* 0x20 */ -+ uint32 gpioselect; /* 0x24 */ -+ uint32 gpioenable; /* 0x28 */ -+ uint32 PAD; -+ uint32 bpaddrlo; /* 0x30 */ -+ uint32 bpaddrhi; /* 0x34 */ -+ uint32 bpdata; /* 0x38 */ -+ uint32 bpindaccess; /* 0x3c */ -+ uint32 PAD[104]; -+ uint32 clk_ctl_st; /* 0x1e0 */ -+ uint32 hw_war; /* 0x1e4 */ -+} armregs_t; -+#define ARMREG(regs, reg) (&((armregs_t *)regs)->reg) -+#endif /* __ARM_ARCH_4T__ */ -+ -+#if defined(__ARM_ARCH_7M__) -+/* cortex-m3 */ -+typedef volatile struct { -+ uint32 corecontrol; /* 0x0 */ -+ uint32 corestatus; /* 0x4 */ -+ uint32 PAD[1]; -+ uint32 biststatus; /* 0xc */ -+ uint32 nmiisrst; /* 0x10 */ -+ uint32 nmimask; /* 0x14 */ -+ uint32 isrmask; /* 0x18 */ -+ uint32 PAD[1]; -+ uint32 resetlog; /* 0x20 */ -+ uint32 gpioselect; /* 0x24 */ -+ uint32 gpioenable; /* 0x28 */ -+ uint32 PAD[1]; -+ uint32 bpaddrlo; /* 0x30 */ -+ uint32 bpaddrhi; /* 0x34 */ -+ uint32 bpdata; /* 0x38 */ -+ uint32 bpindaccess; /* 0x3c */ -+ uint32 ovlidx; /* 0x40 */ -+ uint32 ovlmatch; /* 0x44 */ -+ uint32 ovladdr; /* 0x48 */ -+ uint32 PAD[13]; -+ uint32 bwalloc; /* 0x80 */ -+ uint32 PAD[3]; -+ uint32 cyclecnt; /* 0x90 */ -+ uint32 inttimer; /* 0x94 */ -+ uint32 intmask; /* 0x98 */ -+ uint32 intstatus; /* 0x9c */ -+ uint32 PAD[80]; -+ uint32 clk_ctl_st; /* 0x1e0 */ -+} cm3regs_t; -+#define ARMREG(regs, reg) (&((cm3regs_t *)regs)->reg) -+#endif /* __ARM_ARCH_7M__ */ -+ -+#if defined(__ARM_ARCH_7R__) -+/* cortex-R4 */ -+typedef volatile struct { -+ uint32 corecontrol; /* 0x0 */ -+ uint32 corecapabilities; /* 0x4 */ -+ uint32 corestatus; /* 0x8 */ -+ uint32 biststatus; /* 0xc */ -+ uint32 nmiisrst; /* 0x10 */ -+ uint32 nmimask; /* 0x14 */ -+ uint32 isrmask; /* 0x18 */ -+ uint32 PAD[1]; -+ uint32 intstatus; /* 0x20 */ -+ uint32 intmask; /* 0x24 */ -+ uint32 cyclecnt; /* 0x28 */ -+ uint32 inttimer; /* 0x2c */ -+ uint32 gpioselect; /* 0x30 */ -+ uint32 gpioenable; /* 0x34 */ -+ uint32 PAD[2]; -+ uint32 bankidx; /* 0x40 */ -+ uint32 bankinfo; /* 0x44 */ -+ uint32 bankstbyctl; /* 0x48 */ -+ uint32 bankpda; /* 0x4c */ -+ uint32 PAD[6]; -+ uint32 tcampatchctrl; /* 0x68 */ -+ uint32 tcampatchtblbaseaddr; /* 0x6c */ -+ uint32 tcamcmdreg; /* 0x70 */ -+ uint32 tcamdatareg; /* 0x74 */ -+ uint32 tcambankxmaskreg; /* 0x78 */ -+ uint32 PAD[89]; -+ uint32 clk_ctl_st; /* 0x1e0 */ -+} cr4regs_t; -+#define ARMREG(regs, reg) (&((cr4regs_t *)regs)->reg) -+#endif /* __ARM_ARCH_7R__ */ -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+#endif /* _sbhndarm_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sbhnddma.h b/drivers/net/ethernet/broadcom/gmac/src/include/sbhnddma.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sbhnddma.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sbhnddma.h 2017-11-09 17:53:44.006300000 +0800 -@@ -0,0 +1,403 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * $Id: sbhnddma.h 321146 2012-03-14 08:27:23Z $ -+ */ -+ -+#ifndef _sbhnddma_h_ -+#define _sbhnddma_h_ -+ -+/* DMA structure: -+ * support two DMA engines: 32 bits address or 64 bit addressing -+ * basic DMA register set is per channel(transmit or receive) -+ * a pair of channels is defined for convenience -+ */ -+ -+ -+/* 32 bits addressing */ -+ -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 addr; /* descriptor ring base address (4K aligned) */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 status; /* current active descriptor, et al */ -+} dma32regs_t; -+ -+typedef volatile struct { -+ dma32regs_t xmt; /* dma tx channel */ -+ dma32regs_t rcv; /* dma rx channel */ -+} dma32regp_t; -+ -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma32diag_t; -+ -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+typedef volatile struct { -+ uint32 ctrl; /* misc control bits & bufcount */ -+ uint32 addr; /* data buffer address */ -+} dma32dd_t; -+ -+/* -+ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. -+ */ -+#define D32RINGALIGN_BITS 12 -+#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) -+#define D32RINGALIGN (1 << D32RINGALIGN_BITS) -+ -+#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) -+ -+/* transmit channel control */ -+#define XC_XE ((uint32)1 << 0) /* transmit enable */ -+#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ -+#define XC_LE ((uint32)1 << 2) /* loopback enable */ -+#define XC_FL ((uint32)1 << 4) /* flush request */ -+#define XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ -+#define XC_MR_SHIFT 6 -+#define XC_PD ((uint32)1 << 11) /* parity check disable */ -+#define XC_AE ((uint32)3 << 16) /* address extension bits */ -+#define XC_AE_SHIFT 16 -+#define XC_BL_MASK 0x001C0000 /* BurstLen bits */ -+#define XC_BL_SHIFT 18 -+#define XC_PC_MASK 0x00E00000 /* Prefetch control */ -+#define XC_PC_SHIFT 21 -+#define XC_PT_MASK 0x03000000 /* Prefetch threshold */ -+#define XC_PT_SHIFT 24 -+ -+/* Multiple outstanding reads */ -+#define DMA_MR_1 0 -+#define DMA_MR_2 1 -+/* 2, 3: reserved */ -+ -+/* DMA Burst Length in bytes */ -+#define DMA_BL_16 0 -+#define DMA_BL_32 1 -+#define DMA_BL_64 2 -+#define DMA_BL_128 3 -+#define DMA_BL_256 4 -+#define DMA_BL_512 5 -+#define DMA_BL_1024 6 -+ -+/* Prefetch control */ -+#define DMA_PC_0 0 -+#define DMA_PC_4 1 -+#define DMA_PC_8 2 -+#define DMA_PC_16 3 -+/* others: reserved */ -+ -+/* Prefetch threshold */ -+#define DMA_PT_1 0 -+#define DMA_PT_2 1 -+#define DMA_PT_4 2 -+#define DMA_PT_8 3 -+ -+/* transmit descriptor table pointer */ -+#define XP_LD_MASK 0xfff /* last valid descriptor */ -+ -+/* transmit channel status */ -+#define XS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define XS_XS_MASK 0xf000 /* transmit state */ -+#define XS_XS_SHIFT 12 -+#define XS_XS_DISABLED 0x0000 /* disabled */ -+#define XS_XS_ACTIVE 0x1000 /* active */ -+#define XS_XS_IDLE 0x2000 /* idle wait */ -+#define XS_XS_STOPPED 0x3000 /* stopped */ -+#define XS_XS_SUSP 0x4000 /* suspend pending */ -+#define XS_XE_MASK 0xf0000 /* transmit errors */ -+#define XS_XE_SHIFT 16 -+#define XS_XE_NOERR 0x00000 /* no error */ -+#define XS_XE_DPE 0x10000 /* descriptor protocol error */ -+#define XS_XE_DFU 0x20000 /* data fifo underrun */ -+#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ -+#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ -+#define XS_AD_MASK 0xfff00000 /* active descriptor */ -+#define XS_AD_SHIFT 20 -+ -+/* receive channel control */ -+#define RC_RE ((uint32)1 << 0) /* receive enable */ -+#define RC_RO_MASK 0xfe /* receive frame offset */ -+#define RC_RO_SHIFT 1 -+#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ -+#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */ -+#define RC_OC ((uint32)1 << 10) /* overflow continue */ -+#define RC_PD ((uint32)1 << 11) /* parity check disable */ -+#define RC_AE ((uint32)3 << 16) /* address extension bits */ -+#define RC_AE_SHIFT 16 -+#define RC_BL_MASK 0x001C0000 /* BurstLen bits */ -+#define RC_BL_SHIFT 18 -+#define RC_PC_MASK 0x00E00000 /* Prefetch control */ -+#define RC_PC_SHIFT 21 -+#define RC_PT_MASK 0x03000000 /* Prefetch threshold */ -+#define RC_PT_SHIFT 24 -+ -+/* receive descriptor table pointer */ -+#define RP_LD_MASK 0xfff /* last valid descriptor */ -+ -+/* receive channel status */ -+#define RS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define RS_RS_MASK 0xf000 /* receive state */ -+#define RS_RS_SHIFT 12 -+#define RS_RS_DISABLED 0x0000 /* disabled */ -+#define RS_RS_ACTIVE 0x1000 /* active */ -+#define RS_RS_IDLE 0x2000 /* idle wait */ -+#define RS_RS_STOPPED 0x3000 /* reserved */ -+#define RS_RE_MASK 0xf0000 /* receive errors */ -+#define RS_RE_SHIFT 16 -+#define RS_RE_NOERR 0x00000 /* no error */ -+#define RS_RE_DPE 0x10000 /* descriptor protocol error */ -+#define RS_RE_DFO 0x20000 /* data fifo overflow */ -+#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ -+#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ -+#define RS_AD_MASK 0xfff00000 /* active descriptor */ -+#define RS_AD_SHIFT 20 -+ -+/* fifoaddr */ -+#define FA_OFF_MASK 0xffff /* offset */ -+#define FA_SEL_MASK 0xf0000 /* select */ -+#define FA_SEL_SHIFT 16 -+#define FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define FA_SEL_RDD 0x40000 /* receive dma data */ -+#define FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ -+ -+/* descriptor control flags */ -+#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */ -+#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ -+#define CTRL_AE_SHIFT 16 -+#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */ -+#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ -+#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ -+ -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define CTRL_CORE_MASK 0x0ff00000 -+ -+/* 64 bits addressing */ -+ -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ -+ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ -+ uint32 status0; /* current descriptor, xmt state */ -+ uint32 status1; /* active descriptor, xmt error */ -+} dma64regs_t; -+ -+typedef volatile struct { -+ dma64regs_t tx; /* dma64 tx channel */ -+ dma64regs_t rx; /* dma64 rx channel */ -+} dma64regp_t; -+ -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma64diag_t; -+ -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+typedef volatile struct { -+ uint32 ctrl1; /* misc control bits */ -+ uint32 ctrl2; /* buffer count and address extension */ -+ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ -+ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ -+} dma64dd_t; -+ -+/* -+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. -+ */ -+#define D64RINGALIGN_BITS 13 -+#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) -+#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) -+ -+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) -+ -+/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */ -+#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) -+ -+/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross -+ * 64K boundary -+ */ -+#define D64RINGBOUNDARY_LARGE (1 << 16) -+ -+/* -+ * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11. -+ * When this field contains the value N, the burst length is 2**(N + 4) bytes. -+ */ -+#define D64_DEF_USBBURSTLEN 2 -+#define D64_DEF_SDIOBURSTLEN 1 -+ -+ -+#ifndef D64_USBBURSTLEN -+#define D64_USBBURSTLEN DMA_BL_64 -+#endif -+#ifndef D64_SDIOBURSTLEN -+#define D64_SDIOBURSTLEN DMA_BL_32 -+#endif -+ -+/* transmit channel control */ -+#define D64_XC_XE 0x00000001 /* transmit enable */ -+#define D64_XC_SE 0x00000002 /* transmit suspend request */ -+#define D64_XC_LE 0x00000004 /* loopback enable */ -+#define D64_XC_FL 0x00000010 /* flush request */ -+#define D64_XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ -+#define D64_XC_MR_SHIFT 6 -+#define D64_XC_PD 0x00000800 /* parity check disable */ -+#define D64_XC_AE 0x00030000 /* address extension bits */ -+#define D64_XC_AE_SHIFT 16 -+#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */ -+#define D64_XC_BL_SHIFT 18 -+#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */ -+#define D64_XC_PC_SHIFT 21 -+#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */ -+#define D64_XC_PT_SHIFT 24 -+ -+/* transmit descriptor table pointer */ -+#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ -+ -+/* transmit channel status */ -+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ -+#define D64_XS0_XS_SHIFT 28 -+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ -+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ -+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ -+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ -+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ -+ -+#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ -+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ -+#define D64_XS1_XE_SHIFT 28 -+#define D64_XS1_XE_NOERR 0x00000000 /* no error */ -+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ -+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ -+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ -+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_XS1_XE_COREE 0x50000000 /* core error */ -+ -+/* receive channel control */ -+#define D64_RC_RE 0x00000001 /* receive enable */ -+#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ -+#define D64_RC_RO_SHIFT 1 -+#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ -+#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ -+#define D64_RC_OC 0x00000400 /* overflow continue */ -+#define D64_RC_PD 0x00000800 /* parity check disable */ -+#define D64_RC_GE 0x00004000 /* Glom enable */ -+#define D64_RC_AE 0x00030000 /* address extension bits */ -+#define D64_RC_AE_SHIFT 16 -+#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ -+#define D64_RC_BL_SHIFT 18 -+#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */ -+#define D64_RC_PC_SHIFT 21 -+#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */ -+#define D64_RC_PT_SHIFT 24 -+ -+/* flags for dma controller */ -+#define DMA_CTRL_PEN (1 << 0) /* partity enable */ -+#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ -+#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ -+#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ -+#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) -+#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */ -+#define DMA_CTRL_RXSINGLE (1 << 6) /* always single buffer */ -+ -+/* receive descriptor table pointer */ -+#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ -+ -+/* receive channel status */ -+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ -+#define D64_RS0_RS_SHIFT 28 -+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ -+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ -+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ -+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ -+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ -+ -+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ -+#define D64_RS1_RE_SHIFT 28 -+#define D64_RS1_RE_NOERR 0x00000000 /* no error */ -+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ -+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ -+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ -+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_RS1_RE_COREE 0x50000000 /* core error */ -+ -+/* fifoaddr */ -+#define D64_FA_OFF_MASK 0xffff /* offset */ -+#define D64_FA_SEL_MASK 0xf0000 /* select */ -+#define D64_FA_SEL_SHIFT 16 -+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ -+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ -+ -+/* descriptor control flags 1 */ -+#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ -+#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ -+#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ -+ -+/* descriptor control flags 2 */ -+#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ -+#define D64_CTRL2_AE 0x00030000 /* address extension bits */ -+#define D64_CTRL2_AE_SHIFT 16 -+#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ -+ -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define D64_CTRL_CORE_MASK 0x0ff00000 -+ -+#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ -+#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ -+#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */ -+#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ -+ -+/* receive frame status */ -+typedef volatile struct { -+ uint16 len; -+ uint16 flags; -+} dma_rxh_t; -+ -+#endif /* _sbhnddma_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sbsocram.h b/drivers/net/ethernet/broadcom/gmac/src/include/sbsocram.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sbsocram.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sbsocram.h 2017-11-09 17:53:44.007303000 +0800 -@@ -0,0 +1,193 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * BCM47XX Sonics SiliconBackplane embedded ram core -+ * -+ * $Id: sbsocram.h 271781 2011-07-13 20:00:06Z $ -+ */ -+ -+#ifndef _SBSOCRAM_H -+#define _SBSOCRAM_H -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ -+ -+/* Memcsocram core registers */ -+typedef volatile struct sbsocramregs { -+ uint32 coreinfo; -+ uint32 bwalloc; -+ uint32 extracoreinfo; -+ uint32 biststat; -+ uint32 bankidx; -+ uint32 standbyctrl; -+ -+ uint32 errlogstatus; /* rev 6 */ -+ uint32 errlogaddr; /* rev 6 */ -+ /* used for patching rev 3 & 5 */ -+ uint32 cambankidx; -+ uint32 cambankstandbyctrl; -+ uint32 cambankpatchctrl; -+ uint32 cambankpatchtblbaseaddr; -+ uint32 cambankcmdreg; -+ uint32 cambankdatareg; -+ uint32 cambankmaskreg; -+ uint32 PAD[1]; -+ uint32 bankinfo; /* corev 8 */ -+ uint32 PAD[15]; -+ uint32 extmemconfig; -+ uint32 extmemparitycsr; -+ uint32 extmemparityerrdata; -+ uint32 extmemparityerrcnt; -+ uint32 extmemwrctrlandsize; -+ uint32 PAD[84]; -+ uint32 workaround; -+ uint32 pwrctl; /* corerev >= 2 */ -+ uint32 PAD[133]; -+ uint32 sr_control; /* corerev >= 15 */ -+ uint32 sr_status; /* corerev >= 15 */ -+ uint32 sr_address; /* corerev >= 15 */ -+ uint32 sr_data; /* corerev >= 15 */ -+} sbsocramregs_t; -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+/* Register offsets */ -+#define SR_COREINFO 0x00 -+#define SR_BWALLOC 0x04 -+#define SR_BISTSTAT 0x0c -+#define SR_BANKINDEX 0x10 -+#define SR_BANKSTBYCTL 0x14 -+#define SR_PWRCTL 0x1e8 -+ -+/* Coreinfo register */ -+#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */ -+#define SRCI_PT_SHIFT 16 -+/* port types : SRCI_PT__ */ -+#define SRCI_PT_OCP_OCP 0 -+#define SRCI_PT_AXI_OCP 1 -+#define SRCI_PT_ARM7AHB_OCP 2 -+#define SRCI_PT_CM3AHB_OCP 3 -+#define SRCI_PT_AXI_AXI 4 -+#define SRCI_PT_AHB_AXI 5 -+/* corerev >= 3 */ -+#define SRCI_LSS_MASK 0x00f00000 -+#define SRCI_LSS_SHIFT 20 -+#define SRCI_LRS_MASK 0x0f000000 -+#define SRCI_LRS_SHIFT 24 -+ -+/* In corerev 0, the memory size is 2 to the power of the -+ * base plus 16 plus to the contents of the memsize field plus 1. -+ */ -+#define SRCI_MS0_MASK 0xf -+#define SR_MS0_BASE 16 -+ -+/* -+ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, -+ * the memory size is number of banks times bank size. -+ * The same applies to rom size. -+ */ -+#define SRCI_ROMNB_MASK 0xf000 -+#define SRCI_ROMNB_SHIFT 12 -+#define SRCI_ROMBSZ_MASK 0xf00 -+#define SRCI_ROMBSZ_SHIFT 8 -+#define SRCI_SRNB_MASK 0xf0 -+#define SRCI_SRNB_SHIFT 4 -+#define SRCI_SRBSZ_MASK 0xf -+#define SRCI_SRBSZ_SHIFT 0 -+ -+#define SR_BSZ_BASE 14 -+ -+/* Standby control register */ -+#define SRSC_SBYOVR_MASK 0x80000000 -+#define SRSC_SBYOVR_SHIFT 31 -+#define SRSC_SBYOVRVAL_MASK 0x60000000 -+#define SRSC_SBYOVRVAL_SHIFT 29 -+#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */ -+#define SRSC_SBYEN_SHIFT 24 -+ -+/* Power control register */ -+#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */ -+#define SRPC_PMU_STBYDIS_SHIFT 4 -+#define SRPC_STBYOVRVAL_MASK 0x00000008 -+#define SRPC_STBYOVRVAL_SHIFT 3 -+#define SRPC_STBYOVR_MASK 0x00000007 -+#define SRPC_STBYOVR_SHIFT 0 -+ -+/* Extra core capability register */ -+#define SRECC_NUM_BANKS_MASK 0x000000F0 -+#define SRECC_NUM_BANKS_SHIFT 4 -+#define SRECC_BANKSIZE_MASK 0x0000000F -+#define SRECC_BANKSIZE_SHIFT 0 -+ -+#define SRECC_BANKSIZE(value) (1 << (value)) -+ -+/* CAM bank patch control */ -+#define SRCBPC_PATCHENABLE 0x80000000 -+ -+#define SRP_ADDRESS 0x0001FFFC -+#define SRP_VALID 0x8000 -+ -+/* CAM bank command reg */ -+#define SRCMD_WRITE 0x00020000 -+#define SRCMD_READ 0x00010000 -+#define SRCMD_DONE 0x80000000 -+ -+#define SRCMD_DONE_DLY 1000 -+ -+/* bankidx and bankinfo reg defines corerev >= 8 */ -+#define SOCRAM_BANKINFO_SZMASK 0x7f -+#define SOCRAM_BANKIDX_ROM_MASK 0x100 -+ -+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 -+/* socram bankinfo memtype */ -+#define SOCRAM_MEMTYPE_RAM 0 -+#define SOCRAM_MEMTYPE_R0M 1 -+#define SOCRAM_MEMTYPE_DEVRAM 2 -+ -+#define SOCRAM_BANKINFO_REG 0x40 -+#define SOCRAM_BANKIDX_REG 0x10 -+#define SOCRAM_BANKINFO_STDBY_MASK 0x400 -+#define SOCRAM_BANKINFO_STDBY_TIMER 0x800 -+ -+/* bankinfo rev >= 10 */ -+#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13 -+#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000 -+#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14 -+#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000 -+#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15 -+#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000 -+#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16 -+#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 -+#define SOCRAM_BANKINFO_PDASZ_SHIFT 17 -+#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000 -+#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24 -+#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000 -+ -+/* extracoreinfo register */ -+#define SOCRAM_DEVRAMBANK_MASK 0xF000 -+#define SOCRAM_DEVRAMBANK_SHIFT 12 -+ -+/* bank info to calculate bank size */ -+#define SOCRAM_BANKINFO_SZBASE 8192 -+#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ -+ -+ -+#endif /* _SBSOCRAM_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/sgmiiplus2_serdes.h b/drivers/net/ethernet/broadcom/gmac/src/include/sgmiiplus2_serdes.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/sgmiiplus2_serdes.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/sgmiiplus2_serdes.h 2017-11-09 17:53:44.008297000 +0800 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * These routines provide access to the serdes -+ * -+ */ -+ -+#ifndef _SGMIIPLUS2_SERDES_H_ -+#define _SGMIIPLUS2_SERDES_H_ -+ -+#include -+ -+extern void sgmiiplus2_serdes_reset(uint eth_num, uint phyaddr); -+extern int sgmiiplus2_serdes_init(uint eth_num, uint phyaddr); -+ -+#endif /* _SGMIIPLUS2_SERDES_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/siutils.h b/drivers/net/ethernet/broadcom/gmac/src/include/siutils.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/siutils.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/siutils.h 2017-11-09 17:53:44.009295000 +0800 -@@ -0,0 +1,243 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc utility routines for accessing the SOC Interconnects -+ * of Broadcom HNBU chips. -+ * -+ * $Id: siutils.h 323456 2012-03-24 07:17:39Z $ -+ */ -+ -+#ifndef _siutils_h_ -+#define _siutils_h_ -+ -+#if defined(WLC_HIGH) && !defined(WLC_LOW) -+#include "bcm_rpc.h" -+#endif -+/* -+ * Data structure to export all chip specific common variables -+ * public (read-only) portion of siutils handle returned by si_attach() -+ */ -+struct si_pub { -+ uint socitype; /* SOCI_SB, SOCI_AI */ -+ -+ uint bustype; /* SI_BUS, PCI_BUS */ -+ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ -+ uint buscorerev; /* buscore rev */ -+ uint buscoreidx; /* buscore index */ -+ int ccrev; /* chip common core rev */ -+ uint32 cccaps; /* chip common capabilities */ -+ uint32 cccaps_ext; /* chip common capabilities extension */ -+ int pmurev; /* pmu core rev */ -+ uint32 pmucaps; /* pmu capabilities */ -+ uint boardtype; /* board type */ -+ uint boardrev; /* board rev */ -+ uint boardvendor; /* board vendor */ -+ uint boardflags; /* board flags */ -+ uint boardflags2; /* board flags2 */ -+ uint chip; /* chip number */ -+ uint chiprev; /* chip revision */ -+ uint chippkg; /* chip package option */ -+ uint32 chipst; /* chip status */ -+ bool issim; /* chip is in simulation or emulation */ -+ uint socirev; /* SOC interconnect rev */ -+ bool pci_pr32414; -+ spinlock_t sih_lock; -+ -+#if defined(WLC_HIGH) && !defined(WLC_LOW) -+ rpc_info_t *rpc; -+#endif -+}; -+ -+/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver -+ * for monolithic driver, it is readonly to prevent accident change -+ */ -+#if defined(WLC_HIGH) && !defined(WLC_LOW) -+typedef struct si_pub si_t; -+#else -+typedef const struct si_pub si_t; -+#endif -+ -+#ifdef ATE_BUILD -+typedef struct _ate_params { -+ void* wl; -+ uint8 gpio_input; -+ uint8 gpio_output; -+ bool cmd_proceed; -+ uint16 cmd_idx; -+ bool ate_cmd_done; -+} ate_params_t; -+#endif /* ATE_BUILD */ -+ -+/* -+ * Many of the routines below take an 'sih' handle as their first arg. -+ * Allocate this by calling si_attach(). Free it by calling si_detach(). -+ * At any one time, the sih is logically focused on one particular si core -+ * (the "current core"). -+ * Use si_setcore() or si_setcoreidx() to change the association to another core. -+ */ -+#define BADIDX (SI_MAXCORES + 1) -+ -+/* clkctl xtal what flags */ -+#define XTAL 0x1 /* primary crystal oscillator (2050) */ -+#define PLL 0x2 /* main chip pll */ -+ -+/* clkctl clk mode */ -+#define CLK_FAST 0 /* force fast (pll) clock */ -+#define CLK_DYNAMIC 2 /* enable dynamic clock control */ -+ -+/* GPIO usage priorities */ -+#define GPIO_DRV_PRIORITY 0 /* Driver */ -+#define GPIO_APP_PRIORITY 1 /* Application */ -+#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ -+ -+/* GPIO pull up/down */ -+#define GPIO_PULLUP 0 -+#define GPIO_PULLDN 1 -+ -+/* GPIO event regtype */ -+#define GPIO_REGEVT 0 /* GPIO register event */ -+#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ -+#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ -+ -+/* device path */ -+#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ -+ -+/* SI routine enumeration: to be used by update function with multiple hooks */ -+#define SI_DOATTACH 1 -+#define SI_PCIDOWN 2 -+#define SI_PCIUP 3 -+ -+#if defined(BCMQT) -+#define ISSIM_ENAB(sih) ((sih)->issim) -+#else -+#define ISSIM_ENAB(sih) 0 -+#endif -+ -+/* PMU clock/power control */ -+#if defined(BCMPMUCTL) -+#define PMUCTL_ENAB(sih) (BCMPMUCTL) -+#else -+#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) -+#endif -+ -+/* chipcommon clock/power control (exclusive with PMU's) */ -+#if defined(BCMPMUCTL) && BCMPMUCTL -+#define CCCTL_ENAB(sih) (0) -+#define CCPLL_ENAB(sih) (0) -+#else -+#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) -+#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) -+#endif -+ -+typedef void (*gpio_handler_t)(uint32 stat, void *arg); -+/* External BT Coex enable mask */ -+#define CC_BTCOEX_EN_MASK 0x01 -+/* External PA enable mask */ -+#define GPIO_CTRL_EPA_EN_MASK 0x40 -+/* WL/BT control enable mask */ -+#define GPIO_CTRL_5_6_EN_MASK 0x60 -+#define GPIO_CTRL_7_6_EN_MASK 0xC0 -+#define GPIO_OUT_7_EN_MASK 0x80 -+ -+ -+/* === exported functions === */ -+extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, -+ void *sdh, char **vars, uint *varsz); -+extern void si_detach(si_t *sih); -+ -+extern uint si_corelist(si_t *sih, uint coreid[]); -+extern uint si_coreid(si_t *sih); -+extern uint si_flag(si_t *sih); -+extern uint si_intflag(si_t *sih); -+extern uint si_coreidx(si_t *sih); -+extern uint si_coreunit(si_t *sih); -+extern uint si_corevendor(si_t *sih); -+extern uint si_corerev(si_t *sih); -+extern void *si_osh(si_t *sih); -+extern void si_setosh(si_t *sih, osl_t *osh); -+extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); -+extern void *si_coreregs(si_t *sih); -+extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); -+extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); -+extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); -+extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); -+#ifdef WLC_HIGH_ONLY -+extern bool wlc_bmac_iscoreup(si_t *sih); -+#define si_iscoreup(sih) wlc_bmac_iscoreup(sih) -+#else -+extern bool si_iscoreup(si_t *sih); -+#endif /* __CONFIG_USBAP__ */ -+extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); -+extern void *si_setcoreidx(si_t *sih, uint coreidx); -+extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); -+extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); -+extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); -+extern int si_numaddrspaces(si_t *sih); -+extern uint32 si_addrspace(si_t *sih, uint asidx); -+extern uint32 si_addrspacesize(si_t *sih, uint asidx); -+extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); -+extern int si_corebist(si_t *sih); -+extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -+extern void si_core_disable(si_t *sih, uint32 bits); -+extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); -+extern uint32 si_clock(si_t *sih); -+extern void si_setint(si_t *sih, int siflag); -+extern bool si_backplane64(si_t *sih); -+extern void si_clkctl_init(si_t *sih); -+extern bool si_clkctl_cc(si_t *sih, uint mode); -+extern int si_clkctl_xtal(si_t *sih, uint what, bool on); -+ -+extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); -+extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); -+ -+/* Wake-on-wireless-LAN (WOWL) */ -+extern bool si_pci_pmecap(si_t *sih); -+struct osl_info; -+extern bool si_pci_fastpmecap(struct osl_info *osh); -+ -+/* Fab-id information */ -+#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */ -+#define CSM_FAB7 0x1 /* CSM Fab7 chip */ -+#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */ -+#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */ -+ -+/* -+ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. -+ * The returned path is NULL terminated and has trailing '/'. -+ * Return 0 on success, nonzero otherwise. -+ */ -+extern int si_devpath(si_t *sih, char *path, int size); -+/* Read variable with prepending the devpath to the name */ -+extern int si_getdevpathintvar(si_t *sih, const char *name); -+extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); -+ -+ -+extern void si_war42780_clkreq(si_t *sih, bool clkreq); -+extern void si_pcie_extendL1timer(si_t *sih, bool extend); -+ -+/* === debug routines === */ -+ -+#ifdef BCMDBG -+extern void si_view(si_t *sih, bool verbose); -+extern void si_viewall(si_t *sih, bool verbose); -+#endif -+ -+#if defined(BCMDBG) -+struct bcmstrbuf; -+extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b); -+#endif -+ -+ -+#endif /* _siutils_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/trxhdr.h b/drivers/net/ethernet/broadcom/gmac/src/include/trxhdr.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/trxhdr.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/trxhdr.h 2017-11-09 17:53:44.010293000 +0800 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * TRX image file header format. -+ * -+ * $Id: trxhdr.h 314841 2012-02-14 18:28:33Z $ -+ */ -+ -+#ifndef _TRX_HDR_H -+#define _TRX_HDR_H -+ -+#include -+ -+#define TRX_MAGIC 0x30524448 /* "HDR0" */ -+#define TRX_MAX_LEN 0x3B0000 /* Max length */ -+#define TRX_NO_HEADER 1 /* Do not write TRX header */ -+#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -+#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ -+#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ -+#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ -+#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ -+ -+#define TRX_V1 1 -+#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ -+ -+#ifndef BCMTRXV2 -+#define TRX_VERSION TRX_V1 /* Version 1 */ -+#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS -+#endif -+ -+/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as -+ * Ver 2 of trx header. To make it generic, trx_header is structure is modified -+ * as below where size of "offsets" field will vary as per the TRX version. -+ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. -+ * To make sure, other applications like "dhdl" which are yet to be enhanced to support -+ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 -+ * is defined. -+ */ -+struct trx_header { -+ uint32 magic; /* "HDR0" */ -+ uint32 len; /* Length of file including header */ -+ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ -+ uint32 flag_version; /* 0:15 flags, 16:31 version */ -+#ifndef BCMTRXV2 -+ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -+#else -+ uint32 offsets[1]; /* Offsets of partitions from start of header */ -+#endif -+}; -+ -+#ifdef BCMTRXV2 -+#define TRX_VERSION TRX_V2 /* Version 2 */ -+#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS -+ -+#define TRX_V2 2 -+/* V2: Max number of individual files -+ * To support SDR signature + Config data region -+ */ -+#define TRX_V2_MAX_OFFSETS 5 -+#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) -+#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) -+#define TRX_VER(trx) (trx->flag_version>>16) -+#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) -+#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) -+/* For V2, return size of V2 size: others, return V1 size */ -+#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) -+#else -+#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) -+#endif /* BCMTRXV2 */ -+ -+/* Compatibility */ -+typedef struct trx_header TRXHDR, *PTRXHDR; -+ -+#endif /* _TRX_HDR_H */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/typedefs.h b/drivers/net/ethernet/broadcom/gmac/src/include/typedefs.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/typedefs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/typedefs.h 2017-11-09 17:53:44.011290000 +0800 -@@ -0,0 +1,447 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ -+ */ -+ -+#ifndef _TYPEDEFS_H_ -+#define _TYPEDEFS_H_ -+ -+#ifdef SITE_TYPEDEFS -+ -+/* -+ * Define SITE_TYPEDEFS in the compile to include a site-specific -+ * typedef file "site_typedefs.h". -+ * -+ * If SITE_TYPEDEFS is not defined, then the code section below makes -+ * inferences about the compile environment based on defined symbols and -+ * possibly compiler pragmas. -+ * -+ * Following these two sections is the Default Typedefs section. -+ * This section is only processed if USE_TYPEDEF_DEFAULTS is -+ * defined. This section has a default set of typedefs and a few -+ * preprocessor symbols (TRUE, FALSE, NULL, ...). -+ */ -+ -+#include "site_typedefs.h" -+ -+#else -+ -+/* -+ * Infer the compile environment based on preprocessor symbols and pragmas. -+ * Override type definitions as needed, and include configuration-dependent -+ * header files to define types. -+ */ -+ -+#ifdef __cplusplus -+ -+#define TYPEDEF_BOOL -+#ifndef FALSE -+#define FALSE false -+#endif -+#ifndef TRUE -+#define TRUE true -+#endif -+ -+#else /* ! __cplusplus */ -+ -+#if defined(_WIN32) -+ -+#define TYPEDEF_BOOL -+typedef unsigned char bool; /* consistent w/BOOL */ -+ -+#endif /* _WIN32 */ -+ -+#endif /* ! __cplusplus */ -+ -+#if defined(_WIN64) && !defined(EFI) -+/* use the Windows ULONG_PTR type when compiling for 64 bit */ -+#include -+#define TYPEDEF_UINTPTR -+typedef ULONG_PTR uintptr; -+#elif defined(__x86_64__) -+#define TYPEDEF_UINTPTR -+typedef unsigned long long int uintptr; -+#endif -+ -+ -+#if defined(_MINOSL_) -+#define _NEED_SIZE_T_ -+#endif -+ -+#if defined(EFI) && !defined(_WIN64) -+#define _NEED_SIZE_T_ -+#endif -+ -+#if defined(TARGETOS_nucleus) -+/* for 'size_t' type */ -+#include -+ -+/* float_t types conflict with the same typedefs from the standard ANSI-C -+** math.h header file. Don't re-typedef them here. -+*/ -+#define TYPEDEF_FLOAT_T -+#endif /* TARGETOS_nucleus */ -+ -+#if defined(_NEED_SIZE_T_) -+typedef long unsigned int size_t; -+#endif -+ -+#ifdef _MSC_VER /* Microsoft C */ -+#define TYPEDEF_INT64 -+#define TYPEDEF_UINT64 -+typedef signed __int64 int64; -+typedef unsigned __int64 uint64; -+#endif -+ -+#if defined(MACOSX) -+#define TYPEDEF_BOOL -+#endif -+ -+#if defined(__NetBSD__) -+#define TYPEDEF_BOOL -+#ifndef _KERNEL -+#include -+#endif -+#define TYPEDEF_UINT -+#define TYPEDEF_USHORT -+#define TYPEDEF_ULONG -+#endif /* defined(__NetBSD__) */ -+ -+#if defined(__sparc__) -+#define TYPEDEF_ULONG -+#endif -+ -+ -+#ifdef linux -+/* -+ * If this is either a Linux hybrid build or the per-port code of a hybrid build -+ * then use the Linux header files to get some of the typedefs. Otherwise, define -+ * them entirely in this file. We can't always define the types because we get -+ * a duplicate typedef error; there is no way to "undefine" a typedef. -+ * We know when it's per-port code because each file defines LINUX_PORT at the top. -+ */ -+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) -+#define TYPEDEF_UINT -+#ifndef TARGETENV_android -+#define TYPEDEF_USHORT -+#define TYPEDEF_ULONG -+#endif /* TARGETENV_android */ -+#ifdef __KERNEL__ -+#include -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) -+#define TYPEDEF_BOOL -+#endif /* >= 2.6.19 */ -+/* special detection for 2.6.18-128.7.1.0.1.el5 */ -+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) -+#include -+#ifdef noinline_for_stack -+#define TYPEDEF_BOOL -+#endif -+#endif /* == 2.6.18 */ -+#endif /* __KERNEL__ */ -+#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ -+#endif /* linux */ -+ -+#if defined(__ECOS) -+#define TYPEDEF_UCHAR -+#define TYPEDEF_UINT -+#define TYPEDEF_USHORT -+#define TYPEDEF_ULONG -+#define TYPEDEF_BOOL -+#endif -+ -+#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ -+ !defined(__DJGPP__) && !defined(__ECOS) && !defined(__BOB__) && \ -+ !defined(TARGETOS_nucleus) && !defined(EFI) && !defined(__FreeBSD__) -+#define TYPEDEF_UINT -+#define TYPEDEF_USHORT -+#endif -+ -+ -+/* Do not support the (u)int64 types with strict ansi for GNU C */ -+#if defined(__GNUC__) && defined(__STRICT_ANSI__) -+#define TYPEDEF_INT64 -+#define TYPEDEF_UINT64 -+#endif -+ -+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode -+ * for signed or unsigned -+ */ -+#if defined(__ICL) -+ -+#define TYPEDEF_INT64 -+ -+#if defined(__STDC__) -+#define TYPEDEF_UINT64 -+#endif -+ -+#endif /* __ICL */ -+ -+#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && !defined(__DJGPP__) && \ -+ !defined(__BOB__) && !defined(TARGETOS_nucleus) && !defined(EFI) -+ -+/* pick up ushort & uint from standard types.h */ -+#if defined(linux) && defined(__KERNEL__) -+ -+/* See note above */ -+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) -+#ifdef USER_MODE -+#include -+#else -+#include /* sys/types.h and linux/types.h are oil and water */ -+#endif /* USER_MODE */ -+#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ -+ -+#else -+ -+#if defined(__ECOS) -+#include -+#include -+#include -+#endif -+ -+#include -+ -+#endif /* linux && __KERNEL__ */ -+ -+#endif -+ -+#ifdef CONFIG_CPU_BIG_ENDIAN -+#define IL_BIGENDIAN -+#else -+#ifdef IL_BIGENDIAN -+#error "IL_BIGENDIAN was defined for a little-endian compile" -+#endif -+#endif /* CONFIG_CPU_BIG_ENDIAN */ -+ -+#if defined(MACOSX) -+ -+#ifdef __BIG_ENDIAN__ -+#define IL_BIGENDIAN -+#else -+#ifdef IL_BIGENDIAN -+#error "IL_BIGENDIAN was defined for a little-endian compile" -+#endif -+#endif /* __BIG_ENDIAN__ */ -+ -+#if !defined(__cplusplus) -+ -+#if defined(__i386__) -+typedef unsigned char bool; -+#else -+typedef unsigned int bool; -+#endif -+#define TYPE_BOOL 1 -+enum { -+ false = 0, -+ true = 1 -+}; -+ -+#if defined(KERNEL) -+#include -+#endif /* KERNEL */ -+ -+#endif /* __cplusplus */ -+ -+#endif /* MACOSX */ -+ -+ -+/* use the default typedefs in the next section of this file */ -+#define USE_TYPEDEF_DEFAULTS -+ -+#endif /* SITE_TYPEDEFS */ -+ -+ -+/* -+ * Default Typedefs -+ */ -+ -+#ifdef USE_TYPEDEF_DEFAULTS -+#undef USE_TYPEDEF_DEFAULTS -+ -+#ifndef TYPEDEF_BOOL -+typedef /* @abstract@ */ unsigned char bool; -+#endif -+ -+/* define uchar, ushort, uint, ulong */ -+ -+#ifndef TYPEDEF_UCHAR -+typedef unsigned char uchar; -+#endif -+ -+#ifndef TYPEDEF_USHORT -+typedef unsigned short ushort; -+#endif -+ -+#ifndef TYPEDEF_UINT -+typedef unsigned int uint; -+#endif -+ -+#ifndef TYPEDEF_ULONG -+typedef unsigned long ulong; -+#endif -+ -+/* define [u]int8/16/32/64, uintptr */ -+ -+#ifndef TYPEDEF_UINT8 -+typedef unsigned char uint8; -+#endif -+ -+#ifndef TYPEDEF_UINT16 -+typedef unsigned short uint16; -+#endif -+ -+#ifndef TYPEDEF_UINT32 -+typedef unsigned int uint32; -+#endif -+ -+#ifndef TYPEDEF_UINT64 -+typedef unsigned long long uint64; -+#endif -+ -+#ifndef TYPEDEF_UINTPTR -+typedef unsigned int uintptr; -+#endif -+ -+#ifndef TYPEDEF_INT8 -+typedef signed char int8; -+#endif -+ -+#ifndef TYPEDEF_INT16 -+typedef signed short int16; -+#endif -+ -+#ifndef TYPEDEF_INT32 -+typedef signed int int32; -+#endif -+ -+#ifndef TYPEDEF_INT64 -+typedef signed long long int64; -+#endif -+ -+/* define float32/64, float_t */ -+ -+#ifndef TYPEDEF_FLOAT32 -+typedef float float32; -+#endif -+ -+#ifndef TYPEDEF_FLOAT64 -+typedef double float64; -+#endif -+ -+/* -+ * abstracted floating point type allows for compile time selection of -+ * single or double precision arithmetic. Compiling with -DFLOAT32 -+ * selects single precision; the default is double precision. -+ */ -+ -+#ifndef TYPEDEF_FLOAT_T -+ -+#if defined(FLOAT32) -+typedef float32 float_t; -+#else /* default to double precision floating point */ -+typedef float64 float_t; -+#endif -+ -+#endif /* TYPEDEF_FLOAT_T */ -+ -+/* define macro values */ -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+ -+#ifndef TRUE -+#define TRUE 1 /* TRUE */ -+#endif -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#ifndef OFF -+#define OFF 0 -+#endif -+ -+#ifndef ON -+#define ON 1 /* ON = 1 */ -+#endif -+ -+#define AUTO (-1) /* Auto = -1 */ -+ -+/* define PTRSZ, INLINE */ -+ -+#ifndef PTRSZ -+#define PTRSZ sizeof(char*) -+#endif -+ -+ -+/* Detect compiler type. */ -+#ifdef _MSC_VER -+ #define BWL_COMPILER_MICROSOFT -+#elif defined(__GNUC__) || defined(__lint) -+ #define BWL_COMPILER_GNU -+#elif defined(__CC_ARM) && __CC_ARM -+ #define BWL_COMPILER_ARMCC -+#else -+ #error "Unknown compiler!" -+#endif /* _MSC_VER */ -+ -+ -+#ifndef INLINE -+ #if defined(BWL_COMPILER_MICROSOFT) -+ #define INLINE __inline -+ #elif defined(BWL_COMPILER_GNU) -+ #define INLINE __inline__ -+ #elif defined(BWL_COMPILER_ARMCC) -+ #define INLINE __inline -+ #else -+ #define INLINE -+ #endif /* _MSC_VER */ -+#endif /* INLINE */ -+ -+#undef TYPEDEF_BOOL -+#undef TYPEDEF_UCHAR -+#undef TYPEDEF_USHORT -+#undef TYPEDEF_UINT -+#undef TYPEDEF_ULONG -+#undef TYPEDEF_UINT8 -+#undef TYPEDEF_UINT16 -+#undef TYPEDEF_UINT32 -+#undef TYPEDEF_UINT64 -+#undef TYPEDEF_UINTPTR -+#undef TYPEDEF_INT8 -+#undef TYPEDEF_INT16 -+#undef TYPEDEF_INT32 -+#undef TYPEDEF_INT64 -+#undef TYPEDEF_FLOAT32 -+#undef TYPEDEF_FLOAT64 -+#undef TYPEDEF_FLOAT_T -+ -+#endif /* USE_TYPEDEF_DEFAULTS */ -+ -+/* Suppress unused parameter warning */ -+#define UNUSED_PARAMETER(x) (void)(x) -+ -+/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ -+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) -+ -+/* -+ * Including the bcmdefs.h here, to make sure everyone including typedefs.h -+ * gets this automatically -+*/ -+#include -+#endif /* _TYPEDEFS_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/include/wlioctl.h b/drivers/net/ethernet/broadcom/gmac/src/include/wlioctl.h ---- a/drivers/net/ethernet/broadcom/gmac/src/include/wlioctl.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/include/wlioctl.h 2017-11-09 17:53:44.016288000 +0800 -@@ -0,0 +1,4877 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Custom OID/ioctl definitions for -+ * Broadcom 802.11abg Networking Device Driver -+ * -+ * Definitions subject to change without notice. -+ * -+ * $Id: wlioctl.h 324203 2012-03-28 09:55:17Z $ -+ */ -+ -+#ifndef _wlioctl_h_ -+#define _wlioctl_h_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#ifdef __NetBSD__ -+/* NetBSD 2.0 does not have SIOCDEVPRIVATE. */ -+#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq) -+#endif -+ -+#ifndef INTF_NAME_SIZ -+#define INTF_NAME_SIZ 16 -+#endif -+ -+/* Used to send ioctls over the transport pipe */ -+typedef struct remote_ioctl { -+ cdc_ioctl_t msg; -+ uint data_len; -+#ifndef OLYMPIC_RWL -+ char intf_name[INTF_NAME_SIZ]; -+#endif -+} rem_ioctl_t; -+#define REMOTE_SIZE sizeof(rem_ioctl_t) -+#ifdef EFI -+#define BCMWL_IOCTL_GUID \ -+ {0xB4910A35, 0x88C5, 0x4328, { 0x90, 0x08, 0x9F, 0xB2, 0x00, 0x00, 0x0, 0x0 } } -+#endif /* EFI */ -+ -+#define ACTION_FRAME_SIZE 1800 -+ -+typedef struct wl_action_frame { -+ struct ether_addr da; -+ uint16 len; -+ uint32 packetId; -+ uint8 data[ACTION_FRAME_SIZE]; -+} wl_action_frame_t; -+ -+#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) -+ -+typedef struct ssid_info -+{ -+ uint8 ssid_len; /* the length of SSID */ -+ uint8 ssid[32]; /* SSID string */ -+} ssid_info_t; -+ -+typedef struct wl_af_params { -+ uint32 channel; -+ int32 dwell_time; -+ struct ether_addr BSSID; -+ wl_action_frame_t action_frame; -+} wl_af_params_t; -+ -+#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) -+ -+#define MFP_TEST_FLAG_NORMAL 0 -+#define MFP_TEST_FLAG_ANY_KEY 1 -+typedef struct wl_sa_query { -+ uint32 flag; -+ uint8 action; -+ uint16 id; -+ struct ether_addr da; -+} wl_sa_query_t; -+ -+ -+/* require default structure packing */ -+#define BWL_DEFAULT_PACKING -+#include -+ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* Legacy structure to help keep backward compatible wl tool and tray app */ -+ -+#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ -+ -+typedef struct wl_bss_info_107 { -+ uint32 version; /* version field */ -+ uint32 length; /* byte length of data in this record, -+ * starting at version and including IEs -+ */ -+ struct ether_addr BSSID; -+ uint16 beacon_period; /* units are Kusec */ -+ uint16 capability; /* Capability information */ -+ uint8 SSID_len; -+ uint8 SSID[32]; -+ struct { -+ uint count; /* # rates in this set */ -+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ -+ } rateset; /* supported rates */ -+ uint8 channel; /* Channel no. */ -+ uint16 atim_window; /* units are Kusec */ -+ uint8 dtim_period; /* DTIM period */ -+ int16 RSSI; /* receive signal strength (in dBm) */ -+ int8 phy_noise; /* noise (in dBm) */ -+ uint32 ie_length; /* byte length of Information Elements */ -+ /* variable length Information Elements */ -+} wl_bss_info_107_t; -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+/* -+ * Per-BSS information structure. -+ */ -+ -+#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ -+ -+/* BSS info structure -+ * Applications MUST CHECK ie_offset field and length field to access IEs and -+ * next bss_info structure in a vector (in wl_scan_results_t) -+ */ -+typedef struct wl_bss_info_108 { -+ uint32 version; /* version field */ -+ uint32 length; /* byte length of data in this record, -+ * starting at version and including IEs -+ */ -+ struct ether_addr BSSID; -+ uint16 beacon_period; /* units are Kusec */ -+ uint16 capability; /* Capability information */ -+ uint8 SSID_len; -+ uint8 SSID[32]; -+ struct { -+ uint count; /* # rates in this set */ -+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ -+ } rateset; /* supported rates */ -+ chanspec_t chanspec; /* chanspec for bss */ -+ uint16 atim_window; /* units are Kusec */ -+ uint8 dtim_period; /* DTIM period */ -+ int16 RSSI; /* receive signal strength (in dBm) */ -+ int8 phy_noise; /* noise (in dBm) */ -+ -+ uint8 n_cap; /* BSS is 802.11N Capable */ -+ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ -+ uint8 ctl_ch; /* 802.11N BSS control channel number */ -+ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */ -+ uint8 flags; /* flags */ -+ uint8 reserved[3]; /* Reserved for expansion of BSS properties */ -+ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ -+ -+ uint16 ie_offset; /* offset at which IEs start, from beginning */ -+ uint32 ie_length; /* byte length of Information Elements */ -+ /* Add new fields here */ -+ /* variable length Information Elements */ -+} wl_bss_info_108_t; -+ -+#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */ -+ -+/* BSS info structure -+ * Applications MUST CHECK ie_offset field and length field to access IEs and -+ * next bss_info structure in a vector (in wl_scan_results_t) -+ */ -+typedef struct wl_bss_info { -+ uint32 version; /* version field */ -+ uint32 length; /* byte length of data in this record, -+ * starting at version and including IEs -+ */ -+ struct ether_addr BSSID; -+ uint16 beacon_period; /* units are Kusec */ -+ uint16 capability; /* Capability information */ -+ uint8 SSID_len; -+ uint8 SSID[32]; -+ struct { -+ uint count; /* # rates in this set */ -+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ -+ } rateset; /* supported rates */ -+ chanspec_t chanspec; /* chanspec for bss */ -+ uint16 atim_window; /* units are Kusec */ -+ uint8 dtim_period; /* DTIM period */ -+ int16 RSSI; /* receive signal strength (in dBm) */ -+ int8 phy_noise; /* noise (in dBm) */ -+ -+ uint8 n_cap; /* BSS is 802.11N Capable */ -+ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ -+ uint8 ctl_ch; /* 802.11N BSS control channel number */ -+ uint16 vht_rxmcsmap; /* VHT rx mcs map */ -+ uint16 vht_txmcsmap; /* VHT tx mcs map */ -+ uint8 flags; /* flags */ -+ uint8 vht_cap; /* BSS is vht capable */ -+ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ -+ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ -+ -+ uint16 ie_offset; /* offset at which IEs start, from beginning */ -+ uint32 ie_length; /* byte length of Information Elements */ -+ int16 SNR; /* average SNR of during frame reception */ -+ /* Add new fields here */ -+ /* variable length Information Elements */ -+} wl_bss_info_t; -+ -+typedef struct wl_bsscfg { -+ uint32 wsec; -+ uint32 WPA_auth; -+ uint32 wsec_index; -+ uint32 associated; -+ uint32 BSS; -+ uint32 phytest_on; -+ struct ether_addr prev_BSSID; -+ struct ether_addr BSSID; -+} wl_bsscfg_t; -+ -+typedef struct wl_bss_config { -+ uint32 atim_window; -+ uint32 beacon_period; -+ uint32 chanspec; -+} wl_bss_config_t; -+ -+#define DLOAD_HANDLER_VER 1 /* Downloader version */ -+#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ -+#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ -+ -+#define DL_CRC_NOT_INUSE 0x0001 -+ -+/* generic download types & flags */ -+enum { -+ DL_TYPE_UCODE = 1, -+ DL_TYPE_CLM = 2 -+}; -+ -+/* ucode type values */ -+enum { -+ UCODE_FW, -+ INIT_VALS, -+ BS_INIT_VALS -+}; -+ -+struct wl_dload_data { -+ uint16 flag; -+ uint16 dload_type; -+ uint32 len; -+ uint32 crc; -+ uint8 data[1]; -+}; -+typedef struct wl_dload_data wl_dload_data_t; -+ -+struct wl_ucode_info { -+ uint32 ucode_type; -+ uint32 num_chunks; -+ uint32 chunk_len; -+ uint32 chunk_num; -+ uint8 data_chunk[1]; -+}; -+typedef struct wl_ucode_info wl_ucode_info_t; -+ -+struct wl_clm_dload_info { -+ uint32 ds_id; -+ uint32 clm_total_len; -+ uint32 num_chunks; -+ uint32 chunk_len; -+ uint32 chunk_offset; -+ uint8 data_chunk[1]; -+}; -+typedef struct wl_clm_dload_info wl_clm_dload_info_t; -+ -+typedef struct wlc_ssid { -+ uint32 SSID_len; -+ uchar SSID[32]; -+} wlc_ssid_t; -+ -+#define MAX_PREFERRED_AP_NUM 5 -+typedef struct wlc_fastssidinfo { -+ uint32 SSID_channel[MAX_PREFERRED_AP_NUM]; -+ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM]; -+} wlc_fastssidinfo_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct wnm_url { -+ uint8 len; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT wnm_url_t; -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+typedef struct chan_scandata { -+ uint8 txpower; -+ uint8 pad; -+ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */ -+ uint32 channel_mintime; -+ uint32 channel_maxtime; -+} chan_scandata_t; -+ -+typedef enum wl_scan_type { -+ EXTDSCAN_FOREGROUND_SCAN, -+ EXTDSCAN_BACKGROUND_SCAN, -+ EXTDSCAN_FORCEDBACKGROUND_SCAN -+} wl_scan_type_t; -+ -+#define WLC_EXTDSCAN_MAX_SSID 5 -+ -+#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ -+#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ -+#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info was received on channel (vs offchannel) */ -+ -+typedef struct wl_extdscan_params { -+ int8 nprobes; /* 0, passive, otherwise active */ -+ int8 split_scan; /* split scan */ -+ int8 band; /* band */ -+ int8 pad; -+ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */ -+ uint32 tx_rate; /* in 500ksec units */ -+ wl_scan_type_t scan_type; /* enum */ -+ int32 channel_num; -+ chan_scandata_t channel_list[1]; /* list of chandata structs */ -+} wl_extdscan_params_t; -+ -+#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t)) -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+#define WL_BSSTYPE_INFRA 1 -+#define WL_BSSTYPE_INDEP 0 -+#define WL_BSSTYPE_ANY 2 -+ -+/* Bitmask for scan_type */ -+#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ -+#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ -+#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ -+ -+#define WL_SCAN_PARAMS_SSID_MAX 10 -+ -+typedef struct wl_scan_params { -+ wlc_ssid_t ssid; /* default: {0, ""} */ -+ struct ether_addr bssid; /* default: bcast */ -+ int8 bss_type; /* default: any, -+ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT -+ */ -+ uint8 scan_type; /* flags, 0 use default */ -+ int32 nprobes; /* -1 use default, number of probes per channel */ -+ int32 active_time; /* -1 use default, dwell time per channel for -+ * active scanning -+ */ -+ int32 passive_time; /* -1 use default, dwell time per channel -+ * for passive scanning -+ */ -+ int32 home_time; /* -1 use default, dwell time for the home channel -+ * between channel scans -+ */ -+ int32 channel_num; /* count of channels and ssids that follow -+ * -+ * low half is count of channels in channel_list, 0 -+ * means default (use all available channels) -+ * -+ * high half is entries in wlc_ssid_t array that -+ * follows channel_list, aligned for int32 (4 bytes) -+ * meaning an odd channel count implies a 2-byte pad -+ * between end of channel_list and first ssid -+ * -+ * if ssid count is zero, single ssid in the fixed -+ * parameter portion is assumed, otherwise ssid in -+ * the fixed portion is ignored -+ */ -+ uint16 channel_list[1]; /* list of chanspecs */ -+} wl_scan_params_t; -+ -+/* size of wl_scan_params not including variable length array */ -+#define WL_SCAN_PARAMS_FIXED_SIZE 64 -+ -+/* masks for channel and ssid count */ -+#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff -+#define WL_SCAN_PARAMS_NSSID_SHIFT 16 -+ -+#define WL_SCAN_ACTION_START 1 -+#define WL_SCAN_ACTION_CONTINUE 2 -+#define WL_SCAN_ACTION_ABORT 3 -+ -+#define ISCAN_REQ_VERSION 1 -+ -+/* incremental scan struct */ -+typedef struct wl_iscan_params { -+ uint32 version; -+ uint16 action; -+ uint16 scan_duration; -+ wl_scan_params_t params; -+} wl_iscan_params_t; -+ -+/* 3 fields + size of wl_scan_params, not including variable length array */ -+#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) -+ -+typedef struct wl_scan_results { -+ uint32 buflen; -+ uint32 version; -+ uint32 count; -+ wl_bss_info_t bss_info[1]; -+} wl_scan_results_t; -+ -+/* size of wl_scan_results not including variable length array */ -+#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t)) -+ -+/* wl_iscan_results status values */ -+#define WL_SCAN_RESULTS_SUCCESS 0 -+#define WL_SCAN_RESULTS_PARTIAL 1 -+#define WL_SCAN_RESULTS_PENDING 2 -+#define WL_SCAN_RESULTS_ABORTED 3 -+#define WL_SCAN_RESULTS_NO_MEM 4 -+ -+/* Used in EXT_STA */ -+#define DNGL_RXCTXT_SIZE 45 -+ -+#if defined(SIMPLE_ISCAN) -+#define ISCAN_RETRY_CNT 5 -+#define ISCAN_STATE_IDLE 0 -+#define ISCAN_STATE_SCANING 1 -+#define ISCAN_STATE_PENDING 2 -+ -+/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ -+#define WLC_IW_ISCAN_MAXLEN 2048 -+typedef struct iscan_buf { -+ struct iscan_buf * next; -+ char iscan_buf[WLC_IW_ISCAN_MAXLEN]; -+} iscan_buf_t; -+#endif /* SIMPLE_ISCAN */ -+ -+#define ESCAN_REQ_VERSION 1 -+ -+typedef struct wl_escan_params { -+ uint32 version; -+ uint16 action; -+ uint16 sync_id; -+ wl_scan_params_t params; -+} wl_escan_params_t; -+ -+#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) -+ -+typedef struct wl_escan_result { -+ uint32 buflen; -+ uint32 version; -+ uint16 sync_id; -+ uint16 bss_count; -+ wl_bss_info_t bss_info[1]; -+} wl_escan_result_t; -+ -+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) -+ -+/* incremental scan results struct */ -+typedef struct wl_iscan_results { -+ uint32 status; -+ wl_scan_results_t results; -+} wl_iscan_results_t; -+ -+/* size of wl_iscan_results not including variable length array */ -+#define WL_ISCAN_RESULTS_FIXED_SIZE \ -+ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) -+ -+typedef struct wl_probe_params { -+ wlc_ssid_t ssid; -+ struct ether_addr bssid; -+ struct ether_addr mac; -+} wl_probe_params_t; -+ -+#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ -+typedef struct wl_rateset { -+ uint32 count; /* # rates in this set */ -+ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ -+} wl_rateset_t; -+ -+typedef struct wl_rateset_args { -+ uint32 count; /* # rates in this set */ -+ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ -+ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ -+} wl_rateset_args_t; -+ -+/* uint32 list */ -+typedef struct wl_uint32_list { -+ /* in - # of elements, out - # of entries */ -+ uint32 count; -+ /* variable length uint32 list */ -+ uint32 element[1]; -+} wl_uint32_list_t; -+ -+/* used for association with a specific BSSID and chanspec list */ -+typedef struct wl_assoc_params { -+ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ -+ int32 chanspec_num; /* 0: all available channels, -+ * otherwise count of chanspecs in chanspec_list -+ */ -+ chanspec_t chanspec_list[1]; /* list of chanspecs */ -+} wl_assoc_params_t; -+#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list) -+ -+/* used for reassociation/roam to a specific BSSID and channel */ -+typedef wl_assoc_params_t wl_reassoc_params_t; -+#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE -+ -+/* used for association to a specific BSSID and channel */ -+typedef wl_assoc_params_t wl_join_assoc_params_t; -+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE -+ -+/* used for join with or without a specific bssid and channel list */ -+typedef struct wl_join_params { -+ wlc_ssid_t ssid; -+ wl_assoc_params_t params; /* optional field, but it must include the fixed portion -+ * of the wl_assoc_params_t struct when it does present. -+ */ -+} wl_join_params_t; -+#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \ -+ WL_ASSOC_PARAMS_FIXED_SIZE) -+/* scan params for extended join */ -+typedef struct wl_join_scan_params { -+ uint8 scan_type; /* 0 use default, active or passive scan */ -+ int32 nprobes; /* -1 use default, number of probes per channel */ -+ int32 active_time; /* -1 use default, dwell time per channel for -+ * active scanning -+ */ -+ int32 passive_time; /* -1 use default, dwell time per channel -+ * for passive scanning -+ */ -+ int32 home_time; /* -1 use default, dwell time for the home channel -+ * between channel scans -+ */ -+} wl_join_scan_params_t; -+ -+/* extended join params */ -+typedef struct wl_extjoin_params { -+ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ -+ wl_join_scan_params_t scan; -+ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion -+ * of the wl_join_assoc_params_t struct when it does -+ * present. -+ */ -+} wl_extjoin_params_t; -+#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \ -+ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE) -+ -+/* All builds use the new 11ac ratespec/chanspec */ -+#undef D11AC_IOTYPES -+#define D11AC_IOTYPES -+ -+#ifndef D11AC_IOTYPES -+ -+/* defines used by the nrate iovar */ -+#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ -+#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ -+#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ -+#define NRATE_STF_SHIFT 8 /* stf mode shift */ -+#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ -+#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ -+#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ -+#define NRATE_SGI_SHIFT 23 /* sgi mode */ -+#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ -+#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ -+ -+#define NRATE_STF_SISO 0 /* stf mode SISO */ -+#define NRATE_STF_CDD 1 /* stf mode CDD */ -+#define NRATE_STF_STBC 2 /* stf mode STBC */ -+#define NRATE_STF_SDM 3 /* stf mode SDM */ -+ -+#else /* D11AC_IOTYPES */ -+ -+/* WL_RSPEC defines for rate information */ -+#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ -+#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ -+#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ -+#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ -+#define WL_RSPEC_TXEXP_MASK 0x00000300 -+#define WL_RSPEC_TXEXP_SHIFT 8 -+#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ -+#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ -+#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ -+#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ -+#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ -+#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ -+#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ -+#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ -+ -+/* WL_RSPEC_ENCODING field defs */ -+#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ -+#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ -+#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ -+ -+/* WL_RSPEC_BW field defs */ -+#define WL_RSPEC_BW_UNSPECIFIED 0 -+#define WL_RSPEC_BW_20MHZ 0x00010000 -+#define WL_RSPEC_BW_40MHZ 0x00020000 -+#define WL_RSPEC_BW_80MHZ 0x00030000 -+#define WL_RSPEC_BW_160MHZ 0x00040000 -+ -+/* Legacy defines for the nrate iovar */ -+#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ -+#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ -+#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ -+#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */ -+#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ -+#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ -+#define OLD_NRATE_SGI 0x00800000 /* sgi mode */ -+#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ -+ -+#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */ -+#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */ -+#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */ -+#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */ -+ -+#endif /* D11AC_IOTYPES */ -+ -+#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ -+#define ANTENNA_NUM_2 2 -+#define ANTENNA_NUM_3 3 -+#define ANTENNA_NUM_4 4 -+ -+#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ -+#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ -+#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ -+#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ -+#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ -+#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ -+#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ -+ -+#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ -+ -+typedef struct { -+ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ -+ uint8 num_antcfg; /* number of available antenna configurations */ -+} wlc_antselcfg_t; -+ -+#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ -+ -+#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ -+#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ -+ -+#define IBSS_MED 15 /* Mediom in-bss congestion percentage */ -+#define IBSS_HI 25 /* Hi in-bss congestion percentage */ -+#define OBSS_MED 12 -+#define OBSS_HI 25 -+#define INTERFER_MED 5 -+#define INTERFER_HI 10 -+ -+#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */ -+#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */ -+#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */ -+#define CCA_FLAGS_PREFER_1_6_11 0x10 -+#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */ -+ -+#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */ -+#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */ -+#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */ -+#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */ -+#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */ -+ -+typedef struct { -+ uint32 duration; /* millisecs spent sampling this channel */ -+ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */ -+ /* move if cur bss moves channels) */ -+ uint32 congest_obss; /* traffic not in our bss */ -+ uint32 interference; /* millisecs detecting a non 802.11 interferer. */ -+ uint32 timestamp; /* second timestamp */ -+} cca_congest_t; -+ -+typedef struct { -+ chanspec_t chanspec; /* Which channel? */ -+ uint8 num_secs; /* How many secs worth of data */ -+ cca_congest_t secs[1]; /* Data */ -+} cca_congest_channel_req_t; -+ -+/* interference source detection and identification mode */ -+#define ITFR_MODE_DISABLE 0 /* disable feature */ -+#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */ -+#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */ -+ -+/* interference sources */ -+enum interference_source { -+ ITFR_NONE = 0, /* interference */ -+ ITFR_PHONE, /* wireless phone */ -+ ITFR_VIDEO_CAMERA, /* wireless video camera */ -+ ITFR_MICROWAVE_OVEN, /* microwave oven */ -+ ITFR_BABY_MONITOR, /* wireless baby monitor */ -+ ITFR_BLUETOOTH, /* bluetooth */ -+ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */ -+ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */ -+ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */ -+ ITFR_UNIDENTIFIED /* interference from unidentified source */ -+}; -+ -+/* structure for interference source report */ -+typedef struct { -+ uint32 flags; /* flags. bit definitions below */ -+ uint32 source; /* last detected interference source */ -+ uint32 timestamp; /* second timestamp on interferenced flag change */ -+} interference_source_rep_t; -+ -+/* bit definitions for flags in interference source report */ -+#define ITFR_INTERFERENCED 1 /* interference detected */ -+#define ITFR_HOME_CHANNEL 2 /* home channel has interference */ -+#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */ -+ -+#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ -+ -+typedef struct wl_country { -+ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in -+ * the Country IE -+ */ -+ int32 rev; /* revision specifier for ccode -+ * on set, -1 indicates unspecified. -+ * on get, rev >= 0 -+ */ -+ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code. -+ * variable length, but fixed size in -+ * struct allows simple allocation for -+ * expected country strings <= 3 chars. -+ */ -+} wl_country_t; -+ -+typedef struct wl_channels_in_country { -+ uint32 buflen; -+ uint32 band; -+ char country_abbrev[WLC_CNTRY_BUF_SZ]; -+ uint32 count; -+ uint32 channel[1]; -+} wl_channels_in_country_t; -+ -+typedef struct wl_country_list { -+ uint32 buflen; -+ uint32 band_set; -+ uint32 band; -+ uint32 count; -+ char country_abbrev[1]; -+} wl_country_list_t; -+ -+#define WL_NUM_RPI_BINS 8 -+#define WL_RM_TYPE_BASIC 1 -+#define WL_RM_TYPE_CCA 2 -+#define WL_RM_TYPE_RPI 3 -+ -+#define WL_RM_FLAG_PARALLEL (1<<0) -+ -+#define WL_RM_FLAG_LATE (1<<1) -+#define WL_RM_FLAG_INCAPABLE (1<<2) -+#define WL_RM_FLAG_REFUSED (1<<3) -+ -+typedef struct wl_rm_req_elt { -+ int8 type; -+ int8 flags; -+ chanspec_t chanspec; -+ uint32 token; /* token for this measurement */ -+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ -+ uint32 tsf_l; /* TSF low 32-bits */ -+ uint32 dur; /* TUs */ -+} wl_rm_req_elt_t; -+ -+typedef struct wl_rm_req { -+ uint32 token; /* overall measurement set token */ -+ uint32 count; /* number of measurement requests */ -+ void *cb; /* completion callback function: may be NULL */ -+ void *cb_arg; /* arg to completion callback function */ -+ wl_rm_req_elt_t req[1]; /* variable length block of requests */ -+} wl_rm_req_t; -+#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req) -+ -+typedef struct wl_rm_rep_elt { -+ int8 type; -+ int8 flags; -+ chanspec_t chanspec; -+ uint32 token; /* token for this measurement */ -+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ -+ uint32 tsf_l; /* TSF low 32-bits */ -+ uint32 dur; /* TUs */ -+ uint32 len; /* byte length of data block */ -+ uint8 data[1]; /* variable length data block */ -+} wl_rm_rep_elt_t; -+#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ -+ -+#define WL_RPI_REP_BIN_NUM 8 -+typedef struct wl_rm_rpi_rep { -+ uint8 rpi[WL_RPI_REP_BIN_NUM]; -+ int8 rpi_max[WL_RPI_REP_BIN_NUM]; -+} wl_rm_rpi_rep_t; -+ -+typedef struct wl_rm_rep { -+ uint32 token; /* overall measurement set token */ -+ uint32 len; /* length of measurement report block */ -+ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ -+} wl_rm_rep_t; -+#define WL_RM_REP_FIXED_LEN 8 -+ -+ -+#if defined(BCMSUP_PSK) -+typedef enum sup_auth_status { -+ /* Basic supplicant authentication states */ -+ WLC_SUP_DISCONNECTED = 0, -+ WLC_SUP_CONNECTING, -+ WLC_SUP_IDREQUIRED, -+ WLC_SUP_AUTHENTICATING, -+ WLC_SUP_AUTHENTICATED, -+ WLC_SUP_KEYXCHANGE, -+ WLC_SUP_KEYED, -+ WLC_SUP_TIMEOUT, -+ WLC_SUP_LAST_BASIC_STATE, -+ -+ /* Extended supplicant authentication states */ -+ /* Waiting to receive handshake msg M1 */ -+ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, -+ /* Preparing to send handshake msg M2 */ -+ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, -+ /* Waiting to receive handshake msg M3 */ -+ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, -+ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */ -+ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */ -+ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */ -+} sup_auth_status_t; -+#endif -+ -+/* Enumerate crypto algorithms */ -+#define CRYPTO_ALGO_OFF 0 -+#define CRYPTO_ALGO_WEP1 1 -+#define CRYPTO_ALGO_TKIP 2 -+#define CRYPTO_ALGO_WEP128 3 -+#define CRYPTO_ALGO_AES_CCM 4 -+#define CRYPTO_ALGO_AES_OCB_MSDU 5 -+#define CRYPTO_ALGO_AES_OCB_MPDU 6 -+#define CRYPTO_ALGO_NALG 7 -+#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ -+ -+#define WSEC_GEN_MIC_ERROR 0x0001 -+#define WSEC_GEN_REPLAY 0x0002 -+#define WSEC_GEN_ICV_ERROR 0x0004 -+#define WSEC_GEN_MFP_ACT_ERROR 0x0008 -+#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010 -+#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020 -+ -+#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ -+#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ -+#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ -+#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ -+#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ -+ -+typedef struct wl_wsec_key { -+ uint32 index; /* key index */ -+ uint32 len; /* key length */ -+ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ -+ uint32 pad_1[18]; -+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ -+ uint32 flags; /* misc flags */ -+ uint32 pad_2[2]; -+ int pad_3; -+ int iv_initialized; /* has IV been initialized already? */ -+ int pad_4; -+ /* Rx IV */ -+ struct { -+ uint32 hi; /* upper 32 bits of IV */ -+ uint16 lo; /* lower 16 bits of IV */ -+ } rxiv; -+ uint32 pad_5[2]; -+ struct ether_addr ea; /* per station */ -+} wl_wsec_key_t; -+ -+#define WSEC_MIN_PSK_LEN 8 -+#define WSEC_MAX_PSK_LEN 64 -+ -+/* Flag for key material needing passhash'ing */ -+#define WSEC_PASSPHRASE (1<<0) -+ -+/* receptacle for WLC_SET_WSEC_PMK parameter */ -+typedef struct { -+ ushort key_len; /* octets in key material */ -+ ushort flags; /* key handling qualification */ -+ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ -+} wsec_pmk_t; -+ -+/* wireless security bitvec */ -+#define WEP_ENABLED 0x0001 -+#define TKIP_ENABLED 0x0002 -+#define AES_ENABLED 0x0004 -+#define WSEC_SWFLAG 0x0008 -+#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ -+ -+/* wsec macros for operating on the above definitions */ -+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) -+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) -+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) -+ -+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) -+#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) -+ -+#ifdef MFP -+#define MFP_CAPABLE 0x0200 -+#define MFP_REQUIRED 0x0400 -+#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ -+#endif /* MFP */ -+ -+/* WPA authentication mode bitvec */ -+#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ -+#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ -+#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ -+#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ -+/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ -+#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ -+#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ -+#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ -+#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ -+#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ -+#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ -+#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ -+#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ -+ -+/* pmkid */ -+#define MAXPMKID 16 -+ -+typedef struct _pmkid { -+ struct ether_addr BSSID; -+ uint8 PMKID[WPA2_PMKID_LEN]; -+} pmkid_t; -+ -+typedef struct _pmkid_list { -+ uint32 npmkid; -+ pmkid_t pmkid[1]; -+} pmkid_list_t; -+ -+typedef struct _pmkid_cand { -+ struct ether_addr BSSID; -+ uint8 preauth; -+} pmkid_cand_t; -+ -+typedef struct _pmkid_cand_list { -+ uint32 npmkid_cand; -+ pmkid_cand_t pmkid_cand[1]; -+} pmkid_cand_list_t; -+ -+typedef struct wl_assoc_info { -+ uint32 req_len; -+ uint32 resp_len; -+ uint32 flags; -+ struct dot11_assoc_req req; -+ struct ether_addr reassoc_bssid; /* used in reassoc's */ -+ struct dot11_assoc_resp resp; -+} wl_assoc_info_t; -+ -+/* flags */ -+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+typedef struct wl_led_info { -+ uint32 index; /* led index */ -+ uint32 behavior; -+ uint8 activehi; -+} wl_led_info_t; -+ -+ -+/* srom read/write struct passed through ioctl */ -+typedef struct { -+ uint byteoff; /* byte offset */ -+ uint nbytes; /* number of bytes */ -+ uint16 buf[1]; -+} srom_rw_t; -+ -+/* similar cis (srom or otp) struct [iovar: may not be aligned] */ -+typedef struct { -+ uint32 source; /* cis source */ -+ uint32 byteoff; /* byte offset */ -+ uint32 nbytes; /* number of bytes */ -+ /* data follows here */ -+} cis_rw_t; -+ -+#define WLC_CIS_DEFAULT 0 /* built-in default */ -+#define WLC_CIS_SROM 1 /* source is sprom */ -+#define WLC_CIS_OTP 2 /* source is otp */ -+ -+/* R_REG and W_REG struct passed through ioctl */ -+typedef struct { -+ uint32 byteoff; /* byte offset of the field in d11regs_t */ -+ uint32 val; /* read/write value of the field */ -+ uint32 size; /* sizeof the field */ -+ uint band; /* band (optional) */ -+} rw_reg_t; -+ -+/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ -+/* PCL - Power Control Loop */ -+/* current gain setting is replaced by user input */ -+#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ -+#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ -+/* current gain setting is maintained */ -+#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ -+ -+typedef struct { -+ uint16 auto_ctrl; /* WL_ATTEN_XX */ -+ uint16 bb; /* Baseband attenuation */ -+ uint16 radio; /* Radio attenuation */ -+ uint16 txctl1; /* Radio TX_CTL1 value */ -+} atten_t; -+ -+/* Per-AC retry parameters */ -+struct wme_tx_params_s { -+ uint8 short_retry; -+ uint8 short_fallback; -+ uint8 long_retry; -+ uint8 long_fallback; -+ uint16 max_rate; /* In units of 512 Kbps */ -+}; -+ -+typedef struct wme_tx_params_s wme_tx_params_t; -+ -+#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) -+ -+/* defines used by poweridx iovar - it controls power in a-band */ -+/* current gain setting is maintained */ -+#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ -+#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ -+#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ -+#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ -+/* value >= 0 causes -+ * - input to be set to that value -+ * - PCL to be off -+ */ -+ -+/* Used to get specific link/ac parameters */ -+typedef struct { -+ int ac; -+ uint8 val; -+ struct ether_addr ea; -+} link_val_t; -+ -+#define BCM_MAC_STATUS_INDICATION (0x40010200L) -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+typedef struct { -+ uint16 ver; /* version of this struct */ -+ uint16 len; /* length in bytes of this structure */ -+ uint16 cap; /* sta's advertised capabilities */ -+ uint32 flags; /* flags defined below */ -+ uint32 idle; /* time since data pkt rx'd from sta */ -+ struct ether_addr ea; /* Station address */ -+ wl_rateset_t rateset; /* rateset in use */ -+ uint32 in; /* seconds elapsed since associated */ -+ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ -+ uint32 tx_pkts; /* # of packets transmitted */ -+ uint32 tx_failures; /* # of packets failed */ -+ uint32 rx_ucast_pkts; /* # of unicast packets received */ -+ uint32 rx_mcast_pkts; /* # of multicast packets received */ -+ uint32 tx_rate; /* Rate of last successful tx frame */ -+ uint32 rx_rate; /* Rate of last successful rx frame */ -+ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ -+ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ -+} sta_info_t; -+ -+#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts) -+ -+#define WL_STA_VER 3 -+ -+/* Flags for sta_info_t indicating properties of STA */ -+#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ -+#define WL_STA_WME 0x2 /* WMM association */ -+#define WL_STA_UNUSED 0x4 -+#define WL_STA_AUTHE 0x8 /* Authenticated */ -+#define WL_STA_ASSOC 0x10 /* Associated */ -+#define WL_STA_AUTHO 0x20 /* Authorized */ -+#define WL_STA_WDS 0x40 /* Wireless Distribution System */ -+#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ -+#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ -+#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ -+#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ -+#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ -+#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ -+#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ -+#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ -+ -+#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ -+ -+/* Values for TX Filter override mode */ -+#define WLC_TXFILTER_OVERRIDE_DISABLED 0 -+#define WLC_TXFILTER_OVERRIDE_ENABLED 1 -+ -+/* Used to get specific STA parameters */ -+typedef struct { -+ uint32 val; -+ struct ether_addr ea; -+} scb_val_t; -+ -+/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */ -+typedef struct { -+ uint32 code; -+ scb_val_t ioctl_args; -+} authops_t; -+ -+/* channel encoding */ -+typedef struct channel_info { -+ int hw_channel; -+ int target_channel; -+ int scan_channel; -+} channel_info_t; -+ -+/* For ioctls that take a list of MAC addresses */ -+struct maclist { -+ uint count; /* number of MAC addresses */ -+ struct ether_addr ea[1]; /* variable length array of MAC addresses */ -+}; -+ -+/* get pkt count struct passed through ioctl */ -+typedef struct get_pktcnt { -+ uint rx_good_pkt; -+ uint rx_bad_pkt; -+ uint tx_good_pkt; -+ uint tx_bad_pkt; -+ uint rx_ocast_good_pkt; /* unicast packets destined for others */ -+} get_pktcnt_t; -+ -+/* NINTENDO2 */ -+#define LQ_IDX_MIN 0 -+#define LQ_IDX_MAX 1 -+#define LQ_IDX_AVG 2 -+#define LQ_IDX_SUM 2 -+#define LQ_IDX_LAST 3 -+#define LQ_STOP_MONITOR 0 -+#define LQ_START_MONITOR 1 -+ -+/* Get averages RSSI, Rx PHY rate and SNR values */ -+typedef struct { -+ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */ -+ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */ -+ int isvalid; /* Flag indicating whether above data is valid */ -+} wl_lq_t; /* Link Quality */ -+ -+typedef enum wl_wakeup_reason_type { -+ LCD_ON = 1, -+ LCD_OFF, -+ DRC1_WAKE, -+ DRC2_WAKE, -+ REASON_LAST -+} wl_wr_type_t; -+ -+typedef struct { -+/* Unique filter id */ -+ uint32 id; -+ -+/* stores the reason for the last wake up */ -+ uint8 reason; -+} wl_wr_t; -+ -+/* Get MAC specific rate histogram command */ -+typedef struct { -+ struct ether_addr ea; /* MAC Address */ -+ uint8 ac_cat; /* Access Category */ -+ uint8 num_pkts; /* Number of packet entries to be averaged */ -+} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */ -+ -+/* Get MAC rate histogram response */ -+typedef struct { -+ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ -+ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ -+ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ -+ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ -+} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */ -+ -+/* Values for TX Filter override mode */ -+#define WLC_TXFILTER_OVERRIDE_DISABLED 0 -+#define WLC_TXFILTER_OVERRIDE_ENABLED 1 -+ -+#define WL_IOCTL_ACTION_GET 0x0 -+#define WL_IOCTL_ACTION_SET 0x1 -+#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e -+#define WL_IOCTL_ACTION_OVL_RSV 0x20 -+#define WL_IOCTL_ACTION_OVL 0x40 -+#define WL_IOCTL_ACTION_MASK 0x7e -+#define WL_IOCTL_ACTION_OVL_SHIFT 1 -+ -+/* Linux network driver ioctl encoding */ -+typedef struct wl_ioctl { -+ uint cmd; /* common ioctl definition */ -+ void *buf; /* pointer to user buffer */ -+ uint len; /* length of user buffer */ -+ uint8 set; /* 1=set IOCTL; 0=query IOCTL */ -+ uint used; /* bytes read or written (optional) */ -+ uint needed; /* bytes needed (optional) */ -+} wl_ioctl_t; -+ -+/* reference to wl_ioctl_t struct used by usermode driver */ -+#define ioctl_subtype set /* subtype param */ -+#define ioctl_pid used /* pid param */ -+#define ioctl_status needed /* status param */ -+ -+/* -+ * Structure for passing hardware and software -+ * revision info up from the driver. -+ */ -+typedef struct wlc_rev_info { -+ uint vendorid; /* PCI vendor id */ -+ uint deviceid; /* device id of chip */ -+ uint radiorev; /* radio revision */ -+ uint chiprev; /* chip revision */ -+ uint corerev; /* core revision */ -+ uint boardid; /* board identifier (usu. PCI sub-device id) */ -+ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ -+ uint boardrev; /* board revision */ -+ uint driverrev; /* driver version */ -+ uint ucoderev; /* microcode version */ -+ uint bus; /* bus type */ -+ uint chipnum; /* chip number */ -+ uint phytype; /* phy type */ -+ uint phyrev; /* phy revision */ -+ uint anarev; /* anacore rev */ -+ uint chippkg; /* chip package info */ -+} wlc_rev_info_t; -+ -+#define WL_REV_INFO_LEGACY_LENGTH 48 -+ -+#define WL_BRAND_MAX 10 -+typedef struct wl_instance_info { -+ uint instance; -+ char brand[WL_BRAND_MAX]; -+} wl_instance_info_t; -+ -+/* structure to change size of tx fifo */ -+typedef struct wl_txfifo_sz { -+ uint16 magic; -+ uint16 fifo; -+ uint16 size; -+} wl_txfifo_sz_t; -+/* magic pattern used for mismatch driver and wl */ -+#define WL_TXFIFO_SZ_MAGIC 0xa5a5 -+ -+/* Transfer info about an IOVar from the driver */ -+/* Max supported IOV name size in bytes, + 1 for nul termination */ -+#define WLC_IOV_NAME_LEN 30 -+typedef struct wlc_iov_trx_s { -+ uint8 module; -+ uint8 type; -+ char name[WLC_IOV_NAME_LEN]; -+} wlc_iov_trx_t; -+ -+/* check this magic number */ -+#define WLC_IOCTL_MAGIC 0x14e46c77 -+ -+/* bump this number if you change the ioctl interface */ -+#ifdef D11AC_IOTYPES -+#define WLC_IOCTL_VERSION 2 -+#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1 -+#else -+#define WLC_IOCTL_VERSION 1 -+#endif /* D11AC_IOTYPES */ -+ -+#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ -+#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ -+#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ -+#ifdef WLC_HIGH_ONLY -+#define WLC_SAMPLECOLLECT_MAXLEN 1024 /* limit sample size for bmac */ -+#else -+#if defined(LCNCONF) || defined(LCN40CONF) -+#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ -+#else -+#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ -+#endif -+#endif /* WLC_HIGH_ONLY */ -+ -+/* common ioctl definitions */ -+#define WLC_GET_MAGIC 0 -+#define WLC_GET_VERSION 1 -+#define WLC_UP 2 -+#define WLC_DOWN 3 -+#define WLC_GET_LOOP 4 -+#define WLC_SET_LOOP 5 -+#define WLC_DUMP 6 -+#define WLC_GET_MSGLEVEL 7 -+#define WLC_SET_MSGLEVEL 8 -+#define WLC_GET_PROMISC 9 -+#define WLC_SET_PROMISC 10 -+/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */ -+#define WLC_GET_RATE 12 -+#define WLC_GET_MAX_RATE 13 -+#define WLC_GET_INSTANCE 14 -+/* #define WLC_GET_FRAG 15 */ /* no longer supported */ -+/* #define WLC_SET_FRAG 16 */ /* no longer supported */ -+/* #define WLC_GET_RTS 17 */ /* no longer supported */ -+/* #define WLC_SET_RTS 18 */ /* no longer supported */ -+#define WLC_GET_INFRA 19 -+#define WLC_SET_INFRA 20 -+#define WLC_GET_AUTH 21 -+#define WLC_SET_AUTH 22 -+#define WLC_GET_BSSID 23 -+#define WLC_SET_BSSID 24 -+#define WLC_GET_SSID 25 -+#define WLC_SET_SSID 26 -+#define WLC_RESTART 27 -+#define WLC_TERMINATED 28 -+/* #define WLC_DUMP_SCB 28 */ /* no longer supported */ -+#define WLC_GET_CHANNEL 29 -+#define WLC_SET_CHANNEL 30 -+#define WLC_GET_SRL 31 -+#define WLC_SET_SRL 32 -+#define WLC_GET_LRL 33 -+#define WLC_SET_LRL 34 -+#define WLC_GET_PLCPHDR 35 -+#define WLC_SET_PLCPHDR 36 -+#define WLC_GET_RADIO 37 -+#define WLC_SET_RADIO 38 -+#define WLC_GET_PHYTYPE 39 -+#define WLC_DUMP_RATE 40 -+#define WLC_SET_RATE_PARAMS 41 -+#define WLC_GET_FIXRATE 42 -+#define WLC_SET_FIXRATE 43 -+/* #define WLC_GET_WEP 42 */ /* no longer supported */ -+/* #define WLC_SET_WEP 43 */ /* no longer supported */ -+#define WLC_GET_KEY 44 -+#define WLC_SET_KEY 45 -+#define WLC_GET_REGULATORY 46 -+#define WLC_SET_REGULATORY 47 -+#define WLC_GET_PASSIVE_SCAN 48 -+#define WLC_SET_PASSIVE_SCAN 49 -+#define WLC_SCAN 50 -+#define WLC_SCAN_RESULTS 51 -+#define WLC_DISASSOC 52 -+#define WLC_REASSOC 53 -+#define WLC_GET_ROAM_TRIGGER 54 -+#define WLC_SET_ROAM_TRIGGER 55 -+#define WLC_GET_ROAM_DELTA 56 -+#define WLC_SET_ROAM_DELTA 57 -+#define WLC_GET_ROAM_SCAN_PERIOD 58 -+#define WLC_SET_ROAM_SCAN_PERIOD 59 -+#define WLC_EVM 60 /* diag */ -+#define WLC_GET_TXANT 61 -+#define WLC_SET_TXANT 62 -+#define WLC_GET_ANTDIV 63 -+#define WLC_SET_ANTDIV 64 -+/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ -+/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ -+#define WLC_GET_CLOSED 67 -+#define WLC_SET_CLOSED 68 -+#define WLC_GET_MACLIST 69 -+#define WLC_SET_MACLIST 70 -+#define WLC_GET_RATESET 71 -+#define WLC_SET_RATESET 72 -+/* #define WLC_GET_LOCALE 73 */ /* no longer supported */ -+#define WLC_LONGTRAIN 74 -+#define WLC_GET_BCNPRD 75 -+#define WLC_SET_BCNPRD 76 -+#define WLC_GET_DTIMPRD 77 -+#define WLC_SET_DTIMPRD 78 -+#define WLC_GET_SROM 79 -+#define WLC_SET_SROM 80 -+#define WLC_GET_WEP_RESTRICT 81 -+#define WLC_SET_WEP_RESTRICT 82 -+#define WLC_GET_COUNTRY 83 -+#define WLC_SET_COUNTRY 84 -+#define WLC_GET_PM 85 -+#define WLC_SET_PM 86 -+#define WLC_GET_WAKE 87 -+#define WLC_SET_WAKE 88 -+/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */ -+#define WLC_GET_FORCELINK 90 /* ndis only */ -+#define WLC_SET_FORCELINK 91 /* ndis only */ -+#define WLC_FREQ_ACCURACY 92 /* diag */ -+#define WLC_CARRIER_SUPPRESS 93 /* diag */ -+#define WLC_GET_PHYREG 94 -+#define WLC_SET_PHYREG 95 -+#define WLC_GET_RADIOREG 96 -+#define WLC_SET_RADIOREG 97 -+#define WLC_GET_REVINFO 98 -+#define WLC_GET_UCANTDIV 99 -+#define WLC_SET_UCANTDIV 100 -+#define WLC_R_REG 101 -+#define WLC_W_REG 102 -+/* #define WLC_DIAG_LOOPBACK 103 old tray diag */ -+/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */ -+#define WLC_GET_MACMODE 105 -+#define WLC_SET_MACMODE 106 -+#define WLC_GET_MONITOR 107 -+#define WLC_SET_MONITOR 108 -+#define WLC_GET_GMODE 109 -+#define WLC_SET_GMODE 110 -+#define WLC_GET_LEGACY_ERP 111 -+#define WLC_SET_LEGACY_ERP 112 -+#define WLC_GET_RX_ANT 113 -+#define WLC_GET_CURR_RATESET 114 /* current rateset */ -+#define WLC_GET_SCANSUPPRESS 115 -+#define WLC_SET_SCANSUPPRESS 116 -+#define WLC_GET_AP 117 -+#define WLC_SET_AP 118 -+#define WLC_GET_EAP_RESTRICT 119 -+#define WLC_SET_EAP_RESTRICT 120 -+#define WLC_SCB_AUTHORIZE 121 -+#define WLC_SCB_DEAUTHORIZE 122 -+#define WLC_GET_WDSLIST 123 -+#define WLC_SET_WDSLIST 124 -+#define WLC_GET_ATIM 125 -+#define WLC_SET_ATIM 126 -+#define WLC_GET_RSSI 127 -+#define WLC_GET_PHYANTDIV 128 -+#define WLC_SET_PHYANTDIV 129 -+#define WLC_AP_RX_ONLY 130 -+#define WLC_GET_TX_PATH_PWR 131 -+#define WLC_SET_TX_PATH_PWR 132 -+#define WLC_GET_WSEC 133 -+#define WLC_SET_WSEC 134 -+#define WLC_GET_PHY_NOISE 135 -+#define WLC_GET_BSS_INFO 136 -+#define WLC_GET_PKTCNTS 137 -+#define WLC_GET_LAZYWDS 138 -+#define WLC_SET_LAZYWDS 139 -+#define WLC_GET_BANDLIST 140 -+#define WLC_GET_BAND 141 -+#define WLC_SET_BAND 142 -+#define WLC_SCB_DEAUTHENTICATE 143 -+#define WLC_GET_SHORTSLOT 144 -+#define WLC_GET_SHORTSLOT_OVERRIDE 145 -+#define WLC_SET_SHORTSLOT_OVERRIDE 146 -+#define WLC_GET_SHORTSLOT_RESTRICT 147 -+#define WLC_SET_SHORTSLOT_RESTRICT 148 -+#define WLC_GET_GMODE_PROTECTION 149 -+#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 -+#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 -+#define WLC_UPGRADE 152 -+/* #define WLC_GET_MRATE 153 */ /* no longer supported */ -+/* #define WLC_SET_MRATE 154 */ /* no longer supported */ -+#define WLC_GET_IGNORE_BCNS 155 -+#define WLC_SET_IGNORE_BCNS 156 -+#define WLC_GET_SCB_TIMEOUT 157 -+#define WLC_SET_SCB_TIMEOUT 158 -+#define WLC_GET_ASSOCLIST 159 -+#define WLC_GET_CLK 160 -+#define WLC_SET_CLK 161 -+#define WLC_GET_UP 162 -+#define WLC_OUT 163 -+#define WLC_GET_WPA_AUTH 164 -+#define WLC_SET_WPA_AUTH 165 -+#define WLC_GET_UCFLAGS 166 -+#define WLC_SET_UCFLAGS 167 -+#define WLC_GET_PWRIDX 168 -+#define WLC_SET_PWRIDX 169 -+#define WLC_GET_TSSI 170 -+#define WLC_GET_SUP_RATESET_OVERRIDE 171 -+#define WLC_SET_SUP_RATESET_OVERRIDE 172 -+/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */ -+/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */ -+/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */ -+/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */ -+/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */ -+#define WLC_GET_PROTECTION_CONTROL 178 -+#define WLC_SET_PROTECTION_CONTROL 179 -+#define WLC_GET_PHYLIST 180 -+#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */ -+#define WLC_DECRYPT_STATUS 182 /* ndis only */ -+#define WLC_GET_KEY_SEQ 183 -+#define WLC_GET_SCAN_CHANNEL_TIME 184 -+#define WLC_SET_SCAN_CHANNEL_TIME 185 -+#define WLC_GET_SCAN_UNASSOC_TIME 186 -+#define WLC_SET_SCAN_UNASSOC_TIME 187 -+#define WLC_GET_SCAN_HOME_TIME 188 -+#define WLC_SET_SCAN_HOME_TIME 189 -+#define WLC_GET_SCAN_NPROBES 190 -+#define WLC_SET_SCAN_NPROBES 191 -+#define WLC_GET_PRB_RESP_TIMEOUT 192 -+#define WLC_SET_PRB_RESP_TIMEOUT 193 -+#define WLC_GET_ATTEN 194 -+#define WLC_SET_ATTEN 195 -+#define WLC_GET_SHMEM 196 /* diag */ -+#define WLC_SET_SHMEM 197 /* diag */ -+/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ -+/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ -+#define WLC_SET_WSEC_TEST 200 -+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 -+#define WLC_TKIP_COUNTERMEASURES 202 -+#define WLC_GET_PIOMODE 203 -+#define WLC_SET_PIOMODE 204 -+#define WLC_SET_ASSOC_PREFER 205 -+#define WLC_GET_ASSOC_PREFER 206 -+#define WLC_SET_ROAM_PREFER 207 -+#define WLC_GET_ROAM_PREFER 208 -+#define WLC_SET_LED 209 -+#define WLC_GET_LED 210 -+#define WLC_GET_INTERFERENCE_MODE 211 -+#define WLC_SET_INTERFERENCE_MODE 212 -+#define WLC_GET_CHANNEL_QA 213 -+#define WLC_START_CHANNEL_QA 214 -+#define WLC_GET_CHANNEL_SEL 215 -+#define WLC_START_CHANNEL_SEL 216 -+#define WLC_GET_VALID_CHANNELS 217 -+#define WLC_GET_FAKEFRAG 218 -+#define WLC_SET_FAKEFRAG 219 -+#define WLC_GET_PWROUT_PERCENTAGE 220 -+#define WLC_SET_PWROUT_PERCENTAGE 221 -+#define WLC_SET_BAD_FRAME_PREEMPT 222 -+#define WLC_GET_BAD_FRAME_PREEMPT 223 -+#define WLC_SET_LEAP_LIST 224 -+#define WLC_GET_LEAP_LIST 225 -+#define WLC_GET_CWMIN 226 -+#define WLC_SET_CWMIN 227 -+#define WLC_GET_CWMAX 228 -+#define WLC_SET_CWMAX 229 -+#define WLC_GET_WET 230 -+#define WLC_SET_WET 231 -+#define WLC_GET_PUB 232 -+/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */ -+/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */ -+#define WLC_GET_KEY_PRIMARY 235 -+#define WLC_SET_KEY_PRIMARY 236 -+/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ -+#define WLC_GET_ACI_ARGS 238 -+#define WLC_SET_ACI_ARGS 239 -+#define WLC_UNSET_CALLBACK 240 -+#define WLC_SET_CALLBACK 241 -+#define WLC_GET_RADAR 242 -+#define WLC_SET_RADAR 243 -+#define WLC_SET_SPECT_MANAGMENT 244 -+#define WLC_GET_SPECT_MANAGMENT 245 -+#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ -+#define WLC_WDS_GET_WPA_SUP 247 -+#define WLC_SET_CS_SCAN_TIMER 248 -+#define WLC_GET_CS_SCAN_TIMER 249 -+#define WLC_MEASURE_REQUEST 250 -+#define WLC_INIT 251 -+#define WLC_SEND_QUIET 252 -+#define WLC_KEEPALIVE 253 -+#define WLC_SEND_PWR_CONSTRAINT 254 -+#define WLC_UPGRADE_STATUS 255 -+#define WLC_CURRENT_PWR 256 -+#define WLC_GET_SCAN_PASSIVE_TIME 257 -+#define WLC_SET_SCAN_PASSIVE_TIME 258 -+#define WLC_LEGACY_LINK_BEHAVIOR 259 -+#define WLC_GET_CHANNELS_IN_COUNTRY 260 -+#define WLC_GET_COUNTRY_LIST 261 -+#define WLC_GET_VAR 262 /* get value of named variable */ -+#define WLC_SET_VAR 263 /* set named variable to value */ -+#define WLC_NVRAM_GET 264 /* deprecated */ -+#define WLC_NVRAM_SET 265 -+#define WLC_NVRAM_DUMP 266 -+#define WLC_REBOOT 267 -+#define WLC_SET_WSEC_PMK 268 -+#define WLC_GET_AUTH_MODE 269 -+#define WLC_SET_AUTH_MODE 270 -+#define WLC_GET_WAKEENTRY 271 -+#define WLC_SET_WAKEENTRY 272 -+#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ -+#define WLC_NVOTPW 274 -+#define WLC_OTPW 275 -+#define WLC_IOV_BLOCK_GET 276 -+#define WLC_IOV_MODULES_GET 277 -+#define WLC_SOFT_RESET 278 -+#define WLC_GET_ALLOW_MODE 279 -+#define WLC_SET_ALLOW_MODE 280 -+#define WLC_GET_DESIRED_BSSID 281 -+#define WLC_SET_DESIRED_BSSID 282 -+#define WLC_DISASSOC_MYAP 283 -+#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */ -+#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */ -+#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */ -+#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */ -+#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */ -+#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */ -+#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */ -+#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */ -+#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */ -+#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */ -+#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */ -+#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */ -+#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */ -+#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */ -+#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */ -+#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */ -+#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */ -+#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */ -+#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */ -+#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */ -+#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */ -+#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */ -+#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */ -+#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */ -+/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */ -+#define WLC_GET_CMD 309 -+/* #define WLC_LAST 310 */ /* Never used - can be reused */ -+#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */ -+#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */ -+/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */ -+/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */ -+/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ -+#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ -+#define WLC_GET_NAT_STATE 317 -+#define WLC_LAST 318 -+ -+#ifndef EPICTRL_COOKIE -+#define EPICTRL_COOKIE 0xABADCEDE -+#endif -+ -+/* vx wlc ioctl's offset */ -+#define CMN_IOCTL_OFF 0x180 -+ -+/* -+ * custom OID support -+ * -+ * 0xFF - implementation specific OID -+ * 0xE4 - first byte of Broadcom PCI vendor ID -+ * 0x14 - second byte of Broadcom PCI vendor ID -+ * 0xXX - the custom OID number -+ */ -+ -+/* begin 0x1f values beyond the start of the ET driver range. */ -+#define WL_OID_BASE 0xFFE41420 -+ -+/* NDIS overrides */ -+#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) -+#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) -+#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) -+#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) -+#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) -+#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) -+#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) -+ -+/* EXT_STA Dongle suuport */ -+#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) -+#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) -+#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) -+#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) -+#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) -+#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) -+#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) -+#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) -+#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) -+#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) -+#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) -+#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) -+#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) -+#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) -+#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) -+ -+/* NAT filter driver support */ -+#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG) -+#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE) -+ -+#define WL_DECRYPT_STATUS_SUCCESS 1 -+#define WL_DECRYPT_STATUS_FAILURE 2 -+#define WL_DECRYPT_STATUS_UNKNOWN 3 -+ -+/* allows user-mode app to poll the status of USB image upgrade */ -+#define WLC_UPGRADE_SUCCESS 0 -+#define WLC_UPGRADE_PENDING 1 -+ -+#ifdef CONFIG_USBRNDIS_RETAIL -+/* struct passed in for WLC_NDCONFIG_ITEM */ -+typedef struct { -+ char *name; -+ void *param; -+} ndconfig_item_t; -+#endif -+ -+ -+/* WLC_GET_AUTH, WLC_SET_AUTH values */ -+#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ -+#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ -+#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ -+ -+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ -+#define WL_RADIO_SW_DISABLE (1<<0) -+#define WL_RADIO_HW_DISABLE (1<<1) -+#define WL_RADIO_MPC_DISABLE (1<<2) -+#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ -+ -+#define WL_SPURAVOID_OFF 0 -+#define WL_SPURAVOID_ON1 1 -+#define WL_SPURAVOID_ON2 2 -+ -+/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ -+#define WL_TXPWR_OVERRIDE (1U<<31) -+#define WL_TXPWR_NEG (1U<<30) -+ -+#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ -+ -+#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ -+#define WL_PHY_PAVAR_VER 1 /* pavars version */ -+typedef struct wl_pavars2 { -+ uint16 ver; /* version of this struct */ -+ uint16 len; /* len of this structure */ -+ uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ -+ uint16 phy_type; /* phy type */ -+ uint16 bandrange; -+ uint16 chain; -+ uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ -+} wl_pavars2_t; -+ -+typedef struct wl_po { -+ uint16 phy_type; /* Phy type */ -+ uint16 band; -+ uint16 cckpo; -+ uint32 ofdmpo; -+ uint16 mcspo[8]; -+} wl_po_t; -+ -+/* a large TX Power as an init value to factor out of MIN() calculations, -+ * keep low enough to fit in an int8, units are .25 dBm -+ */ -+#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ -+ -+/* "diag" iovar argument and error code */ -+#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ -+#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */ -+#define WL_DIAG_MEMORY 3 /* d11 memory test */ -+#define WL_DIAG_LED 4 /* LED test */ -+#define WL_DIAG_REG 5 /* d11/phy register test */ -+#define WL_DIAG_SROM 6 /* srom read/crc test */ -+#define WL_DIAG_DMA 7 /* DMA test */ -+#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */ -+ -+#define WL_DIAGERR_SUCCESS 0 -+#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ -+#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ -+#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ -+#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ -+#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ -+#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ -+#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ -+#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ -+#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ -+#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ -+ -+#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */ -+#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */ -+ -+/* band types */ -+#define WLC_BAND_AUTO 0 /* auto-select */ -+#define WLC_BAND_5G 1 /* 5 Ghz */ -+#define WLC_BAND_2G 2 /* 2.4 Ghz */ -+#define WLC_BAND_ALL 3 /* all bands */ -+ -+/* band range returned by band_range iovar */ -+#define WL_CHAN_FREQ_RANGE_2G 0 -+#define WL_CHAN_FREQ_RANGE_5GL 1 -+#define WL_CHAN_FREQ_RANGE_5GM 2 -+#define WL_CHAN_FREQ_RANGE_5GH 3 -+ -+#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 -+#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 -+#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 -+#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 -+#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 -+ -+#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 -+#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 -+#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 -+#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 -+ -+#define WL_CHAN_FREQ_RANGE_5G_4BAND 5 -+ -+/* phy types (returned by WLC_GET_PHYTPE) */ -+#define WLC_PHY_TYPE_A 0 -+#define WLC_PHY_TYPE_B 1 -+#define WLC_PHY_TYPE_G 2 -+#define WLC_PHY_TYPE_N 4 -+#define WLC_PHY_TYPE_LP 5 -+#define WLC_PHY_TYPE_SSN 6 -+#define WLC_PHY_TYPE_HT 7 -+#define WLC_PHY_TYPE_LCN 8 -+#define WLC_PHY_TYPE_LCN40 10 -+#define WLC_PHY_TYPE_AC 11 -+#define WLC_PHY_TYPE_NULL 0xf -+ -+/* MAC list modes */ -+#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ -+#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ -+#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ -+ -+/* -+ * 54g modes (basic bits may still be overridden) -+ * -+ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 -+ * Preamble: Long -+ * Shortslot: Off -+ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 -+ * Extended Rateset: 6, 9, 12, 48 -+ * Preamble: Long -+ * Shortslot: Auto -+ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 -+ * Extended Rateset: 6b, 9, 12b, 48 -+ * Preamble: Short required -+ * Shortslot: Auto -+ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 -+ * Extended Rateset: 6, 9, 12, 48 -+ * Preamble: Long -+ * Shortslot: On -+ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 -+ * Preamble: Short required -+ * Shortslot: On and required -+ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b -+ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 -+ * Preamble: Long -+ * Shortslot: Auto -+ */ -+#define GMODE_LEGACY_B 0 -+#define GMODE_AUTO 1 -+#define GMODE_ONLY 2 -+#define GMODE_B_DEFERRED 3 -+#define GMODE_PERFORMANCE 4 -+#define GMODE_LRS 5 -+#define GMODE_MAX 6 -+ -+/* values for PLCPHdr_override */ -+#define WLC_PLCP_AUTO -1 -+#define WLC_PLCP_SHORT 0 -+#define WLC_PLCP_LONG 1 -+ -+/* values for g_protection_override and n_protection_override */ -+#define WLC_PROTECTION_AUTO -1 -+#define WLC_PROTECTION_OFF 0 -+#define WLC_PROTECTION_ON 1 -+#define WLC_PROTECTION_MMHDR_ONLY 2 -+#define WLC_PROTECTION_CTS_ONLY 3 -+ -+/* values for g_protection_control and n_protection_control */ -+#define WLC_PROTECTION_CTL_OFF 0 -+#define WLC_PROTECTION_CTL_LOCAL 1 -+#define WLC_PROTECTION_CTL_OVERLAP 2 -+ -+/* values for n_protection */ -+#define WLC_N_PROTECTION_OFF 0 -+#define WLC_N_PROTECTION_OPTIONAL 1 -+#define WLC_N_PROTECTION_20IN40 2 -+#define WLC_N_PROTECTION_MIXEDMODE 3 -+ -+/* values for n_preamble_type */ -+#define WLC_N_PREAMBLE_MIXEDMODE 0 -+#define WLC_N_PREAMBLE_GF 1 -+#define WLC_N_PREAMBLE_GF_BRCM 2 -+ -+/* values for band specific 40MHz capabilities (deprecated) */ -+#define WLC_N_BW_20ALL 0 -+#define WLC_N_BW_40ALL 1 -+#define WLC_N_BW_20IN2G_40IN5G 2 -+ -+#define WLC_BW_20MHZ_BIT (1<<0) -+#define WLC_BW_40MHZ_BIT (1<<1) -+#define WLC_BW_80MHZ_BIT (1<<2) -+ -+/* Bandwidth capabilities */ -+#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) -+#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) -+#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) -+#define WLC_BW_CAP_UNRESTRICTED 0xFF -+ -+#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE) -+#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE) -+#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE) -+ -+/* values to force tx/rx chain */ -+#define WLC_N_TXRX_CHAIN0 0 -+#define WLC_N_TXRX_CHAIN1 1 -+ -+/* bitflags for SGI support (sgi_rx iovar) */ -+#define WLC_N_SGI_20 0x01 -+#define WLC_N_SGI_40 0x02 -+ -+/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ -+#define WLC_SGI_ALL 0x02 -+ -+/* Values for PM */ -+#define PM_OFF 0 -+#define PM_MAX 1 -+#define PM_FAST 2 -+#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */ -+ -+#define LISTEN_INTERVAL 10 -+/* interference mitigation options */ -+#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ -+#define INTERFERE_NONE 0 /* off */ -+#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */ -+#define WLAN_MANUAL 2 /* ACI: no auto detection */ -+#define WLAN_AUTO 3 /* ACI: auto detect */ -+#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ -+#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ -+ -+typedef struct wl_aci_args { -+ int enter_aci_thresh; /* Trigger level to start detecting ACI */ -+ int exit_aci_thresh; /* Trigger level to exit ACI mode */ -+ int usec_spin; /* microsecs to delay between rssi samples */ -+ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */ -+ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */ -+ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */ -+ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */ -+ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */ -+ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */ -+ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */ -+ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */ -+ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */ -+ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */ -+ uint16 nphy_noise_noassoc_glitch_th_dn; -+ uint16 nphy_noise_assoc_glitch_th_up; -+ uint16 nphy_noise_assoc_glitch_th_dn; -+ uint16 nphy_noise_assoc_aci_glitch_th_up; -+ uint16 nphy_noise_assoc_aci_glitch_th_dn; -+ uint16 nphy_noise_assoc_enter_th; -+ uint16 nphy_noise_noassoc_enter_th; -+ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th; -+ uint16 nphy_noise_noassoc_crsidx_incr; -+ uint16 nphy_noise_assoc_crsidx_incr; -+ uint16 nphy_noise_crsidx_decr; -+} wl_aci_args_t; -+ -+#define TRIGGER_NOW 0 -+#define TRIGGER_CRS 0x01 -+#define TRIGGER_CRSDEASSERT 0x02 -+#define TRIGGER_GOODFCS 0x04 -+#define TRIGGER_BADFCS 0x08 -+#define TRIGGER_BADPLCP 0x10 -+#define TRIGGER_CRSGLITCH 0x20 -+#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */ -+#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */ -+typedef struct wl_samplecollect_args { -+ /* version 0 fields */ -+ uint8 coll_us; -+ int cores; -+ /* add'l version 1 fields */ -+ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */ -+ uint16 length; /* length of entire structure */ -+ int8 trigger; -+ uint16 timeout; -+ uint16 mode; -+ uint32 pre_dur; -+ uint32 post_dur; -+ uint8 gpio_sel; -+ bool downsamp; -+ bool be_deaf; -+ bool agc; /* loop from init gain and going down */ -+ bool filter; /* override high pass corners to lowest */ -+ /* add'l version 2 fields */ -+ uint8 trigger_state; -+ uint8 module_sel1; -+ uint8 module_sel2; -+ uint16 nsamps; -+} wl_samplecollect_args_t; -+ -+#define WL_SAMPLEDATA_HEADER_TYPE 1 -+#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */ -+#define WL_SAMPLEDATA_TYPE 2 -+#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */ -+#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */ -+#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */ -+/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */ -+#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2 -+ -+typedef struct wl_sampledata { -+ uint16 version; /* structure version */ -+ uint16 size; /* size of structure */ -+ uint16 tag; /* Header/Data */ -+ uint16 length; /* data length */ -+ uint32 flag; /* bit def */ -+} wl_sampledata_t; -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+/* wl_radar_args_t */ -+typedef struct { -+ int npulses; /* required number of pulses at n * t_int */ -+ int ncontig; /* required number of pulses at t_int */ -+ int min_pw; /* minimum pulse width (20 MHz clocks) */ -+ int max_pw; /* maximum pulse width (20 MHz clocks) */ -+ uint16 thresh0; /* Radar detection, thresh 0 */ -+ uint16 thresh1; /* Radar detection, thresh 1 */ -+ uint16 blank; /* Radar detection, blank control */ -+ uint16 fmdemodcfg; /* Radar detection, fmdemod config */ -+ int npulses_lp; /* Radar detection, minimum long pulses */ -+ int min_pw_lp; /* Minimum pulsewidth for long pulses */ -+ int max_pw_lp; /* Maximum pulsewidth for long pulses */ -+ int min_fm_lp; /* Minimum fm for long pulses */ -+ int max_span_lp; /* Maximum deltat for long pulses */ -+ int min_deltat; /* Minimum spacing between pulses */ -+ int max_deltat; /* Maximum spacing between pulses */ -+ uint16 autocorr; /* Radar detection, autocorr on or off */ -+ uint16 st_level_time; /* Radar detection, start_timing level */ -+ uint16 t2_min; /* minimum clocks needed to remain in state 2 */ -+ uint32 version; /* version */ -+ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */ -+ int npulses_fra; /* Radar detection, minimum French pulses set */ -+ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */ -+ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */ -+ uint16 percal_mask; /* defines which period cal is masked from radar detection */ -+ int quant; /* quantization resolution to pulse positions */ -+ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */ -+ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */ -+ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */ -+ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */ -+ uint16 feature_mask; /* 16-bit mask to specify enabled features */ -+} wl_radar_args_t; -+ -+#define WL_RADAR_ARGS_VERSION 2 -+ -+typedef struct { -+ uint32 version; /* version */ -+ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */ -+ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */ -+ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */ -+ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */ -+ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */ -+ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */ -+ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */ -+ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */ -+ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */ -+ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */ -+ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */ -+ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */ -+ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */ -+ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */ -+ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */ -+ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */ -+} wl_radar_thr_t; -+ -+#define WL_RADAR_THR_VERSION 2 -+#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */ -+ -+/* radar iovar SET defines */ -+#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ -+#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ -+#define WL_RADAR_SIMULATED 2 /* force radar detector to declare -+ * detection once -+ */ -+#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */ -+#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ -+#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ -+#define WL_ANT_IDX_1 0 /* antenna index 1 */ -+#define WL_ANT_IDX_2 1 /* antenna index 2 */ -+ -+#ifndef WL_RSSI_ANT_MAX -+#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ -+#elif WL_RSSI_ANT_MAX != 4 -+#error "WL_RSSI_ANT_MAX does not match" -+#endif -+ -+/* RSSI per antenna */ -+typedef struct { -+ uint32 version; /* version field */ -+ uint32 count; /* number of valid antenna rssi */ -+ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */ -+} wl_rssi_ant_t; -+ -+/* dfs_status iovar-related defines */ -+ -+/* cac - channel availability check, -+ * ism - in-service monitoring -+ * csa - channel switching announcement -+ */ -+ -+/* cac state values */ -+#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ -+#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ -+#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ -+#define WL_DFS_CACSTATE_CSA 3 /* csa */ -+#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ -+#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ -+#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ -+#define WL_DFS_CACSTATES 7 /* this many states exist */ -+ -+/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ -+typedef struct { -+ uint state; /* noted by WL_DFS_CACSTATE_XX. */ -+ uint duration; /* time spent in ms in state. */ -+ /* as dfs enters ISM state, it removes the operational channel from quiet channel -+ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared -+ */ -+ chanspec_t chanspec_cleared; -+ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ -+ uint16 pad; -+} wl_dfs_status_t; -+ -+#define NUM_PWRCTRL_RATES 12 -+ -+typedef struct { -+ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */ -+ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */ -+ uint8 txpwr_local_max; /* local max according to the AP */ -+ uint8 txpwr_local_constraint; /* local constraint according to the AP */ -+ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */ -+ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */ -+ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ -+ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */ -+ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */ -+ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */ -+ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */ -+ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */ -+ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ -+} tx_power_legacy_t; -+ -+#define WL_TX_POWER_RATES_LEGACY 45 -+#define WL_TX_POWER_MCS20_FIRST 12 -+#define WL_TX_POWER_MCS20_NUM 16 -+#define WL_TX_POWER_MCS40_FIRST 28 -+#define WL_TX_POWER_MCS40_NUM 17 -+ -+typedef struct { -+ uint32 flags; -+ chanspec_t chanspec; /* txpwr report for this channel */ -+ chanspec_t local_chanspec; /* channel on which we are associated */ -+ uint8 local_max; /* local max according to the AP */ -+ uint8 local_constraint; /* local constraint according to the AP */ -+ int8 antgain[2]; /* Ant gain for each band - from SROM */ -+ uint8 rf_cores; /* count of RF Cores being reported */ -+ uint8 est_Pout[4]; /* Latest tx power out estimate per RF -+ * chain without adjustment -+ */ -+ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ -+ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ -+ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ -+ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ -+ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ -+} tx_power_legacy2_t; -+ -+/* TX Power index defines */ -+#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */ -+#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */ -+#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */ -+#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */ -+#define WL_NUM_RATES_VHT 10 -+#define WL_NUM_RATES_MCS32 1 -+ -+#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK -+#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM -+#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM -+#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM -+#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32 -+#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK -+#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM -+#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM -+#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM -+#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32 -+ -+#define WL_NUM_2x2_ELEMENTS 4 -+#define WL_NUM_3x3_ELEMENTS 6 -+ -+typedef struct txppr { -+ /* start of 20MHz tx power limits */ -+ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ /* start of 40MHz tx power limits */ -+ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ /* start of 20in40MHz tx power limits */ -+ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ -+ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ /* start of 80MHz tx power limits */ -+ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ /* start of 20in80MHz tx power limits */ -+ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ /* start of 40in80MHz tx power limits */ -+ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ -+ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ -+ -+ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ -+ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ -+ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ -+ -+ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ -+ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ -+ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ -+ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ -+ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ -+ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ -+ -+ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ -+ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ -+ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ -+ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ -+ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ -+ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ -+ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ -+ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ -+ -+ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ -+} txppr_t; -+ -+/* 20MHz */ -+#define WL_TX_POWER_CCK_FIRST OFFSETOF(txppr_t, b20_1x1dsss) -+#define WL_TX_POWER_OFDM20_FIRST OFFSETOF(txppr_t, b20_1x1ofdm) -+#define WL_TX_POWER_MCS20_SISO_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) -+#define WL_TX_POWER_20_S1x1_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) -+ -+#define WL_TX_POWER_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2dsss) -+#define WL_TX_POWER_OFDM20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_ofdm) -+#define WL_TX_POWER_MCS20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) -+#define WL_TX_POWER_20_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) -+#define WL_TX_POWER_MCS20_STBC_FIRST OFFSETOF(txppr_t, b20_2x2stbc_mcs0) -+#define WL_TX_POWER_MCS20_SDM_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) -+#define WL_TX_POWER_20_S2x2_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3dsss) -+#define WL_TX_POWER_OFDM20_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_ofdm) -+#define WL_TX_POWER_20_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_mcs0) -+#define WL_TX_POWER_20_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3stbc_mcs0) -+#define WL_TX_POWER_20_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3sdm_mcs8) -+#define WL_TX_POWER_20_S3x3_FIRST OFFSETOF(txppr_t, b20_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_20_S1X1_VHT OFFSETOF(txppr_t, b20_1x1vht) -+#define WL_TX_POWER_20_S1X2_CDD_VHT OFFSETOF(txppr_t, b20_1x2cdd_vht) -+#define WL_TX_POWER_20_S2X2_STBC_VHT OFFSETOF(txppr_t, b20_2x2stbc_vht) -+#define WL_TX_POWER_20_S2X2_VHT OFFSETOF(txppr_t, b20_2x2sdm_vht) -+#define WL_TX_POWER_20_S1X3_CDD_VHT OFFSETOF(txppr_t, b20_1x3cdd_vht) -+#define WL_TX_POWER_20_S2X3_STBC_VHT OFFSETOF(txppr_t, b20_2x3stbc_vht) -+#define WL_TX_POWER_20_S2X3_VHT OFFSETOF(txppr_t, b20_2x3sdm_vht) -+#define WL_TX_POWER_20_S3X3_VHT OFFSETOF(txppr_t, b20_3x3sdm_vht) -+ -+/* 40MHz */ -+#define WL_TX_POWER_40_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40_dummy1x1dsss) -+#define WL_TX_POWER_OFDM40_FIRST OFFSETOF(txppr_t, b40_1x1ofdm) -+#define WL_TX_POWER_MCS40_SISO_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) -+#define WL_TX_POWER_40_S1x1_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) -+ -+#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40_dummy1x2dsss) -+#define WL_TX_POWER_OFDM40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_ofdm) -+#define WL_TX_POWER_MCS40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) -+#define WL_TX_POWER_40_S1x2_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) -+#define WL_TX_POWER_MCS40_STBC_FIRST OFFSETOF(txppr_t, b40_2x2stbc_mcs0) -+#define WL_TX_POWER_MCS40_SDM_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) -+#define WL_TX_POWER_40_S2x2_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_dummy1x3dsss) -+#define WL_TX_POWER_OFDM40_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_ofdm) -+#define WL_TX_POWER_40_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_mcs0) -+#define WL_TX_POWER_40_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3stbc_mcs0) -+#define WL_TX_POWER_40_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3sdm_mcs8) -+#define WL_TX_POWER_40_S3x3_FIRST OFFSETOF(txppr_t, b40_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_40_S1X1_VHT OFFSETOF(txppr_t, b40_1x1vht) -+#define WL_TX_POWER_40_S1X2_CDD_VHT OFFSETOF(txppr_t, b40_1x2cdd_vht) -+#define WL_TX_POWER_40_S2X2_STBC_VHT OFFSETOF(txppr_t, b40_2x2stbc_vht) -+#define WL_TX_POWER_40_S2X2_VHT OFFSETOF(txppr_t, b40_2x2sdm_vht) -+#define WL_TX_POWER_40_S1X3_CDD_VHT OFFSETOF(txppr_t, b40_1x3cdd_vht) -+#define WL_TX_POWER_40_S2X3_STBC_VHT OFFSETOF(txppr_t, b40_2x3stbc_vht) -+#define WL_TX_POWER_40_S2X3_VHT OFFSETOF(txppr_t, b40_2x3sdm_vht) -+#define WL_TX_POWER_40_S3X3_VHT OFFSETOF(txppr_t, b40_3x3sdm_vht) -+ -+/* 20 in 40MHz */ -+#define WL_TX_POWER_20UL_CCK_FIRST OFFSETOF(txppr_t, b20in40_1x1dsss) -+#define WL_TX_POWER_20UL_OFDM_FIRST OFFSETOF(txppr_t, b20in40_1x1ofdm) -+#define WL_TX_POWER_20UL_S1x1_FIRST OFFSETOF(txppr_t, b20in40_1x1mcs0) -+ -+#define WL_TX_POWER_CCK_20U_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2dsss) -+#define WL_TX_POWER_20UL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_ofdm) -+#define WL_TX_POWER_20UL_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_mcs0) -+#define WL_TX_POWER_20UL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2stbc_mcs0) -+#define WL_TX_POWER_20UL_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_CCK_20U_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3dsss) -+#define WL_TX_POWER_20UL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_ofdm) -+#define WL_TX_POWER_20UL_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_mcs0) -+#define WL_TX_POWER_20UL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3stbc_mcs0) -+#define WL_TX_POWER_20UL_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3sdm_mcs8) -+#define WL_TX_POWER_20UL_S3x3_FIRST OFFSETOF(txppr_t, b20in40_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_20UL_S1X1_VHT OFFSETOF(txppr_t, b20in40_1x1vht) -+#define WL_TX_POWER_20UL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in40_1x2cdd_vht) -+#define WL_TX_POWER_20UL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in40_2x2stbc_vht) -+#define WL_TX_POWER_20UL_S2X2_VHT OFFSETOF(txppr_t, b20in40_2x2sdm_vht) -+#define WL_TX_POWER_20UL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in40_1x3cdd_vht) -+#define WL_TX_POWER_20UL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in40_2x3stbc_vht) -+#define WL_TX_POWER_20UL_S2X3_VHT OFFSETOF(txppr_t, b20in40_2x3sdm_vht) -+#define WL_TX_POWER_20UL_S3X3_VHT OFFSETOF(txppr_t, b20in40_3x3sdm_vht) -+ -+/* 80MHz */ -+#define WL_TX_POWER_80_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b80_dummy1x1dsss) -+#define WL_TX_POWER_OFDM80_FIRST OFFSETOF(txppr_t, b80_1x1ofdm) -+#define WL_TX_POWER_MCS80_SISO_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) -+#define WL_TX_POWER_80_S1x1_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) -+ -+#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b80_dummy1x2dsss) -+#define WL_TX_POWER_OFDM80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_ofdm) -+#define WL_TX_POWER_MCS80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) -+#define WL_TX_POWER_80_S1x2_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) -+#define WL_TX_POWER_MCS80_STBC_FIRST OFFSETOF(txppr_t, b80_2x2stbc_mcs0) -+#define WL_TX_POWER_MCS80_SDM_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) -+#define WL_TX_POWER_80_S2x2_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_dummy1x3dsss) -+#define WL_TX_POWER_OFDM80_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_ofdm) -+#define WL_TX_POWER_80_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_mcs0) -+#define WL_TX_POWER_80_STBC_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3stbc_mcs0) -+#define WL_TX_POWER_80_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3sdm_mcs8) -+#define WL_TX_POWER_80_S3x3_FIRST OFFSETOF(txppr_t, b80_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_80_S1X1_VHT OFFSETOF(txppr_t, b80_1x1vht) -+#define WL_TX_POWER_80_S1X2_CDD_VHT OFFSETOF(txppr_t, b80_1x2cdd_vht) -+#define WL_TX_POWER_80_S2X2_STBC_VHT OFFSETOF(txppr_t, b80_2x2stbc_vht) -+#define WL_TX_POWER_80_S2X2_VHT OFFSETOF(txppr_t, b80_2x2sdm_vht) -+#define WL_TX_POWER_80_S1X3_CDD_VHT OFFSETOF(txppr_t, b80_1x3cdd_vht) -+#define WL_TX_POWER_80_S2X3_STBC_VHT OFFSETOF(txppr_t, b80_2x3stbc_vht) -+#define WL_TX_POWER_80_S2X3_VHT OFFSETOF(txppr_t, b80_2x3sdm_vht) -+#define WL_TX_POWER_80_S3X3_VHT OFFSETOF(txppr_t, b80_3x3sdm_vht) -+ -+/* 20 in 80MHz */ -+#define WL_TX_POWER_20UUL_CCK_FIRST OFFSETOF(txppr_t, b20in80_1x1dsss) -+#define WL_TX_POWER_20UUL_OFDM_FIRST OFFSETOF(txppr_t, b20in80_1x1ofdm) -+#define WL_TX_POWER_20UUL_S1x1_FIRST OFFSETOF(txppr_t, b20in80_1x1mcs0) -+ -+#define WL_TX_POWER_CCK_20UU_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2dsss) -+#define WL_TX_POWER_20UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_ofdm) -+#define WL_TX_POWER_20UUL_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_mcs0) -+#define WL_TX_POWER_20UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2stbc_mcs0) -+#define WL_TX_POWER_20UUL_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_CCK_20UU_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3dsss) -+#define WL_TX_POWER_20UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_ofdm) -+#define WL_TX_POWER_20UUL_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_mcs0) -+#define WL_TX_POWER_20UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3stbc_mcs0) -+#define WL_TX_POWER_20UUL_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3sdm_mcs8) -+#define WL_TX_POWER_20UUL_S3x3_FIRST OFFSETOF(txppr_t, b20in80_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_20UUL_S1X1_VHT OFFSETOF(txppr_t, b20in80_1x1vht) -+#define WL_TX_POWER_20UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in80_1x2cdd_vht) -+#define WL_TX_POWER_20UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in80_2x2stbc_vht) -+#define WL_TX_POWER_20UUL_S2X2_VHT OFFSETOF(txppr_t, b20in80_2x2sdm_vht) -+#define WL_TX_POWER_20UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in80_1x3cdd_vht) -+#define WL_TX_POWER_20UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in80_2x3stbc_vht) -+#define WL_TX_POWER_20UUL_S2X3_VHT OFFSETOF(txppr_t, b20in80_2x3sdm_vht) -+#define WL_TX_POWER_20UUL_S3X3_VHT OFFSETOF(txppr_t, b20in80_3x3sdm_vht) -+ -+/* 40 in 80MHz */ -+#define WL_TX_POWER_40UUL_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40in80_dummy1x1dsss) -+#define WL_TX_POWER_40UUL_OFDM_FIRST OFFSETOF(txppr_t, b40in80_1x1ofdm) -+#define WL_TX_POWER_40UUL_S1x1_FIRST OFFSETOF(txppr_t, b40in80_1x1mcs0) -+ -+#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40in80_dummy1x2dsss) -+#define WL_TX_POWER_40UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_ofdm) -+#define WL_TX_POWER_40UUL_S1x2_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_mcs0) -+#define WL_TX_POWER_40UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2stbc_mcs0) -+#define WL_TX_POWER_40UUL_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2sdm_mcs8) -+ -+#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_dummy1x3dsss) -+#define WL_TX_POWER_40UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_ofdm) -+#define WL_TX_POWER_40UUL_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_mcs0) -+#define WL_TX_POWER_40UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3stbc_mcs0) -+#define WL_TX_POWER_40UUL_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3sdm_mcs8) -+#define WL_TX_POWER_40UUL_S3x3_FIRST OFFSETOF(txppr_t, b40in80_3x3sdm_mcs16) -+ -+#define WL_TX_POWER_40UUL_S1X1_VHT OFFSETOF(txppr_t, b40in80_1x1vht) -+#define WL_TX_POWER_40UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b40in80_1x2cdd_vht) -+#define WL_TX_POWER_40UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b40in80_2x2stbc_vht) -+#define WL_TX_POWER_40UUL_S2X2_VHT OFFSETOF(txppr_t, b40in80_2x2sdm_vht) -+#define WL_TX_POWER_40UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b40in80_1x3cdd_vht) -+#define WL_TX_POWER_40UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b40in80_2x3stbc_vht) -+#define WL_TX_POWER_40UUL_S2X3_VHT OFFSETOF(txppr_t, b40in80_2x3sdm_vht) -+#define WL_TX_POWER_40UUL_S3X3_VHT OFFSETOF(txppr_t, b40in80_3x3sdm_vht) -+ -+#define WL_TX_POWER_MCS_32 OFFSETOF(txppr_t, mcs32) /* C_CHECK remove later */ -+ -+#define WL_TX_POWER_RATES sizeof(struct txppr) -+ -+/* sslpnphy specifics */ -+#define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST -+#define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST -+ -+typedef struct { -+ uint16 ver; /* version of this struct */ -+ uint16 len; /* length in bytes of this structure */ -+ uint32 flags; -+ chanspec_t chanspec; /* txpwr report for this channel */ -+ chanspec_t local_chanspec; /* channel on which we are associated */ -+ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ -+} wl_txppr_t; -+ -+#define WL_TXPPR_VERSION 0 -+#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) -+#define TX_POWER_T_VERSION 43 -+ -+/* Defines used with channel_bandwidth for curpower */ -+#define WL_BW_20MHZ 0 -+#define WL_BW_40MHZ 1 -+#define WL_BW_80MHZ 2 -+ -+/* tx_power_t.flags bits */ -+#ifdef PPR_API -+#define WL_TX_POWER2_F_ENABLED 1 -+#define WL_TX_POWER2_F_HW 2 -+#define WL_TX_POWER2_F_MIMO 4 -+#define WL_TX_POWER2_F_SISO 8 -+#define WL_TX_POWER2_F_HT 0x10 -+#else -+#define WL_TX_POWER_F_ENABLED 1 -+#define WL_TX_POWER_F_HW 2 -+#define WL_TX_POWER_F_MIMO 4 -+#define WL_TX_POWER_F_SISO 8 -+#define WL_TX_POWER_F_HT 0x10 -+#endif -+ -+typedef struct { -+ uint32 flags; -+ chanspec_t chanspec; /* txpwr report for this channel */ -+ chanspec_t local_chanspec; /* channel on which we are associated */ -+ uint8 local_max; /* local max according to the AP */ -+ uint8 local_constraint; /* local constraint according to the AP */ -+ int8 antgain[2]; /* Ant gain for each band - from SROM */ -+ uint8 rf_cores; /* count of RF Cores being reported */ -+ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ -+ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ -+ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ -+ uint8 tx_power_max[4]; /* Maximum target power among all rates */ -+ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ -+ uint8 user_limit[WL_TX_POWER_RATES]; /* User limit */ -+ int8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ -+ int8 target[WL_TX_POWER_RATES]; /* Latest target power */ -+ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ -+ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ -+ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ -+ int8 sar; /* SAR limit for display by wl executable */ -+ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ -+ uint8 version; /* Version of the data format wlu <--> driver */ -+ uint8 display_core; /* Displayed curpower core */ -+#ifdef PPR_API -+} tx_power_new_t; -+#else -+} tx_power_t; -+#endif -+ -+typedef struct tx_inst_power { -+ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ -+ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ -+} tx_inst_power_t; -+ -+ -+typedef struct { -+ uint32 flags; -+ chanspec_t chanspec; /* txpwr report for this channel */ -+ chanspec_t local_chanspec; /* channel on which we are associated */ -+ uint8 local_max; /* local max according to the AP */ -+ uint8 local_constraint; /* local constraint according to the AP */ -+ int8 antgain[2]; /* Ant gain for each band - from SROM */ -+ uint8 rf_cores; /* count of RF Cores being reported */ -+ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ -+ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain -+ * without adjustment -+ */ -+ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ -+ uint8 tx_power_max[4]; /* Maximum target power among all rates */ -+ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ -+ txppr_t user_limit; /* User limit */ -+ txppr_t reg_limit; /* Regulatory power limit */ -+ txppr_t board_limit; /* Max power board can support (SROM) */ -+ txppr_t target; /* Latest target power */ -+} wl_txpwr_t; -+ -+#define WL_NUM_TXCHAIN_MAX 4 -+typedef struct wl_txchain_pwr_offsets { -+ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */ -+} wl_txchain_pwr_offsets_t; -+ -+/* 802.11h measurement types */ -+#define WLC_MEASURE_TPC 1 -+#define WLC_MEASURE_CHANNEL_BASIC 2 -+#define WLC_MEASURE_CHANNEL_CCA 3 -+#define WLC_MEASURE_CHANNEL_RPI 4 -+ -+/* regulatory enforcement levels */ -+#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ -+#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ -+#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ -+#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ -+/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE -+ * adoption is done regardless of capability spectrum_management -+ */ -+#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ -+ -+#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ -+#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ -+#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ -+#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ -+#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ -+#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ -+#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ -+ -+/* BTC mode used by "btc_mode" iovar */ -+#define WL_BTC_DISABLE 0 /* disable BT coexistence */ -+#define WL_BTC_FULLTDM 1 /* full TDM COEX */ -+#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */ -+#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */ -+#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */ -+#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */ -+#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */ -+#define WL_BTC_DEFAULT 8 /* set the default mode for the device */ -+#define WL_INF_BTC_DISABLE 0 -+#define WL_INF_BTC_ENABLE 1 -+#define WL_INF_BTC_AUTO 3 -+ -+/* BTC wire used by "btc_wire" iovar */ -+#define WL_BTC_DEFWIRE 0 /* use default wire setting */ -+#define WL_BTC_2WIRE 2 /* use 2-wire BTC */ -+#define WL_BTC_3WIRE 3 /* use 3-wire BTC */ -+#define WL_BTC_4WIRE 4 /* use 4-wire BTC */ -+ -+/* BTC flags: BTC configuration that can be set by host */ -+#define WL_BTC_FLAG_PREMPT (1 << 0) -+#define WL_BTC_FLAG_BT_DEF (1 << 1) -+#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) -+#define WL_BTC_FLAG_SIM_RSP (1 << 3) -+#define WL_BTC_FLAG_PS_PROTECT (1 << 4) -+#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) -+#define WL_BTC_FLAG_ECI (1 << 6) -+#define WL_BTC_FLAG_LIGHT (1 << 7) -+#define WL_BTC_FLAG_PARALLEL (1 << 8) -+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */ -+ -+/* Message levels */ -+#define WL_ERROR_VAL 0x00000001 -+#define WL_TRACE_VAL 0x00000002 -+#define WL_PRHDRS_VAL 0x00000004 -+#define WL_PRPKT_VAL 0x00000008 -+#define WL_INFORM_VAL 0x00000010 -+#define WL_TMP_VAL 0x00000020 -+#define WL_OID_VAL 0x00000040 -+#define WL_RATE_VAL 0x00000080 -+#define WL_ASSOC_VAL 0x00000100 -+#define WL_PRUSR_VAL 0x00000200 -+#define WL_PS_VAL 0x00000400 -+#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */ -+#define WL_PORT_VAL 0x00001000 -+#define WL_DUAL_VAL 0x00002000 -+#define WL_WSEC_VAL 0x00004000 -+#define WL_WSEC_DUMP_VAL 0x00008000 -+#define WL_LOG_VAL 0x00010000 -+#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */ -+#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */ -+#define WL_REGULATORY_VAL 0x00080000 -+#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */ -+#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */ -+#define WL_MPC_VAL 0x00400000 -+#define WL_APSTA_VAL 0x00800000 -+#define WL_DFS_VAL 0x01000000 -+#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */ -+#define WL_ACI_VAL 0x04000000 -+#define WL_MBSS_VAL 0x04000000 -+#define WL_CAC_VAL 0x08000000 -+#define WL_AMSDU_VAL 0x10000000 -+#define WL_AMPDU_VAL 0x20000000 -+#define WL_FFPLD_VAL 0x40000000 -+ -+/* wl_msg_level is full. For new bits take the next one and AND with -+ * wl_msg_level2 in wl_dbg.h -+ */ -+#define WL_DPT_VAL 0x00000001 -+#define WL_SCAN_VAL 0x00000002 -+#define WL_WOWL_VAL 0x00000004 -+#define WL_COEX_VAL 0x00000008 -+#define WL_RTDC_VAL 0x00000010 -+#define WL_PROTO_VAL 0x00000020 -+#define WL_BTA_VAL 0x00000040 -+#define WL_CHANINT_VAL 0x00000080 -+#define WL_THERMAL_VAL 0x00000100 /* retired in TOT on 6/10/2009 */ -+#define WL_P2P_VAL 0x00000200 -+#define WL_ITFR_VAL 0x00000400 -+#define WL_MCHAN_VAL 0x00000800 -+#define WL_TDLS_VAL 0x00001000 -+#define WL_MCNX_VAL 0x00002000 -+#define WL_PROT_VAL 0x00004000 -+#define WL_PSTA_VAL 0x00008000 -+#define WL_TSO_VAL 0x00010000 -+/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier -+ * rather than a message-type of its own -+ */ -+#define WL_TIMESTAMP_VAL 0x80000000 -+ -+/* max # of leds supported by GPIO (gpio pin# == led index#) */ -+#define WL_LED_NUMGPIO 32 /* gpio 0-31 */ -+ -+/* led per-pin behaviors */ -+#define WL_LED_OFF 0 /* always off */ -+#define WL_LED_ON 1 /* always on */ -+#define WL_LED_ACTIVITY 2 /* activity */ -+#define WL_LED_RADIO 3 /* radio enabled */ -+#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ -+#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ -+#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ -+#define WL_LED_WI1 7 -+#define WL_LED_WI2 8 -+#define WL_LED_WI3 9 -+#define WL_LED_ASSOC 10 /* associated state indicator */ -+#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ -+#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */ -+#define WL_LED_WI4 13 -+#define WL_LED_WI5 14 -+#define WL_LED_BLINKSLOW 15 /* blink slow */ -+#define WL_LED_BLINKMED 16 /* blink med */ -+#define WL_LED_BLINKFAST 17 /* blink fast */ -+#define WL_LED_BLINKCUSTOM 18 /* blink custom */ -+#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */ -+#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ -+ /* keep on for 300 sec */ -+#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ -+#define WL_LED_NUMBEHAVIOR 22 -+ -+/* led behavior numeric value format */ -+#define WL_LED_BEH_MASK 0x7f /* behavior mask */ -+#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ -+ -+/* maximum channels returned by the get valid channels iovar */ -+#define WL_NUMCHANNELS 64 -+ -+/* max number of chanspecs (used by the iovar to calc. buf space) */ -+#define WL_NUMCHANSPECS 110 -+ -+/* WDS link local endpoint WPA role */ -+#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ -+#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ -+#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ -+ -+/* number of bytes needed to define a 128-bit mask for MAC event reporting */ -+#define WL_EVENTING_MASK_LEN 16 -+ -+/* -+ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, -+ * a one-byte length, and a variable length value. RSSI type tuple must be present -+ * in the array. -+ * -+ * Types are defined in "join preference types" section. -+ * -+ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple -+ * and must be set to zero. -+ * -+ * Values are defined below. -+ * -+ * 1. RSSI - 2 octets -+ * offset 0: reserved -+ * offset 1: reserved -+ * -+ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below) -+ * offset 0: reserved -+ * offset 1: # of tuples -+ * offset 2: tuple 1 -+ * offset 14: tuple 2 -+ * ... -+ * offset 2 + 12 * (n - 1) octets: tuple n -+ * -+ * struct wpa_cfg_tuple { -+ * uint8 akm[DOT11_OUI_LEN+1]; akm suite -+ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite -+ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite -+ * }; -+ * -+ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY. -+ * -+ * 3. BAND - 2 octets -+ * offset 0: reserved -+ * offset 1: see "band preference" and "band types" -+ * -+ * 4. BAND RSSI - 2 octets -+ * offset 0: band types -+ * offset 1: +ve RSSI boost balue in dB -+ */ -+ -+/* join preference types */ -+#define WL_JOIN_PREF_RSSI 1 /* by RSSI */ -+#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */ -+#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */ -+#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */ -+#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */ -+ -+/* band preference */ -+#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */ -+ -+/* any multicast cipher suite */ -+#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" -+ -+struct tsinfo_arg { -+ uint8 octets[3]; -+}; -+ -+#define NFIFO 6 /* # tx/rx fifopairs */ -+ -+#define WL_CNT_T_VERSION 8 /* current version of wl_cnt_t struct */ -+ -+typedef struct { -+ uint16 version; /* see definition of WL_CNT_T_VERSION */ -+ uint16 length; /* length of entire structure */ -+ -+ /* transmit stat counters */ -+ uint32 txframe; /* tx data frames */ -+ uint32 txbyte; /* tx data bytes */ -+ uint32 txretrans; /* tx mac retransmits */ -+ uint32 txerror; /* tx data errors (derived: sum of others) */ -+ uint32 txctl; /* tx management frames */ -+ uint32 txprshort; /* tx short preamble frames */ -+ uint32 txserr; /* tx status errors */ -+ uint32 txnobuf; /* tx out of buffers errors */ -+ uint32 txnoassoc; /* tx discard because we're not associated */ -+ uint32 txrunt; /* tx runt frames */ -+ uint32 txchit; /* tx header cache hit (fastpath) */ -+ uint32 txcmiss; /* tx header cache miss (slowpath) */ -+ -+ /* transmit chip error counters */ -+ uint32 txuflo; /* tx fifo underflows */ -+ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ -+ uint32 txphycrs; -+ -+ /* receive stat counters */ -+ uint32 rxframe; /* rx data frames */ -+ uint32 rxbyte; /* rx data bytes */ -+ uint32 rxerror; /* rx data errors (derived: sum of others) */ -+ uint32 rxctl; /* rx management frames */ -+ uint32 rxnobuf; /* rx out of buffers errors */ -+ uint32 rxnondata; /* rx non data frames in the data channel errors */ -+ uint32 rxbadds; /* rx bad DS errors */ -+ uint32 rxbadcm; /* rx bad control or management frames */ -+ uint32 rxfragerr; /* rx fragmentation errors */ -+ uint32 rxrunt; /* rx runt frames */ -+ uint32 rxgiant; /* rx giant frames */ -+ uint32 rxnoscb; /* rx no scb error */ -+ uint32 rxbadproto; /* rx invalid frames */ -+ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ -+ uint32 rxbadda; /* rx frames tossed for invalid da */ -+ uint32 rxfilter; /* rx frames filtered out */ -+ -+ /* receive chip error counters */ -+ uint32 rxoflo; /* rx fifo overflow errors */ -+ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ -+ -+ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ -+ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ -+ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ -+ -+ /* misc counters */ -+ uint32 dmade; /* tx/rx dma descriptor errors */ -+ uint32 dmada; /* tx/rx dma data errors */ -+ uint32 dmape; /* tx/rx dma descriptor protocol errors */ -+ uint32 reset; /* reset count */ -+ uint32 tbtt; /* cnts the TBTT int's */ -+ uint32 txdmawar; -+ uint32 pkt_callback_reg_fail; /* callbacks register failure */ -+ -+ /* MAC counters: 32-bit version of d11.h's macstat_t */ -+ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, -+ * Control Management (includes retransmissions) -+ */ -+ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ -+ uint32 txctsfrm; /* number of CTS sent out by the MAC */ -+ uint32 txackfrm; /* number of ACK frames sent out */ -+ uint32 txdnlfrm; /* Not used */ -+ uint32 txbcnfrm; /* beacons transmitted */ -+ uint32 txfunfl[8]; /* per-fifo tx underflows */ -+ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS -+ * or BCN) -+ */ -+ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for -+ * driver enqueued frames -+ */ -+ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ -+ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ -+ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not -+ * data/control/management -+ */ -+ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ -+ uint32 rxbadplcp; /* parity check of the PLCP header failed */ -+ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ -+ uint32 rxstrt; /* Number of received frames with a good PLCP -+ * (i.e. passing parity check) -+ */ -+ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ -+ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ -+ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ -+ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ -+ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ -+ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ -+ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ -+ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ -+ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ -+ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ -+ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ -+ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ -+ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ -+ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC -+ * (unlikely to see these) -+ */ -+ uint32 rxbeaconmbss; /* beacons received from member of BSS */ -+ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from -+ * other BSS (WDS FRAME) -+ */ -+ uint32 rxbeaconobss; /* beacons received from other BSS */ -+ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames -+ * expecting a response -+ */ -+ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ -+ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ -+ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ -+ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ -+ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ -+ uint32 pmqovfl; /* Number of PMQ overflows */ -+ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into -+ * the PRQ fifo -+ */ -+ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ -+ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did -+ * not get ACK -+ */ -+ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ -+ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ -+ * fifo because a probe response could not be sent out within -+ * the time limit defined in M_PRS_MAXTIME -+ */ -+ uint32 rxnack; /* obsolete */ -+ uint32 frmscons; /* obsolete */ -+ uint32 txnack; /* obsolete */ -+ uint32 txglitch_nack; /* obsolete */ -+ uint32 txburst; /* obsolete */ -+ -+ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ -+ uint32 txfrag; /* dot11TransmittedFragmentCount */ -+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ -+ uint32 txfail; /* dot11FailedCount */ -+ uint32 txretry; /* dot11RetryCount */ -+ uint32 txretrie; /* dot11MultipleRetryCount */ -+ uint32 rxdup; /* dot11FrameduplicateCount */ -+ uint32 txrts; /* dot11RTSSuccessCount */ -+ uint32 txnocts; /* dot11RTSFailureCount */ -+ uint32 txnoack; /* dot11ACKFailureCount */ -+ uint32 rxfrag; /* dot11ReceivedFragmentCount */ -+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ -+ uint32 rxcrc; /* dot11FCSErrorCount */ -+ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ -+ uint32 rxundec; /* dot11WEPUndecryptableCount */ -+ -+ /* WPA2 counters (see rxundec for DecryptFailureCount) */ -+ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ -+ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ -+ uint32 tkipreplay; /* TKIPReplays */ -+ uint32 ccmpfmterr; /* CCMPFormatErrors */ -+ uint32 ccmpreplay; /* CCMPReplays */ -+ uint32 ccmpundec; /* CCMPDecryptErrors */ -+ uint32 fourwayfail; /* FourWayHandshakeFailures */ -+ uint32 wepundec; /* dot11WEPUndecryptableCount */ -+ uint32 wepicverr; /* dot11WEPICVErrorCount */ -+ uint32 decsuccess; /* DecryptSuccessCount */ -+ uint32 tkipicverr; /* TKIPICVErrorCount */ -+ uint32 wepexcluded; /* dot11WEPExcludedCount */ -+ -+ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ -+ uint32 psmwds; /* Count PSM watchdogs */ -+ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ -+ -+ /* MBSS counters, AP only */ -+ uint32 prq_entries_handled; /* PRQ entries read in */ -+ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ -+ uint32 prq_bad_entries; /* which could not be translated to info */ -+ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ -+ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ -+ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ -+ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ -+ -+ /* per-rate receive stat counters */ -+ uint32 rx1mbps; /* packets rx at 1Mbps */ -+ uint32 rx2mbps; /* packets rx at 2Mbps */ -+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ -+ uint32 rx6mbps; /* packets rx at 6Mbps */ -+ uint32 rx9mbps; /* packets rx at 9Mbps */ -+ uint32 rx11mbps; /* packets rx at 11Mbps */ -+ uint32 rx12mbps; /* packets rx at 12Mbps */ -+ uint32 rx18mbps; /* packets rx at 18Mbps */ -+ uint32 rx24mbps; /* packets rx at 24Mbps */ -+ uint32 rx36mbps; /* packets rx at 36Mbps */ -+ uint32 rx48mbps; /* packets rx at 48Mbps */ -+ uint32 rx54mbps; /* packets rx at 54Mbps */ -+ uint32 rx108mbps; /* packets rx at 108mbps */ -+ uint32 rx162mbps; /* packets rx at 162mbps */ -+ uint32 rx216mbps; /* packets rx at 216 mbps */ -+ uint32 rx270mbps; /* packets rx at 270 mbps */ -+ uint32 rx324mbps; /* packets rx at 324 mbps */ -+ uint32 rx378mbps; /* packets rx at 378 mbps */ -+ uint32 rx432mbps; /* packets rx at 432 mbps */ -+ uint32 rx486mbps; /* packets rx at 486 mbps */ -+ uint32 rx540mbps; /* packets rx at 540 mbps */ -+ -+ /* pkteng rx frame stats */ -+ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ -+ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ -+ -+ uint32 rfdisable; /* count of radio disables */ -+ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ -+ -+ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ -+ -+ uint32 txmpdu_sgi; /* count for sgi transmit */ -+ uint32 rxmpdu_sgi; /* count for sgi received */ -+ uint32 txmpdu_stbc; /* count for stbc transmit */ -+ uint32 rxmpdu_stbc; /* count for stbc received */ -+ -+ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ -+ -+ /* WPA2 counters (see rxundec for DecryptFailureCount) */ -+ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ -+ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ -+ uint32 tkipreplay_mcst; /* TKIPReplays */ -+ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ -+ uint32 ccmpreplay_mcst; /* CCMPReplays */ -+ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ -+ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ -+ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ -+ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ -+ uint32 decsuccess_mcst; /* DecryptSuccessCount */ -+ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ -+ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ -+ -+ uint32 dma_hang; /* count for dma hang */ -+ uint32 reinit; /* count for reinit */ -+ -+ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */ -+ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ -+ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */ -+ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */ -+ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ -+ -+ uint32 cso_passthrough; /* hw cso required but passthrough */ -+ uint32 cso_normal; /* hw cso hdr for normal process */ -+ uint32 chained; /* number of frames chained */ -+ uint32 chainedsz1; /* number of chain size 1 frames */ -+ uint32 unchained; /* number of frames not chained */ -+ uint32 maxchainsz; /* max chain size so far */ -+ uint32 currchainsz; /* current chain size */ -+} wl_cnt_t; -+ -+typedef struct { -+ uint16 version; /* see definition of WL_CNT_T_VERSION */ -+ uint16 length; /* length of entire structure */ -+ -+ /* transmit stat counters */ -+ uint32 txframe; /* tx data frames */ -+ uint32 txbyte; /* tx data bytes */ -+ uint32 txretrans; /* tx mac retransmits */ -+ uint32 txerror; /* tx data errors (derived: sum of others) */ -+ uint32 txctl; /* tx management frames */ -+ uint32 txprshort; /* tx short preamble frames */ -+ uint32 txserr; /* tx status errors */ -+ uint32 txnobuf; /* tx out of buffers errors */ -+ uint32 txnoassoc; /* tx discard because we're not associated */ -+ uint32 txrunt; /* tx runt frames */ -+ uint32 txchit; /* tx header cache hit (fastpath) */ -+ uint32 txcmiss; /* tx header cache miss (slowpath) */ -+ -+ /* transmit chip error counters */ -+ uint32 txuflo; /* tx fifo underflows */ -+ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ -+ uint32 txphycrs; -+ -+ /* receive stat counters */ -+ uint32 rxframe; /* rx data frames */ -+ uint32 rxbyte; /* rx data bytes */ -+ uint32 rxerror; /* rx data errors (derived: sum of others) */ -+ uint32 rxctl; /* rx management frames */ -+ uint32 rxnobuf; /* rx out of buffers errors */ -+ uint32 rxnondata; /* rx non data frames in the data channel errors */ -+ uint32 rxbadds; /* rx bad DS errors */ -+ uint32 rxbadcm; /* rx bad control or management frames */ -+ uint32 rxfragerr; /* rx fragmentation errors */ -+ uint32 rxrunt; /* rx runt frames */ -+ uint32 rxgiant; /* rx giant frames */ -+ uint32 rxnoscb; /* rx no scb error */ -+ uint32 rxbadproto; /* rx invalid frames */ -+ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ -+ uint32 rxbadda; /* rx frames tossed for invalid da */ -+ uint32 rxfilter; /* rx frames filtered out */ -+ -+ /* receive chip error counters */ -+ uint32 rxoflo; /* rx fifo overflow errors */ -+ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ -+ -+ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ -+ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ -+ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ -+ -+ /* misc counters */ -+ uint32 dmade; /* tx/rx dma descriptor errors */ -+ uint32 dmada; /* tx/rx dma data errors */ -+ uint32 dmape; /* tx/rx dma descriptor protocol errors */ -+ uint32 reset; /* reset count */ -+ uint32 tbtt; /* cnts the TBTT int's */ -+ uint32 txdmawar; -+ uint32 pkt_callback_reg_fail; /* callbacks register failure */ -+ -+ /* MAC counters: 32-bit version of d11.h's macstat_t */ -+ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, -+ * Control Management (includes retransmissions) -+ */ -+ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ -+ uint32 txctsfrm; /* number of CTS sent out by the MAC */ -+ uint32 txackfrm; /* number of ACK frames sent out */ -+ uint32 txdnlfrm; /* Not used */ -+ uint32 txbcnfrm; /* beacons transmitted */ -+ uint32 txfunfl[8]; /* per-fifo tx underflows */ -+ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS -+ * or BCN) -+ */ -+ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for -+ * driver enqueued frames -+ */ -+ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ -+ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ -+ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not -+ * data/control/management -+ */ -+ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ -+ uint32 rxbadplcp; /* parity check of the PLCP header failed */ -+ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ -+ uint32 rxstrt; /* Number of received frames with a good PLCP -+ * (i.e. passing parity check) -+ */ -+ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ -+ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ -+ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ -+ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ -+ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ -+ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ -+ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ -+ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ -+ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ -+ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ -+ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ -+ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ -+ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ -+ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC -+ * (unlikely to see these) -+ */ -+ uint32 rxbeaconmbss; /* beacons received from member of BSS */ -+ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from -+ * other BSS (WDS FRAME) -+ */ -+ uint32 rxbeaconobss; /* beacons received from other BSS */ -+ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames -+ * expecting a response -+ */ -+ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ -+ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ -+ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ -+ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ -+ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ -+ uint32 pmqovfl; /* Number of PMQ overflows */ -+ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into -+ * the PRQ fifo -+ */ -+ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ -+ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did -+ * not get ACK -+ */ -+ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ -+ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ -+ * fifo because a probe response could not be sent out within -+ * the time limit defined in M_PRS_MAXTIME -+ */ -+ uint32 rxnack; -+ uint32 frmscons; -+ uint32 txnack; -+ uint32 txglitch_nack; /* obsolete */ -+ uint32 txburst; /* obsolete */ -+ -+ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ -+ uint32 txfrag; /* dot11TransmittedFragmentCount */ -+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ -+ uint32 txfail; /* dot11FailedCount */ -+ uint32 txretry; /* dot11RetryCount */ -+ uint32 txretrie; /* dot11MultipleRetryCount */ -+ uint32 rxdup; /* dot11FrameduplicateCount */ -+ uint32 txrts; /* dot11RTSSuccessCount */ -+ uint32 txnocts; /* dot11RTSFailureCount */ -+ uint32 txnoack; /* dot11ACKFailureCount */ -+ uint32 rxfrag; /* dot11ReceivedFragmentCount */ -+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ -+ uint32 rxcrc; /* dot11FCSErrorCount */ -+ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ -+ uint32 rxundec; /* dot11WEPUndecryptableCount */ -+ -+ /* WPA2 counters (see rxundec for DecryptFailureCount) */ -+ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ -+ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ -+ uint32 tkipreplay; /* TKIPReplays */ -+ uint32 ccmpfmterr; /* CCMPFormatErrors */ -+ uint32 ccmpreplay; /* CCMPReplays */ -+ uint32 ccmpundec; /* CCMPDecryptErrors */ -+ uint32 fourwayfail; /* FourWayHandshakeFailures */ -+ uint32 wepundec; /* dot11WEPUndecryptableCount */ -+ uint32 wepicverr; /* dot11WEPICVErrorCount */ -+ uint32 decsuccess; /* DecryptSuccessCount */ -+ uint32 tkipicverr; /* TKIPICVErrorCount */ -+ uint32 wepexcluded; /* dot11WEPExcludedCount */ -+ -+ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ -+ -+ /* WPA2 counters (see rxundec for DecryptFailureCount) */ -+ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ -+ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ -+ uint32 tkipreplay_mcst; /* TKIPReplays */ -+ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ -+ uint32 ccmpreplay_mcst; /* CCMPReplays */ -+ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ -+ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ -+ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ -+ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ -+ uint32 decsuccess_mcst; /* DecryptSuccessCount */ -+ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ -+ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ -+ -+ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ -+ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ -+ uint32 psmwds; /* Count PSM watchdogs */ -+ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ -+ -+ /* MBSS counters, AP only */ -+ uint32 prq_entries_handled; /* PRQ entries read in */ -+ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ -+ uint32 prq_bad_entries; /* which could not be translated to info */ -+ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ -+ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ -+ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ -+ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ -+ -+ /* per-rate receive stat counters */ -+ uint32 rx1mbps; /* packets rx at 1Mbps */ -+ uint32 rx2mbps; /* packets rx at 2Mbps */ -+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ -+ uint32 rx6mbps; /* packets rx at 6Mbps */ -+ uint32 rx9mbps; /* packets rx at 9Mbps */ -+ uint32 rx11mbps; /* packets rx at 11Mbps */ -+ uint32 rx12mbps; /* packets rx at 12Mbps */ -+ uint32 rx18mbps; /* packets rx at 18Mbps */ -+ uint32 rx24mbps; /* packets rx at 24Mbps */ -+ uint32 rx36mbps; /* packets rx at 36Mbps */ -+ uint32 rx48mbps; /* packets rx at 48Mbps */ -+ uint32 rx54mbps; /* packets rx at 54Mbps */ -+ uint32 rx108mbps; /* packets rx at 108mbps */ -+ uint32 rx162mbps; /* packets rx at 162mbps */ -+ uint32 rx216mbps; /* packets rx at 216 mbps */ -+ uint32 rx270mbps; /* packets rx at 270 mbps */ -+ uint32 rx324mbps; /* packets rx at 324 mbps */ -+ uint32 rx378mbps; /* packets rx at 378 mbps */ -+ uint32 rx432mbps; /* packets rx at 432 mbps */ -+ uint32 rx486mbps; /* packets rx at 486 mbps */ -+ uint32 rx540mbps; /* packets rx at 540 mbps */ -+ -+ /* pkteng rx frame stats */ -+ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ -+ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ -+ -+ uint32 rfdisable; /* count of radio disables */ -+ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ -+ -+ uint32 txmpdu_sgi; /* count for sgi transmit */ -+ uint32 rxmpdu_sgi; /* count for sgi received */ -+ uint32 txmpdu_stbc; /* count for stbc transmit */ -+ uint32 rxmpdu_stbc; /* count for stbc received */ -+} wl_cnt_ver_six_t; -+ -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+#define WL_DELTA_STATS_T_VERSION 1 /* current version of wl_delta_stats_t struct */ -+ -+typedef struct { -+ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */ -+ uint16 length; /* length of entire structure */ -+ -+ /* transmit stat counters */ -+ uint32 txframe; /* tx data frames */ -+ uint32 txbyte; /* tx data bytes */ -+ uint32 txretrans; /* tx mac retransmits */ -+ uint32 txfail; /* tx failures */ -+ -+ /* receive stat counters */ -+ uint32 rxframe; /* rx data frames */ -+ uint32 rxbyte; /* rx data bytes */ -+ -+ /* per-rate receive stat counters */ -+ uint32 rx1mbps; /* packets rx at 1Mbps */ -+ uint32 rx2mbps; /* packets rx at 2Mbps */ -+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ -+ uint32 rx6mbps; /* packets rx at 6Mbps */ -+ uint32 rx9mbps; /* packets rx at 9Mbps */ -+ uint32 rx11mbps; /* packets rx at 11Mbps */ -+ uint32 rx12mbps; /* packets rx at 12Mbps */ -+ uint32 rx18mbps; /* packets rx at 18Mbps */ -+ uint32 rx24mbps; /* packets rx at 24Mbps */ -+ uint32 rx36mbps; /* packets rx at 36Mbps */ -+ uint32 rx48mbps; /* packets rx at 48Mbps */ -+ uint32 rx54mbps; /* packets rx at 54Mbps */ -+ uint32 rx108mbps; /* packets rx at 108mbps */ -+ uint32 rx162mbps; /* packets rx at 162mbps */ -+ uint32 rx216mbps; /* packets rx at 216 mbps */ -+ uint32 rx270mbps; /* packets rx at 270 mbps */ -+ uint32 rx324mbps; /* packets rx at 324 mbps */ -+ uint32 rx378mbps; /* packets rx at 378 mbps */ -+ uint32 rx432mbps; /* packets rx at 432 mbps */ -+ uint32 rx486mbps; /* packets rx at 486 mbps */ -+ uint32 rx540mbps; /* packets rx at 540 mbps */ -+} wl_delta_stats_t; -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ -+ -+typedef struct { -+ uint32 packets; -+ uint32 bytes; -+} wl_traffic_stats_t; -+ -+typedef struct { -+ uint16 version; /* see definition of WL_WME_CNT_VERSION */ -+ uint16 length; /* length of entire structure */ -+ -+ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ -+ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ -+ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ -+ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ -+ -+ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ -+ -+ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ -+ -+} wl_wme_cnt_t; -+ -+struct wl_msglevel2 { -+ uint32 low; -+ uint32 high; -+}; -+ -+typedef struct wl_mkeep_alive_pkt { -+ uint16 version; /* Version for mkeep_alive */ -+ uint16 length; /* length of fixed parameters in the structure */ -+ uint32 period_msec; -+ uint16 len_bytes; -+ uint8 keep_alive_id; /* 0 - 3 for N = 4 */ -+ uint8 data[1]; -+} wl_mkeep_alive_pkt_t; -+ -+#define WL_MKEEP_ALIVE_VERSION 1 -+#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) -+#define WL_MKEEP_ALIVE_PRECISION 500 -+ -+#ifndef LINUX_POSTMOGRIFY_REMOVAL -+#ifdef WLBA -+ -+#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ -+ -+/* block ack related stats */ -+typedef struct wlc_ba_cnt { -+ uint16 version; /* WLC_BA_CNT_VERSION */ -+ uint16 length; /* length of entire structure */ -+ -+ /* transmit stat counters */ -+ uint32 txpdu; /* pdus sent */ -+ uint32 txsdu; /* sdus sent */ -+ uint32 txfc; /* tx side flow controlled packets */ -+ uint32 txfci; /* tx side flow control initiated */ -+ uint32 txretrans; /* retransmitted pdus */ -+ uint32 txbatimer; /* ba resend due to timer */ -+ uint32 txdrop; /* dropped packets */ -+ uint32 txaddbareq; /* addba req sent */ -+ uint32 txaddbaresp; /* addba resp sent */ -+ uint32 txdelba; /* delba sent */ -+ uint32 txba; /* ba sent */ -+ uint32 txbar; /* bar sent */ -+ uint32 txpad[4]; /* future */ -+ -+ /* receive side counters */ -+ uint32 rxpdu; /* pdus recd */ -+ uint32 rxqed; /* pdus buffered before sending up */ -+ uint32 rxdup; /* duplicate pdus */ -+ uint32 rxnobuf; /* pdus discarded due to no buf */ -+ uint32 rxaddbareq; /* addba req recd */ -+ uint32 rxaddbaresp; /* addba resp recd */ -+ uint32 rxdelba; /* delba recd */ -+ uint32 rxba; /* ba recd */ -+ uint32 rxbar; /* bar recd */ -+ uint32 rxinvba; /* invalid ba recd */ -+ uint32 rxbaholes; /* ba recd with holes */ -+ uint32 rxunexp; /* unexpected packets */ -+ uint32 rxpad[4]; /* future */ -+} wlc_ba_cnt_t; -+#endif /* WLBA */ -+ -+/* structure for per-tid ampdu control */ -+struct ampdu_tid_control { -+ uint8 tid; /* tid */ -+ uint8 enable; /* enable/disable */ -+}; -+ -+/* structure for identifying ea/tid for sending addba/delba */ -+struct ampdu_ea_tid { -+ struct ether_addr ea; /* Station address */ -+ uint8 tid; /* tid */ -+}; -+/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */ -+struct ampdu_retry_tid { -+ uint8 tid; /* tid */ -+ uint8 retry; /* retry value */ -+}; -+ -+/* Different discovery modes for dpt */ -+#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */ -+#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */ -+#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */ -+ -+/* different path selection values */ -+#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */ -+#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */ -+#define DPT_PATHSEL_APPATH 2 /* always use AP path */ -+ -+/* different ops for deny list */ -+#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */ -+#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */ -+ -+/* different ops for manual end point */ -+#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ -+#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ -+#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ -+ -+/* structure for dpt iovars */ -+typedef struct dpt_iovar { -+ struct ether_addr ea; /* Station address */ -+ uint8 mode; /* mode: depends on iovar */ -+ uint32 pad; /* future */ -+} dpt_iovar_t; -+ -+/* flags to indicate DPT status */ -+#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */ -+#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */ -+#define DPT_STATUS_FAILED 0x04 /* DPT link failed */ -+ -+#define DPT_FNAME_LEN 48 /* Max length of friendly name */ -+ -+typedef struct dpt_status { -+ uint8 status; /* flags to indicate status */ -+ uint8 fnlen; /* length of friendly name */ -+ uchar name[DPT_FNAME_LEN]; /* friendly name */ -+ uint32 rssi; /* RSSI of the link */ -+ sta_info_t sta; /* sta info */ -+} dpt_status_t; -+ -+/* structure for dpt list */ -+typedef struct dpt_list { -+ uint32 num; /* number of entries in struct */ -+ dpt_status_t status[1]; /* per station info */ -+} dpt_list_t; -+ -+/* structure for dpt friendly name */ -+typedef struct dpt_fname { -+ uint8 len; /* length of friendly name */ -+ uchar name[DPT_FNAME_LEN]; /* friendly name */ -+} dpt_fname_t; -+ -+#define BDD_FNAME_LEN 32 /* Max length of friendly name */ -+typedef struct bdd_fname { -+ uint8 len; /* length of friendly name */ -+ uchar name[BDD_FNAME_LEN]; /* friendly name */ -+} bdd_fname_t; -+ -+/* structure for addts arguments */ -+/* For ioctls that take a list of TSPEC */ -+struct tslist { -+ int count; /* number of tspecs */ -+ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ -+}; -+ -+#ifdef WLTDLS -+/* different ops for manual end point */ -+#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ -+#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ -+#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ -+#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ -+#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ -+#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ -+#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ -+ -+/* structure for tdls iovars */ -+typedef struct tdls_iovar { -+ struct ether_addr ea; /* Station address */ -+ uint8 mode; /* mode: depends on iovar */ -+ chanspec_t chanspec; -+ uint32 pad; /* future */ -+} tdls_iovar_t; -+#endif /* WLTDLS */ -+ -+/* structure for addts/delts arguments */ -+typedef struct tspec_arg { -+ uint16 version; /* see definition of TSPEC_ARG_VERSION */ -+ uint16 length; /* length of entire structure */ -+ uint flag; /* bit field */ -+ /* TSPEC Arguments */ -+ struct tsinfo_arg tsinfo; /* TS Info bit field */ -+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ -+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ -+ uint min_srv_interval; /* Minimum Service Interval (us) */ -+ uint max_srv_interval; /* Maximum Service Interval (us) */ -+ uint inactivity_interval; /* Inactivity Interval (us) */ -+ uint suspension_interval; /* Suspension Interval (us) */ -+ uint srv_start_time; /* Service Start Time (us) */ -+ uint min_data_rate; /* Minimum Data Rate (bps) */ -+ uint mean_data_rate; /* Mean Data Rate (bps) */ -+ uint peak_data_rate; /* Peak Data Rate (bps) */ -+ uint max_burst_size; /* Maximum Burst Size (bytes) */ -+ uint delay_bound; /* Delay Bound (us) */ -+ uint min_phy_rate; /* Minimum PHY Rate (bps) */ -+ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ -+ uint16 medium_time; /* Medium Time (32 us/s periods) */ -+ uint8 dialog_token; /* dialog token */ -+} tspec_arg_t; -+ -+/* tspec arg for desired station */ -+typedef struct tspec_per_sta_arg { -+ struct ether_addr ea; -+ struct tspec_arg ts; -+} tspec_per_sta_arg_t; -+ -+/* structure for max bandwidth for each access category */ -+typedef struct wme_max_bandwidth { -+ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */ -+} wme_max_bandwidth_t; -+ -+#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) -+ -+/* current version of wl_tspec_arg_t struct */ -+#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ -+#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ -+#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ -+#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ -+ -+ -+#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 -+#define WLC_WOWL_MAX_KEEPALIVE 2 -+ -+/* define for flag */ -+#define TSPEC_PENDING 0 /* TSPEC pending */ -+#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ -+#define TSPEC_REJECTED 2 /* TSPEC rejected */ -+#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ -+#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ -+ -+ -+/* Software feature flag defines used by wlfeatureflag */ -+#ifdef WLAFTERBURNER -+#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ -+#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ -+#endif /* WLAFTERBURNER */ -+#define WL_SWFL_NOHWRADIO 0x0004 -+#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ -+#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ -+ -+#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ -+ -+/* Packet lifetime configuration per ac */ -+typedef struct wl_lifetime { -+ uint32 ac; /* access class */ -+ uint32 lifetime; /* Packet lifetime value in ms */ -+} wl_lifetime_t; -+ -+/* Channel Switch Announcement param */ -+typedef struct wl_chan_switch { -+ uint8 mode; /* value 0 or 1 */ -+ uint8 count; /* count # of beacons before switching */ -+ chanspec_t chspec; /* chanspec */ -+ uint8 reg; /* regulatory class */ -+} wl_chan_switch_t; -+#endif /* LINUX_POSTMOGRIFY_REMOVAL */ -+ -+/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER. -+ * -+ * (-100 < value < 0) value is used directly as a roaming trigger in dBm -+ * (0 <= value) value specifies a logical roaming trigger level from -+ * the list below -+ * -+ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never -+ * the logical roam trigger value. -+ */ -+#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */ -+#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */ -+#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */ -+#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */ -+#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */ -+ -+#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */ -+ -+/* Preferred Network Offload (PNO, formerly PFN) defines */ -+#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ -+ -+enum { -+ PFN_LIST_ORDER, -+ PFN_RSSI -+}; -+ -+enum { -+ DISABLE, -+ ENABLE -+}; -+ -+enum { -+ OFF_ADAPT, -+ SMART_ADAPT, -+ STRICT_ADAPT, -+ SLOW_ADAPT -+}; -+ -+#define SORT_CRITERIA_BIT 0 -+#define AUTO_NET_SWITCH_BIT 1 -+#define ENABLE_BKGRD_SCAN_BIT 2 -+#define IMMEDIATE_SCAN_BIT 3 -+#define AUTO_CONNECT_BIT 4 -+#define ENABLE_BD_SCAN_BIT 5 -+#define ENABLE_ADAPTSCAN_BIT 6 -+#define IMMEDIATE_EVENT_BIT 8 -+ -+#define SORT_CRITERIA_MASK 0x0001 -+#define AUTO_NET_SWITCH_MASK 0x0002 -+#define ENABLE_BKGRD_SCAN_MASK 0x0004 -+#define IMMEDIATE_SCAN_MASK 0x0008 -+#define AUTO_CONNECT_MASK 0x0010 -+ -+#define ENABLE_BD_SCAN_MASK 0x0020 -+#define ENABLE_ADAPTSCAN_MASK 0x00c0 -+#define IMMEDIATE_EVENT_MASK 0x0100 -+ -+#define PFN_VERSION 2 -+#define PFN_SCANRESULT_VERSION 1 -+#define MAX_PFN_LIST_COUNT 16 -+ -+#define PFN_COMPLETE 1 -+#define PFN_INCOMPLETE 0 -+ -+#define DEFAULT_BESTN 2 -+#define DEFAULT_MSCAN 0 -+#define DEFAULT_REPEAT 10 -+#define DEFAULT_EXP 2 -+ -+/* PFN network info structure */ -+typedef struct wl_pfn_subnet_info { -+ struct ether_addr BSSID; -+ uint8 channel; /* channel number only */ -+ uint8 SSID_len; -+ uint8 SSID[32]; -+} wl_pfn_subnet_info_t; -+ -+typedef struct wl_pfn_net_info { -+ wl_pfn_subnet_info_t pfnsubnet; -+ int16 RSSI; /* receive signal strength (in dBm) */ -+ uint16 timestamp; /* age in seconds */ -+} wl_pfn_net_info_t; -+ -+typedef struct wl_pfn_scanresults { -+ uint32 version; -+ uint32 status; -+ uint32 count; -+ wl_pfn_net_info_t netinfo[1]; -+} wl_pfn_scanresults_t; -+ -+/* PFN data structure */ -+typedef struct wl_pfn_param { -+ int32 version; /* PNO parameters version */ -+ int32 scan_freq; /* Scan frequency */ -+ int32 lost_network_timeout; /* Timeout in sec. to declare -+ * discovered network as lost -+ */ -+ int16 flags; /* Bit field to control features -+ * of PFN such as sort criteria auto -+ * enable switch and background scan -+ */ -+ int16 rssi_margin; /* Margin to avoid jitter for choosing a -+ * PFN based on RSSI sort criteria -+ */ -+ uint8 bestn; /* number of best networks in each scan */ -+ uint8 mscan; /* number of scans recorded */ -+ uint8 repeat; /* Minimum number of scan intervals -+ *before scan frequency changes in adaptive scan -+ */ -+ uint8 exp; /* Exponent of 2 for maximum scan interval */ -+#if !defined(WLC_PATCH) || !defined(BCM43362A2) -+ int32 slow_freq; /* slow scan period */ -+#endif /* !WLC_PATCH || !BCM43362A2 */ -+} wl_pfn_param_t; -+ -+typedef struct wl_pfn { -+ wlc_ssid_t ssid; /* ssid name and its length */ -+ int32 bss_type; /* IBSS or infrastructure */ -+ int32 infra; /* BSS Vs IBSS */ -+ int32 auth; /* Open Vs Closed */ -+ int32 wpa_auth; /* WPA type */ -+ int32 wsec; /* wsec value */ -+} wl_pfn_t; -+#define WL_PFN_HIDDEN_BIT 2 -+#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ -+#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ -+#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ -+#define WL_PFN_HIDDEN_MASK 0x4 -+ -+/* TCP Checksum Offload defines */ -+#define TOE_TX_CSUM_OL 0x00000001 -+#define TOE_RX_CSUM_OL 0x00000002 -+ -+/* TCP Checksum Offload error injection for testing */ -+#define TOE_ERRTEST_TX_CSUM 0x00000001 -+#define TOE_ERRTEST_RX_CSUM 0x00000002 -+#define TOE_ERRTEST_RX_CSUM2 0x00000004 -+ -+struct toe_ol_stats_t { -+ /* Num of tx packets that don't need to be checksummed */ -+ uint32 tx_summed; -+ -+ /* Num of tx packets where checksum is filled by offload engine */ -+ uint32 tx_iph_fill; -+ uint32 tx_tcp_fill; -+ uint32 tx_udp_fill; -+ uint32 tx_icmp_fill; -+ -+ /* Num of rx packets where toe finds out if checksum is good or bad */ -+ uint32 rx_iph_good; -+ uint32 rx_iph_bad; -+ uint32 rx_tcp_good; -+ uint32 rx_tcp_bad; -+ uint32 rx_udp_good; -+ uint32 rx_udp_bad; -+ uint32 rx_icmp_good; -+ uint32 rx_icmp_bad; -+ -+ /* Num of tx packets in which csum error is injected */ -+ uint32 tx_tcp_errinj; -+ uint32 tx_udp_errinj; -+ uint32 tx_icmp_errinj; -+ -+ /* Num of rx packets in which csum error is injected */ -+ uint32 rx_tcp_errinj; -+ uint32 rx_udp_errinj; -+ uint32 rx_icmp_errinj; -+}; -+ -+/* ARP Offload feature flags for arp_ol iovar */ -+#define ARP_OL_AGENT 0x00000001 -+#define ARP_OL_SNOOP 0x00000002 -+#define ARP_OL_HOST_AUTO_REPLY 0x00000004 -+#define ARP_OL_PEER_AUTO_REPLY 0x00000008 -+ -+/* ARP Offload error injection */ -+#define ARP_ERRTEST_REPLY_PEER 0x1 -+#define ARP_ERRTEST_REPLY_HOST 0x2 -+ -+#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ -+#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ -+ -+/* Arp offload statistic counts */ -+struct arp_ol_stats_t { -+ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ -+ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ -+ -+ uint32 arp_table_entries; /* ARP table entries */ -+ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */ -+ -+ uint32 host_request; /* ARP requests from host */ -+ uint32 host_reply; /* ARP replies from host */ -+ uint32 host_service; /* ARP requests from host serviced by ARP Agent */ -+ -+ uint32 peer_request; /* ARP requests received from network */ -+ uint32 peer_request_drop; /* ARP requests from network that were dropped */ -+ uint32 peer_reply; /* ARP replies received from network */ -+ uint32 peer_reply_drop; /* ARP replies from network that were dropped */ -+ uint32 peer_service; /* ARP request from host serviced by ARP Agent */ -+}; -+ -+/* NS offload statistic counts */ -+struct nd_ol_stats_t { -+ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ -+ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ -+ uint32 peer_request; /* NS requests received from network */ -+ uint32 peer_request_drop; /* NS requests from network that were dropped */ -+ uint32 peer_reply_drop; /* NA replies from network that were dropped */ -+ uint32 peer_service; /* NS request from host serviced by firmware */ -+}; -+ -+/* -+ * Keep-alive packet offloading. -+ */ -+ -+/* NAT keep-alive packets format: specifies the re-transmission period, the packet -+ * length, and packet contents. -+ */ -+typedef struct wl_keep_alive_pkt { -+ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */ -+ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */ -+ uint8 data[1]; /* Variable length packet to transmit. Contents should include -+ * entire ethernet packet (enet header, IP header, UDP header, -+ * and UDP payload) in network byte order. -+ */ -+} wl_keep_alive_pkt_t; -+ -+#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) -+ -+/* -+ * Dongle pattern matching filter. -+ */ -+ -+/* Packet filter types. Currently, only pattern matching is supported. */ -+typedef enum wl_pkt_filter_type { -+ WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ -+} wl_pkt_filter_type_t; -+ -+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t -+ -+/* Pattern matching filter. Specifies an offset within received packets to -+ * start matching, the pattern to match, the size of the pattern, and a bitmask -+ * that indicates which bits within the pattern should be matched. -+ */ -+typedef struct wl_pkt_filter_pattern { -+ uint32 offset; /* Offset within received packet to start pattern matching. -+ * Offset '0' is the first byte of the ethernet header. -+ */ -+ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ -+ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts -+ * at offset 0. Pattern immediately follows mask. -+ */ -+} wl_pkt_filter_pattern_t; -+ -+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ -+typedef struct wl_pkt_filter { -+ uint32 id; /* Unique filter id, specified by app. */ -+ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ -+ uint32 negate_match; /* Negate the result of filter matches */ -+ union { /* Filter definitions */ -+ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */ -+ } u; -+} wl_pkt_filter_t; -+ -+#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) -+#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) -+ -+/* IOVAR "pkt_filter_enable" parameter. */ -+typedef struct wl_pkt_filter_enable { -+ uint32 id; /* Unique filter id */ -+ uint32 enable; /* Enable/disable bool */ -+} wl_pkt_filter_enable_t; -+ -+/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ -+typedef struct wl_pkt_filter_list { -+ uint32 num; /* Number of installed packet filters */ -+ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ -+} wl_pkt_filter_list_t; -+ -+#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) -+ -+/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ -+typedef struct wl_pkt_filter_stats { -+ uint32 num_pkts_matched; /* # filter matches for specified filter id */ -+ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ -+ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ -+} wl_pkt_filter_stats_t; -+ -+/* Sequential Commands ioctl */ -+typedef struct wl_seq_cmd_ioctl { -+ uint32 cmd; /* common ioctl definition */ -+ uint32 len; /* length of user buffer */ -+} wl_seq_cmd_ioctl_t; -+ -+#define WL_SEQ_CMD_ALIGN_BYTES 4 -+ -+/* These are the set of get IOCTLs that should be allowed when using -+ * IOCTL sequence commands. These are issued implicitly by wl.exe each time -+ * it is invoked. We never want to buffer these, or else wl.exe will stop working. -+ */ -+#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ -+ (((cmd) == WLC_GET_MAGIC) || \ -+ ((cmd) == WLC_GET_VERSION) || \ -+ ((cmd) == WLC_GET_AP) || \ -+ ((cmd) == WLC_GET_INSTANCE)) -+ -+/* -+ * Packet engine interface -+ */ -+ -+#define WL_PKTENG_PER_TX_START 0x01 -+#define WL_PKTENG_PER_TX_STOP 0x02 -+#define WL_PKTENG_PER_RX_START 0x04 -+#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 -+#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 -+#define WL_PKTENG_PER_RX_STOP 0x08 -+#define WL_PKTENG_PER_MASK 0xff -+ -+#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ -+ -+typedef struct wl_pkteng { -+ uint32 flags; -+ uint32 delay; /* Inter-packet delay */ -+ uint32 nframes; /* Number of frames */ -+ uint32 length; /* Packet length */ -+ uint8 seqno; /* Enable/disable sequence no. */ -+ struct ether_addr dest; /* Destination address */ -+ struct ether_addr src; /* Source address */ -+} wl_pkteng_t; -+ -+#define NUM_80211b_RATES 4 -+#define NUM_80211ag_RATES 8 -+#define NUM_80211n_RATES 32 -+#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) -+typedef struct wl_pkteng_stats { -+ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */ -+ int32 rssi; /* RSSI */ -+ int32 snr; /* signal to noise ratio */ -+ uint16 rxpktcnt[NUM_80211_RATES+1]; -+} wl_pkteng_stats_t; -+ -+typedef struct wl_sslpnphy_papd_debug_data { -+ uint8 psat_pwr; -+ uint8 psat_indx; -+ uint8 final_idx; -+ uint8 start_idx; -+ int32 min_phase; -+ int32 voltage; -+ int8 temperature; -+} wl_sslpnphy_papd_debug_data_t; -+typedef struct wl_sslpnphy_debug_data { -+ int16 papdcompRe [64]; -+ int16 papdcompIm [64]; -+} wl_sslpnphy_debug_data_t; -+typedef struct wl_sslpnphy_spbdump_data { -+ uint16 tbl_length; -+ int16 spbreal[256]; -+ int16 spbimg[256]; -+} wl_sslpnphy_spbdump_data_t; -+typedef struct wl_sslpnphy_percal_debug_data { -+ uint cur_idx; -+ uint tx_drift; -+ uint8 prev_cal_idx; -+ uint percal_ctr; -+ int nxt_cal_idx; -+ uint force_1idxcal; -+ uint onedxacl_req; -+ int32 last_cal_volt; -+ int8 last_cal_temp; -+ uint vbat_ripple; -+ uint exit_route; -+ int32 volt_winner; -+} wl_sslpnphy_percal_debug_data_t; -+ -+#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */ -+#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */ -+#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */ -+#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */ -+#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */ -+#define WL_WOWL_TST (1 << 5) /* Wakeup after test */ -+#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */ -+#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */ -+#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */ -+#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */ -+#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */ -+#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */ -+#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */ -+#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */ -+#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */ -+#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */ -+ -+#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ -+ -+#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ -+#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ -+ -+typedef struct { -+ uint32 masksize; /* Size of the mask in #of bytes */ -+ uint32 offset; /* Offset to start looking for the packet in # of bytes */ -+ uint32 patternoffset; /* Offset of start of pattern in the structure */ -+ uint32 patternsize; /* Size of the pattern itself in #of bytes */ -+ uint32 id; /* id */ -+ uint32 reasonsize; /* Size of the wakeup reason code */ -+ uint32 flags; /* Flags to tell the pattern type and other properties */ -+ /* Mask follows the structure above */ -+ /* Pattern follows the mask is at 'patternoffset' from the start */ -+} wl_wowl_pattern_t; -+ -+typedef struct { -+ uint count; -+ wl_wowl_pattern_t pattern[1]; -+} wl_wowl_pattern_list_t; -+ -+typedef struct { -+ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */ -+ uint16 ucode_wakeind; /* What wakeup-event indication was set by ucode */ -+} wl_wowl_wakeind_t; -+ -+ -+/* per AC rate control related data structure */ -+typedef struct wl_txrate_class { -+ uint8 init_rate; -+ uint8 min_rate; -+ uint8 max_rate; -+} wl_txrate_class_t; -+ -+ -+/* Overlap BSS Scan parameters default, minimum, maximum */ -+#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */ -+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */ -+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */ -+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */ -+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */ -+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */ -+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 -+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 -+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 -+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */ -+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */ -+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ -+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */ -+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */ -+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */ -+ -+/* structure for Overlap BSS scan arguments */ -+typedef struct wl_obss_scan_arg { -+ int16 passive_dwell; -+ int16 active_dwell; -+ int16 bss_widthscan_interval; -+ int16 passive_total; -+ int16 active_total; -+ int16 chanwidth_transition_delay; -+ int16 activity_threshold; -+} wl_obss_scan_arg_t; -+ -+#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) -+#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */ -+ -+#define WL_COEX_INFO_MASK 0x07 -+#define WL_COEX_INFO_REQ 0x01 -+#define WL_COEX_40MHZ_INTOLERANT 0x02 -+#define WL_COEX_WIDTH20 0x04 -+ -+#define WLC_RSSI_INVALID 0 /* invalid RSSI value */ -+ -+#define MAX_RSSI_LEVELS 8 -+ -+/* RSSI event notification configuration. */ -+typedef struct wl_rssi_event { -+ uint32 rate_limit_msec; /* # of events posted to application will be limited to -+ * one per specified period (0 to disable rate limit). -+ */ -+ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */ -+ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event -+ * will be posted each time the RSSI of received -+ * beacons/packets crosses a level. -+ */ -+} wl_rssi_event_t; -+ -+typedef struct wl_action_obss_coex_req { -+ uint8 info; -+ uint8 num; -+ uint8 ch_list[1]; -+} wl_action_obss_coex_req_t; -+ -+ -+/* IOVar parameter block for small MAC address array with type indicator */ -+#define WL_IOV_MAC_PARAM_LEN 4 -+ -+#define WL_IOV_PKTQ_LOG_PRECS 16 -+ -+typedef struct { -+ uint32 num_addrs; -+ char addr_type[WL_IOV_MAC_PARAM_LEN]; -+ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN]; -+} wl_iov_mac_params_t; -+ -+ -+/* Parameter block for PKTQ_LOG statistics */ -+typedef struct { -+ uint32 requested; /* packets requested to be stored */ -+ uint32 stored; /* packets stored */ -+ uint32 saved; /* packets saved, -+ because a lowest priority queue has given away one packet -+ */ -+ uint32 selfsaved; /* packets saved, -+ because an older packet from the same queue has been dropped -+ */ -+ uint32 full_dropped; /* packets dropped, -+ because pktq is full with higher precedence packets -+ */ -+ uint32 dropped; /* packets dropped because pktq per that precedence is full */ -+ uint32 sacrificed; /* packets dropped, -+ in order to save one from a queue of a highest priority -+ */ -+ uint32 busy; /* packets droped because of hardware/transmission error */ -+ uint32 retry; /* packets re-sent because they were not received */ -+ uint32 ps_retry; /* packets retried again prior to moving power save mode */ -+ uint32 retry_drop; /* packets finally dropped after retry limit */ -+ uint32 max_avail; /* the high-water mark of the queue capacity for packets - -+ goes to zero as queue fills -+ */ -+ uint32 max_used; /* the high-water mark of the queue utilisation for packets - -+ increases with use ('inverse' of max_avail) -+ */ -+ uint32 queue_capacity; /* the maximum capacity of the queue */ -+} pktq_log_counters_v01_t; -+ -+#define sacrified sacrificed -+ -+typedef struct { -+ uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; -+ pktq_log_counters_v01_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; -+ char headings[1]; -+} pktq_log_format_v01_t; -+ -+ -+typedef struct { -+ uint32 version; -+ wl_iov_mac_params_t params; -+ union { -+ pktq_log_format_v01_t v01; -+ } pktq_log; -+} wl_iov_pktq_log_t; -+ -+ -+/* **** EXTLOG **** */ -+#define EXTLOG_CUR_VER 0x0100 -+ -+#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */ -+ -+/* log modules (bitmap) */ -+#define LOG_MODULE_COMMON 0x0001 -+#define LOG_MODULE_ASSOC 0x0002 -+#define LOG_MODULE_EVENT 0x0004 -+#define LOG_MODULE_MAX 3 /* Update when adding module */ -+ -+/* log levels */ -+#define WL_LOG_LEVEL_DISABLE 0 -+#define WL_LOG_LEVEL_ERR 1 -+#define WL_LOG_LEVEL_WARN 2 -+#define WL_LOG_LEVEL_INFO 3 -+#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */ -+ -+/* flag */ -+#define LOG_FLAG_EVENT 1 -+ -+/* log arg_type */ -+#define LOG_ARGTYPE_NULL 0 -+#define LOG_ARGTYPE_STR 1 /* %s */ -+#define LOG_ARGTYPE_INT 2 /* %d */ -+#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */ -+#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */ -+ -+typedef struct wlc_extlog_cfg { -+ int max_number; -+ uint16 module; /* bitmap */ -+ uint8 level; -+ uint8 flag; -+ uint16 version; -+} wlc_extlog_cfg_t; -+ -+typedef struct log_record { -+ uint32 time; -+ uint16 module; -+ uint16 id; -+ uint8 level; -+ uint8 sub_unit; -+ uint8 seq_num; -+ int32 arg; -+ char str[MAX_ARGSTR_LEN]; -+} log_record_t; -+ -+typedef struct wlc_extlog_req { -+ uint32 from_last; -+ uint32 num; -+} wlc_extlog_req_t; -+ -+typedef struct wlc_extlog_results { -+ uint16 version; -+ uint16 record_len; -+ uint32 num; -+ log_record_t logs[1]; -+} wlc_extlog_results_t; -+ -+typedef struct log_idstr { -+ uint16 id; -+ uint16 flag; -+ uint8 arg_type; -+ const char *fmt_str; -+} log_idstr_t; -+ -+#define FMTSTRF_USER 1 -+ -+/* flat ID definitions -+ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will -+ * affect backward compatibility with pre-existing apps -+ */ -+typedef enum { -+ FMTSTR_DRIVER_UP_ID = 0, -+ FMTSTR_DRIVER_DOWN_ID = 1, -+ FMTSTR_SUSPEND_MAC_FAIL_ID = 2, -+ FMTSTR_NO_PROGRESS_ID = 3, -+ FMTSTR_RFDISABLE_ID = 4, -+ FMTSTR_REG_PRINT_ID = 5, -+ FMTSTR_EXPTIME_ID = 6, -+ FMTSTR_JOIN_START_ID = 7, -+ FMTSTR_JOIN_COMPLETE_ID = 8, -+ FMTSTR_NO_NETWORKS_ID = 9, -+ FMTSTR_SECURITY_MISMATCH_ID = 10, -+ FMTSTR_RATE_MISMATCH_ID = 11, -+ FMTSTR_AP_PRUNED_ID = 12, -+ FMTSTR_KEY_INSERTED_ID = 13, -+ FMTSTR_DEAUTH_ID = 14, -+ FMTSTR_DISASSOC_ID = 15, -+ FMTSTR_LINK_UP_ID = 16, -+ FMTSTR_LINK_DOWN_ID = 17, -+ FMTSTR_RADIO_HW_OFF_ID = 18, -+ FMTSTR_RADIO_HW_ON_ID = 19, -+ FMTSTR_EVENT_DESC_ID = 20, -+ FMTSTR_PNP_SET_POWER_ID = 21, -+ FMTSTR_RADIO_SW_OFF_ID = 22, -+ FMTSTR_RADIO_SW_ON_ID = 23, -+ FMTSTR_PWD_MISMATCH_ID = 24, -+ FMTSTR_FATAL_ERROR_ID = 25, -+ FMTSTR_AUTH_FAIL_ID = 26, -+ FMTSTR_ASSOC_FAIL_ID = 27, -+ FMTSTR_IBSS_FAIL_ID = 28, -+ FMTSTR_EXTAP_FAIL_ID = 29, -+ FMTSTR_MAX_ID -+} log_fmtstr_id_t; -+ -+#ifdef DONGLEOVERLAYS -+typedef struct { -+ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */ -+ uint32 offset; /* offset into overlay region to write code */ -+ uint32 len; /* overlay code len */ -+ /* overlay code follows this struct */ -+} wl_ioctl_overlay_t; -+ -+#define OVERLAY_IDX_MASK 0x000000ff -+#define OVERLAY_IDX_SHIFT 0 -+#define OVERLAY_FLAGS_MASK 0xffffff00 -+#define OVERLAY_FLAGS_SHIFT 8 -+/* overlay written to device memory immediately after loading the base image */ -+#define OVERLAY_FLAG_POSTLOAD 0x100 -+/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */ -+#define OVERLAY_FLAG_DEFER_DL 0x200 -+/* overlay downloaded prior to the host going to sleep */ -+#define OVERLAY_FLAG_PRESLEEP 0x400 -+ -+#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024 -+#endif /* DONGLEOVERLAYS */ -+ -+/* no default structure packing */ -+#include -+ -+/* require strict packing */ -+#include -+/* Structures and constants used for "vndr_ie" IOVar interface */ -+#define VNDR_IE_CMD_LEN 4 /* length of the set command string: -+ * "add", "del" (+ NUL) -+ */ -+ -+/* 802.11 Mgmt Packet flags */ -+#define VNDR_IE_BEACON_FLAG 0x1 -+#define VNDR_IE_PRBRSP_FLAG 0x2 -+#define VNDR_IE_ASSOCRSP_FLAG 0x4 -+#define VNDR_IE_AUTHRSP_FLAG 0x8 -+#define VNDR_IE_PRBREQ_FLAG 0x10 -+#define VNDR_IE_ASSOCREQ_FLAG 0x20 -+#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ -+#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ -+ -+#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ -+ vndr_ie_t vndr_ie_data; /* vendor IE data */ -+} BWL_POST_PACKED_STRUCT vndr_ie_info_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ int iecount; /* number of entries in the vndr_ie_list[] array */ -+ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ -+} BWL_POST_PACKED_STRUCT vndr_ie_buf_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */ -+ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ -+} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; -+ -+/* tag_ID/length/value_buffer tuple */ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ uint8 id; -+ uint8 len; -+ uint8 data[1]; -+} BWL_POST_PACKED_STRUCT tlv_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ -+ tlv_t ie_data; /* IE data */ -+} BWL_POST_PACKED_STRUCT ie_info_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ int iecount; /* number of entries in the ie_list[] array */ -+ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ -+} BWL_POST_PACKED_STRUCT ie_buf_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ -+ ie_buf_t ie_buffer; /* buffer containing IE list information */ -+} BWL_POST_PACKED_STRUCT ie_setbuf_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct { -+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ -+ uint8 id; /* IE type */ -+} BWL_POST_PACKED_STRUCT ie_getbuf_t; -+ -+/* structures used to define format of wps ie data from probe requests */ -+/* passed up to applications via iovar "prbreq_wpsie" */ -+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { -+ struct ether_addr staAddr; -+ uint16 ieLen; -+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { -+ sta_prbreq_wps_ie_hdr_t hdr; -+ uint8 ieData[1]; -+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; -+ -+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { -+ uint32 totLen; -+ uint8 ieDataList[1]; -+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; -+ -+ -+#ifdef WLMEDIA_TXFAILEVENT -+typedef BWL_PRE_PACKED_STRUCT struct { -+ char dest[ETHER_ADDR_LEN]; /* destination MAC */ -+ uint8 prio; /* Packet Priority */ -+ uint8 flags; /* Flags */ -+ uint32 tsf_l; /* TSF timer low */ -+ uint32 tsf_h; /* TSF timer high */ -+ uint16 rates; /* Main Rates */ -+ uint16 txstatus; /* TX Status */ -+} BWL_POST_PACKED_STRUCT txfailinfo_t; -+#endif /* WLMEDIA_TXFAILEVENT */ -+ -+/* no strict structure packing */ -+#include -+ -+/* Global ASSERT Logging */ -+#define ASSERTLOG_CUR_VER 0x0100 -+#define MAX_ASSRTSTR_LEN 64 -+ -+typedef struct assert_record { -+ uint32 time; -+ uint8 seq_num; -+ char str[MAX_ASSRTSTR_LEN]; -+} assert_record_t; -+ -+typedef struct assertlog_results { -+ uint16 version; -+ uint16 record_len; -+ uint32 num; -+ assert_record_t logs[1]; -+} assertlog_results_t; -+ -+#define LOGRRC_FIX_LEN 8 -+#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) -+ -+ -+/* channel interference measurement (chanim) related defines */ -+ -+/* chanim mode */ -+#define CHANIM_DISABLE 0 /* disabled */ -+#define CHANIM_DETECT 1 /* detection only */ -+#define CHANIM_EXT 2 /* external state machine */ -+#define CHANIM_ACT 3 /* full internal state machine, detect + act */ -+#define CHANIM_MODE_MAX 4 -+ -+/* define for apcs reason code */ -+#define APCS_INIT 0 -+#define APCS_IOCTL 1 -+#define APCS_CHANIM 2 -+#define APCS_CSTIMER 3 -+#define APCS_BTA 4 -+ -+/* number of ACS record entries */ -+#define CHANIM_ACS_RECORD 10 -+ -+/* CHANIM */ -+#define CCASTATS_TXDUR 0 -+#define CCASTATS_INBSS 1 -+#define CCASTATS_OBSS 2 -+#define CCASTATS_NOCTG 3 -+#define CCASTATS_NOPKT 4 -+#define CCASTATS_DOZE 5 -+#define CCASTATS_TXOP 6 -+#define CCASTATS_GDTXDUR 7 -+#define CCASTATS_BDTXDUR 8 -+#define CCASTATS_MAX 9 -+ -+/* chanim acs record */ -+typedef struct { -+ bool valid; -+ uint8 trigger; -+ chanspec_t selected_chspc; -+ int8 bgnoise; -+ uint32 glitch_cnt; -+ uint8 ccastats; -+ uint timestamp; -+} chanim_acs_record_t; -+ -+typedef struct { -+ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD]; -+ uint8 count; -+ uint timestamp; -+} wl_acs_record_t; -+ -+typedef struct chanim_stats { -+ uint32 glitchcnt; /* normalized as per second count */ -+ uint32 badplcp; /* normalized as per second count */ -+ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */ -+ int8 bgnoise; /* background noise level (in dBm) */ -+ chanspec_t chanspec; -+ uint32 timestamp; -+} chanim_stats_t; -+ -+#define WL_CHANIM_STATS_VERSION 1 -+#define WL_CHANIM_COUNT_ALL 0xff -+#define WL_CHANIM_COUNT_ONE 0x1 -+ -+typedef struct { -+ uint32 buflen; -+ uint32 version; -+ uint32 count; -+ chanim_stats_t stats[1]; -+} wl_chanim_stats_t; -+ -+#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats) -+ -+/* Noise measurement metrics. */ -+#define NOISE_MEASURE_KNOISE 0x1 -+ -+/* scb probe parameter */ -+typedef struct { -+ uint32 scb_timeout; -+ uint32 scb_activity_time; -+ uint32 scb_max_probe; -+} wl_scb_probe_t; -+ -+/* ap tpc modes */ -+#define AP_TPC_OFF 0 -+#define AP_TPC_BSS_PWR 1 /* BSS power control */ -+#define AP_TPC_AP_PWR 2 /* AP power control */ -+#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ -+#define AP_TPC_MAX_LINK_MARGIN 127 -+ -+/* structure/defines for selective mgmt frame (smf) stats support */ -+ -+#define SMFS_VERSION 1 -+/* selected mgmt frame (smf) stats element */ -+typedef struct wl_smfs_elem { -+ uint32 count; -+ uint16 code; /* SC or RC code */ -+} wl_smfs_elem_t; -+ -+typedef struct wl_smf_stats { -+ uint32 version; -+ uint16 length; /* reserved for future usage */ -+ uint8 type; -+ uint8 codetype; -+ uint32 ignored_cnt; -+ uint32 malformed_cnt; -+ uint32 count_total; /* count included the interested group */ -+ wl_smfs_elem_t elem[1]; -+} wl_smf_stats_t; -+ -+#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem); -+ -+enum { -+ SMFS_CODETYPE_SC, -+ SMFS_CODETYPE_RC -+}; -+ -+/* reuse two number in the sc/rc space */ -+#define SMFS_CODE_MALFORMED 0xFFFE -+#define SMFS_CODE_IGNORED 0xFFFD -+ -+typedef enum smfs_type { -+ SMFS_TYPE_AUTH, -+ SMFS_TYPE_ASSOC, -+ SMFS_TYPE_REASSOC, -+ SMFS_TYPE_DISASSOC_TX, -+ SMFS_TYPE_DISASSOC_RX, -+ SMFS_TYPE_DEAUTH_TX, -+ SMFS_TYPE_DEAUTH_RX, -+ SMFS_TYPE_MAX -+} smfs_type_t; -+ -+#ifdef PHYMON -+ -+#define PHYMON_VERSION 1 -+ -+typedef struct wl_phycal_core_state { -+ /* Tx IQ/LO calibration coeffs */ -+ int16 tx_iqlocal_a; -+ int16 tx_iqlocal_b; -+ int8 tx_iqlocal_ci; -+ int8 tx_iqlocal_cq; -+ int8 tx_iqlocal_di; -+ int8 tx_iqlocal_dq; -+ int8 tx_iqlocal_ei; -+ int8 tx_iqlocal_eq; -+ int8 tx_iqlocal_fi; -+ int8 tx_iqlocal_fq; -+ -+ /* Rx IQ calibration coeffs */ -+ int16 rx_iqcal_a; -+ int16 rx_iqcal_b; -+ -+ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */ -+ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */ -+ int16 papd_epsilon_offset; /* PAPD epsilon offset */ -+ uint8 curr_tx_pwrindex; /* Tx power index */ -+ int8 idle_tssi; /* Idle TSSI */ -+ int8 est_tx_pwr; /* Estimated Tx Power (dB) */ -+ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */ -+ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */ -+ uint16 init_gaincode; /* initgain required for ACI */ -+ int8 estirr_tx; -+ int8 estirr_rx; -+ -+} wl_phycal_core_state_t; -+ -+typedef struct wl_phycal_state { -+ int version; -+ int8 num_phy_cores; /* number of cores */ -+ int8 curr_temperature; /* on-chip temperature sensor reading */ -+ chanspec_t chspec; /* channspec for this state */ -+ bool aci_state; /* ACI state: ON/OFF */ -+ uint16 crsminpower; /* crsminpower required for ACI */ -+ uint16 crsminpowerl; /* crsminpowerl required for ACI */ -+ uint16 crsminpoweru; /* crsminpoweru required for ACI */ -+ wl_phycal_core_state_t phycal_core[1]; -+} wl_phycal_state_t; -+ -+#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) -+#endif /* PHYMON */ -+ -+/* discovery state */ -+typedef struct wl_p2p_disc_st { -+ uint8 state; /* see state */ -+ chanspec_t chspec; /* valid in listen state */ -+ uint16 dwell; /* valid in listen state, in ms */ -+} wl_p2p_disc_st_t; -+ -+/* state */ -+#define WL_P2P_DISC_ST_SCAN 0 -+#define WL_P2P_DISC_ST_LISTEN 1 -+#define WL_P2P_DISC_ST_SEARCH 2 -+ -+/* scan request */ -+typedef struct wl_p2p_scan { -+ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */ -+ uint8 reserved[3]; -+ /* scan or escan parms... */ -+} wl_p2p_scan_t; -+ -+/* i/f request */ -+typedef struct wl_p2p_if { -+ struct ether_addr addr; -+ uint8 type; /* see i/f type */ -+ chanspec_t chspec; /* for p2p_ifadd GO */ -+} wl_p2p_if_t; -+ -+/* i/f type */ -+#define WL_P2P_IF_CLIENT 0 -+#define WL_P2P_IF_GO 1 -+#define WL_P2P_IF_DYNBCN_GO 2 -+#define WL_P2P_IF_DEV 3 -+ -+/* i/f query */ -+typedef struct wl_p2p_ifq { -+ uint bsscfgidx; -+ char ifname[BCM_MSG_IFNAME_MAX]; -+} wl_p2p_ifq_t; -+ -+/* OppPS & CTWindow */ -+typedef struct wl_p2p_ops { -+ uint8 ops; /* 0: disable 1: enable */ -+ uint8 ctw; /* >= 10 */ -+} wl_p2p_ops_t; -+ -+/* absence and presence request */ -+typedef struct wl_p2p_sched_desc { -+ uint32 start; -+ uint32 interval; -+ uint32 duration; -+ uint32 count; /* see count */ -+} wl_p2p_sched_desc_t; -+ -+/* count */ -+#define WL_P2P_SCHED_RSVD 0 -+#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ -+ -+typedef struct wl_p2p_sched { -+ uint8 type; /* see schedule type */ -+ uint8 action; /* see schedule action */ -+ uint8 option; /* see schedule option */ -+ wl_p2p_sched_desc_t desc[1]; -+} wl_p2p_sched_t; -+#define WL_P2P_SCHED_FIXED_LEN 3 -+ -+/* schedule type */ -+#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ -+#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ -+ -+/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ -+#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ -+#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ -+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ -+#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */ -+/* schedule option - WL_P2P_SCHED_TYPE_XXX */ -+#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ -+ -+/* schedule option - WL_P2P_SCHED_TYPE_ABS */ -+#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */ -+#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ -+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ -+#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with -+ * start being an offset of the 'current' TSF -+ */ -+ -+/* feature flags */ -+#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */ -+#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe -+ * requests -+ */ -+#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */ -+ -+/* RFAWARE def */ -+#define BCM_ACTION_RFAWARE 0x77 -+#define BCM_ACTION_RFAWARE_DCS 0x01 -+ -+/* DCS reason code define */ -+#define BCM_DCS_IOVAR 0x1 -+#define BCM_DCS_UNKNOWN 0xFF -+ -+typedef struct wl_bcmdcs_data { -+ uint reason; -+ chanspec_t chspec; -+} wl_bcmdcs_data_t; -+ -+/* n-mode support capability */ -+/* 2x2 includes both 1x1 & 2x2 devices -+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and -+ * control it independently -+ */ -+#define WL_11N_2x2 1 -+#define WL_11N_3x3 3 -+#define WL_11N_4x4 4 -+ -+/* define 11n feature disable flags */ -+#define WLFEATURE_DISABLE_11N 0x00000001 -+#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 -+#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 -+#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 -+#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 -+#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 -+#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 -+#define WLFEATURE_DISABLE_11N_GF 0x00000080 -+ -+/* Proxy STA modes */ -+#define PSTA_MODE_DISABLED 0 -+#define PSTA_MODE_PROXY 1 -+#define PSTA_MODE_REPEATER 2 -+ -+ -+/* NAT configuration */ -+typedef struct { -+ uint32 ipaddr; /* interface ip address */ -+ uint32 ipaddr_mask; /* interface ip address mask */ -+ uint32 ipaddr_gateway; /* gateway ip address */ -+ uint8 mac_gateway[6]; /* gateway mac address */ -+ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */ -+ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */ -+ uint8 GUID[38]; /* interface GUID */ -+} nat_if_info_t; -+ -+typedef struct { -+ uint op; /* operation code */ -+ bool pub_if; /* set for public if, clear for private if */ -+ nat_if_info_t if_info; /* interface info */ -+} nat_cfg_t; -+ -+/* op code in nat_cfg */ -+#define NAT_OP_ENABLE 1 /* enable NAT on given interface */ -+#define NAT_OP_DISABLE 2 /* disable NAT on given interface */ -+#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */ -+ -+/* NAT state */ -+#define NAT_STATE_ENABLED 1 /* NAT is enabled */ -+#define NAT_STATE_DISABLED 2 /* NAT is disabled */ -+ -+typedef struct { -+ int state; /* NAT state returned */ -+} nat_state_t; -+ -+#ifdef PROP_TXSTATUS -+/* Bit definitions for tlv iovar */ -+/* -+ * enable RSSI signals: -+ * WLFC_CTL_TYPE_RSSI -+ */ -+#define WLFC_FLAGS_RSSI_SIGNALS 1 -+ -+/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals: -+ * -+ * WLFC_CTL_TYPE_MAC_OPEN -+ * WLFC_CTL_TYPE_MAC_CLOSE -+ * -+ * WLFC_CTL_TYPE_INTERFACE_OPEN -+ * WLFC_CTL_TYPE_INTERFACE_CLOSE -+ * -+ * WLFC_CTL_TYPE_MACDESC_ADD -+ * WLFC_CTL_TYPE_MACDESC_DEL -+ * -+ */ -+#define WLFC_FLAGS_XONXOFF_SIGNALS 2 -+ -+/* enable (status, fifo_credit, mac_credit) signals -+ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT -+ * WLFC_CTL_TYPE_TXSTATUS -+ * WLFC_CTL_TYPE_FIFO_CREDITBACK -+ */ -+#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 4 -+ -+#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 8 -+#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 16 -+#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 32 -+#endif /* PROP_TXSTATUS */ -+ -+#define BTA_STATE_LOG_SZ 64 -+ -+/* BTAMP Statemachine states */ -+enum { -+ HCIReset = 1, -+ HCIReadLocalAMPInfo, -+ HCIReadLocalAMPASSOC, -+ HCIWriteRemoteAMPASSOC, -+ HCICreatePhysicalLink, -+ HCIAcceptPhysicalLinkRequest, -+ HCIDisconnectPhysicalLink, -+ HCICreateLogicalLink, -+ HCIAcceptLogicalLink, -+ HCIDisconnectLogicalLink, -+ HCILogicalLinkCancel, -+ HCIAmpStateChange, -+ HCIWriteLogicalLinkAcceptTimeout -+}; -+ -+typedef struct flush_txfifo { -+ uint32 txfifobmp; -+ uint32 hwtxfifoflush; -+ struct ether_addr ea; -+} flush_txfifo_t; -+ -+#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */ -+#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */ -+#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */ -+#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */ -+ -+enum { -+ SPATIAL_MODE_2G_IDX = 0, -+ SPATIAL_MODE_5G_LOW_IDX, -+ SPATIAL_MODE_5G_MID_IDX, -+ SPATIAL_MODE_5G_HIGH_IDX, -+ SPATIAL_MODE_5G_UPPER_IDX, -+ SPATIAL_MODE_MAX_IDX -+}; -+ -+/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ -+typedef struct wl_mempool_stats { -+ int num; /* Number of memory pools */ -+ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */ -+} wl_mempool_stats_t; -+ -+/* Network Offload Engine */ -+#define NWOE_OL_ENABLE 0x00000001 -+ -+typedef struct { -+ uint32 ipaddr; -+ uint32 ipaddr_netmask; -+ uint32 ipaddr_gateway; -+} nwoe_ifconfig_t; -+ -+/* -+ * Traffic management structures/defines. -+ */ -+ -+/* Traffic management bandwidth parameters */ -+#define TRF_MGMT_MAX_PRIORITIES 3 -+ -+#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ -+#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ -+ -+ -+/* Traffic management priority classes */ -+typedef enum trf_mgmt_priority_class { -+ trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ -+ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ -+ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ -+ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) -+} trf_mgmt_priority_class_t; -+ -+/* Traffic management configuration parameters */ -+typedef struct trf_mgmt_config { -+ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */ -+ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */ -+ uint32 host_ip_addr; -+ uint32 host_subnet_mask; -+ uint32 downlink_bandwidth; /* In units of kbps */ -+ uint32 uplink_bandwidth; /* In units of kbps */ -+ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; -+ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; -+} trf_mgmt_config_t; -+ -+/* Traffic management filter */ -+typedef struct trf_mgmt_filter { -+ uint32 dst_ip_addr; /* His IP address */ -+ uint16 dst_port; /* His L4 port */ -+ uint16 src_port; /* My L4 port */ -+ uint16 prot; /* L4 protocol (only TCP or UDP protocols) */ -+ uint16 flags; /* TBD. For now, this must be zero. */ -+ trf_mgmt_priority_class_t priority; /* 802.1p priority for filtered packets */ -+} trf_mgmt_filter_t; -+ -+/* Traffic management filter list (variable length) */ -+typedef struct trf_mgmt_filter_list { -+ uint32 num_filters; -+ trf_mgmt_filter_t filter[1]; -+} trf_mgmt_filter_list_t; -+ -+/* Traffic management shaping info */ -+typedef struct trf_mgmt_shaping_info { -+ uint32 max_bps; /* Max bytes consumed or produced per second */ -+ uint32 max_bytes_per_sampling_period; /* Max bytes consumed or produced per sample */ -+ uint32 shaping_delay_threshold; /* Theshold for starting traffic delays */ -+ uint32 num_bytes_produced_per_sec; /* Bytes produced over the sampling period */ -+ uint32 num_bytes_consumed_per_sec; /* Bytes consumed over the sampling period */ -+} trf_mgmt_shaping_info_t; -+ -+/* Traffic management shaping info array */ -+typedef struct trf_mgmt_shaping_info_array { -+ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; -+ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; -+} trf_mgmt_shaping_info_array_t; -+ -+ -+/* Traffic management statistical counters */ -+typedef struct trf_mgmt_stats { -+ uint32 num_processed_packets; /* Number of packets processed */ -+ uint32 num_processed_bytes; /* Number of bytes processed */ -+ uint32 num_queued_packets; /* Number of packets in queue */ -+ uint32 num_queued_bytes; /* Number of bytes in queue */ -+ uint32 num_discarded_packets; /* Number of packets discarded from queue */ -+} trf_mgmt_stats_t; -+ -+/* Traffic management statisics array */ -+typedef struct trf_mgmt_stats_array { -+ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; -+ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; -+} trf_mgmt_stats_array_t; -+ -+#endif /* _wlioctl_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/aiutils.c b/drivers/net/ethernet/broadcom/gmac/src/shared/aiutils.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/aiutils.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/aiutils.c 2017-11-09 17:53:44.023292000 +0800 -@@ -0,0 +1,1028 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Misc utility routines for accessing chip-specific features -+ * of the SiliconBackplane-based Broadcom chips. -+ * -+ * $Id: aiutils.c 327582 2012-04-14 05:02:37Z kenlo $ -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "siutils_priv.h" -+#if defined(CONFIG_MACH_HX4) -+#include "hx4_erom.h" -+#elif defined(CONFIG_MACH_HR2) -+#include "hr2_erom.h" -+#elif defined(CONFIG_MACH_KT2) -+#include "kt2_erom.h" -+#elif defined(CONFIG_MACH_GH) -+#include "gh_erom.h" -+#elif defined(CONFIG_MACH_SB2) -+#include "sb2_erom.h" -+#elif defined(CONFIG_MACH_HR3) -+#include "hr3_erom.h" -+#elif defined(CONFIG_MACH_GH2) -+#include "gh2_erom.h" -+#endif -+ -+/* EROM parsing */ -+static uint32 -+get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match) -+{ -+ uint32 ent; -+ uint inv = 0, nom = 0; -+ -+ while (TRUE) { -+ ent = **eromptr; -+ -+ (*eromptr)++; -+ -+ if (mask == 0) { -+ break; -+ } -+ -+ if ((ent & ER_VALID) == 0) { -+ inv++; -+ continue; -+ } -+ -+ if (ent == (ER_END | ER_VALID)) { -+ break; -+ } -+ -+ if ((ent & mask) == match) { -+ break; -+ } -+ -+ nom++; -+ } -+ -+ SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent)); -+ if (inv + nom) { -+ SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom)); -+ } -+ return ent; -+} -+ -+static uint32 -+get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, -+ uint32 *sizel, uint32 *sizeh) -+{ -+ uint32 asd, sz, szd; -+ -+ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); -+ if (((asd & ER_TAG1) != ER_ADD) || -+ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || -+ ((asd & AD_ST_MASK) != st)) { -+ /* This is not what we want, "push" it back */ -+ (*eromptr)--; -+ return 0; -+ } -+ *addrl = asd & AD_ADDR_MASK; -+ if (asd & AD_AG32) { -+ *addrh = get_erom_ent(sih, eromptr, 0, 0); -+ } else { -+ *addrh = 0; -+ } -+ *sizeh = 0; -+ sz = asd & AD_SZ_MASK; -+ if (sz == AD_SZ_SZD) { -+ szd = get_erom_ent(sih, eromptr, 0, 0); -+ *sizel = szd & SD_SZ_MASK; -+ if (szd & SD_SG32) { -+ *sizeh = get_erom_ent(sih, eromptr, 0, 0); -+ } -+ } else { -+ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); -+ } -+ -+ SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", -+ sp, ad, st, *sizeh, *sizel, *addrh, *addrl)); -+ -+ return asd; -+} -+ -+/* parse the enumeration rom to identify all cores */ -+void -+BCMATTACHFN(ai_scan)(si_t *sih, void *regs, uint devid) -+{ -+ si_info_t *sii = SI_INFO(sih); -+ chipcregs_t *cc = (chipcregs_t *)regs; -+ uint32 erombase, *eromptr, *eromlim; -+ -+ erombase = R_REG(sii->osh, &cc->eromptr); -+ -+ switch (BUSTYPE(sih->bustype)) { -+ case SI_BUS: -+#if defined(CONFIG_MACH_HX4) -+ eromptr = hx4_erom; -+#elif defined(CONFIG_MACH_HR2) -+ eromptr = hr2_erom; -+#elif defined(CONFIG_MACH_KT2) -+ eromptr = kt2_erom; -+#elif defined(CONFIG_MACH_GH) -+ eromptr = gh_erom; -+#elif defined(CONFIG_MACH_SB2) -+ eromptr = sb2_erom; -+#elif defined(CONFIG_MACH_HR3) -+ eromptr = hr3_erom; -+#elif defined(CONFIG_MACH_GH2) -+ eromptr = gh2_erom; -+#endif -+ break; -+ -+ case PCI_BUS: -+ /* Set wrappers address */ -+ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); -+ -+ /* Now point the window at the erom */ -+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); -+ eromptr = regs; -+ break; -+ -+ case PCMCIA_BUS: -+ default: -+ SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype)); -+ ASSERT(0); -+ return; -+ } -+ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); -+ -+ SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", -+ regs, erombase, eromptr, eromlim)); -+ while (eromptr < eromlim) { -+ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; -+ uint32 mpd, asd, addrl, addrh, sizel, sizeh; -+ uint i, j, idx; -+ bool br; -+ -+ br = FALSE; -+ -+ /* Grok a component */ -+ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); -+ if (cia == (ER_END | ER_VALID)) { -+ SI_VMSG(("Found END of erom after %d cores\n", sii->numcores)); -+ return; -+ } -+ -+ cib = get_erom_ent(sih, &eromptr, 0, 0); -+ -+ if ((cib & ER_TAG) != ER_CI) { -+ SI_ERROR(("CIA not followed by CIB\n")); -+ goto error; -+ } -+ -+ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; -+ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; -+ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; -+ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; -+ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; -+ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; -+ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; -+ -+#ifdef BCMDBG_SI -+ SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " -+ "nsw = %d, nmp = %d & nsp = %d\n", -+ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp)); -+#else -+ BCM_REFERENCE(crev); -+#endif -+ -+ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) { -+ continue; -+ } -+ -+ if ((nmw + nsw == 0)) { -+ /* A component which is not a core */ -+ /* XXX: Should record some info */ -+ if (cid == OOB_ROUTER_CORE_ID) { -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, -+ &addrl, &addrh, &sizel, &sizeh); -+ if (asd != 0) { -+ sii->oob_router = addrl; -+ } -+ } -+ if (cid != GMAC_COMMON_4706_CORE_ID) { -+ continue; -+ } -+ } -+ -+ idx = sii->numcores; -+ -+ sii->cia[idx] = cia; -+ sii->cib[idx] = cib; -+ sii->coreid[idx] = cid; -+ -+ for (i = 0; i < nmp; i++) { -+ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); -+ if ((mpd & ER_TAG) != ER_MP) { -+ SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); -+ goto error; -+ } -+ /* XXX: Record something? */ -+ SI_VMSG((" Master port %d, mp: %d id: %d\n", i, -+ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, -+ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT)); -+ } -+ -+ /* First Slave Address Descriptor should be port 0: -+ * the main register space for the core -+ */ -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); -+ if (asd == 0) { -+ do { -+ /* Try again to see if it is a bridge */ -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, -+ &sizel, &sizeh); -+ if (asd != 0) { -+ br = TRUE; -+ } else { -+ if (br == TRUE) { -+ break; -+ } else if ((addrh != 0) || (sizeh != 0) || -+ (sizel != SI_CORE_SIZE)) { -+ /* XXX: Could we have sizel != 4KB? */ -+ SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 =" -+ "0x%x\n", addrh, sizeh, sizel)); -+ SI_ERROR(("First Slave ASD for" -+ "core 0x%04x malformed " -+ "(0x%08x)\n", cid, asd)); -+ goto error; -+ } -+ } -+ } while (1); -+ } -+ sii->coresba[idx] = addrl; -+ sii->coresba_size[idx] = sizel; -+ /* Get any more ASDs in port 0 */ -+ j = 1; -+ do { -+ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, -+ &sizel, &sizeh); -+ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { -+ sii->coresba2[idx] = addrl; -+ sii->coresba2_size[idx] = sizel; -+ } -+ j++; -+ } while (asd != 0); -+ -+ /* Go through the ASDs for other slave ports */ -+ for (i = 1; i < nsp; i++) { -+ j = 0; -+ do { -+ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, -+ &sizel, &sizeh); -+ /* XXX: Should record them so we can do error recovery later */ -+ -+ if (asd == 0) -+ break; -+ j++; -+ } while (1); -+ if (j == 0) { -+ SI_ERROR((" SP %d has no address descriptors\n", i)); -+ goto error; -+ } -+ } -+ -+ /* Now get master wrappers */ -+ for (i = 0; i < nmw; i++) { -+ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, -+ &sizel, &sizeh); -+ if (asd == 0) { -+ SI_ERROR(("Missing descriptor for MW %d\n", i)); -+ goto error; -+ } -+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { -+ SI_ERROR(("Master wrapper %d is not 4KB\n", i)); -+ goto error; -+ } -+ if (i == 0) { -+ sii->wrapba[idx] = addrl; -+ } -+ } -+ -+ /* And finally slave wrappers */ -+ for (i = 0; i < nsw; i++) { -+ uint fwp = (nsp == 1) ? 0 : 1; -+ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, -+ &sizel, &sizeh); -+ if (asd == 0) { -+ SI_ERROR(("Missing descriptor for SW %d\n", i)); -+ goto error; -+ } -+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { -+ SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); -+ goto error; -+ } -+ if ((nmw == 0) && (i == 0)) { -+ sii->wrapba[idx] = addrl; -+ } -+ } -+ -+ /* Don't record bridges */ -+ if (br) { -+ continue; -+ } -+ -+ /* Done with core */ -+ sii->numcores++; -+ } -+ -+ SI_ERROR(("Reached end of erom without finding END")); -+ -+error: -+ sii->numcores = 0; -+ return; -+} -+ -+/* This function changes the logical "focus" to the indicated core. -+ * Return the current core's virtual address. -+ */ -+void * -+ai_setcoreidx(si_t *sih, uint coreidx) -+{ -+ si_info_t *sii = SI_INFO(sih); -+ uint32 addr, wrap; -+ void *regs; -+ -+ if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) { -+ return (NULL); -+ } -+ -+ addr = sii->coresba[coreidx]; -+ wrap = sii->wrapba[coreidx]; -+ -+ /* -+ * If the user has provided an interrupt mask enabled function, -+ * then assert interrupts are disabled before switching the core. -+ */ -+ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); -+ -+ switch (BUSTYPE(sih->bustype)) { -+ case SI_BUS: -+ /* map new one */ -+ if (!sii->regs[coreidx]) { -+ sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); -+ ASSERT(GOODREGS(sii->regs[coreidx])); -+ } -+ sii->curmap = regs = sii->regs[coreidx]; -+ if (!sii->wrappers[coreidx]) { -+ sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); -+ ASSERT(GOODREGS(sii->wrappers[coreidx])); -+ } -+ sii->curwrap = sii->wrappers[coreidx]; -+ break; -+ -+ case PCI_BUS: -+ /* point bar0 window */ -+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr); -+ regs = sii->curmap; -+ /* point bar0 2nd 4KB window to the primary wrapper */ -+ if (PCIE_GEN2(sii)) { -+ OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap); -+ } else { -+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap); -+ } -+ break; -+ -+ case PCMCIA_BUS: -+ default: -+ ASSERT(0); -+ regs = NULL; -+ break; -+ } -+ -+ sii->curmap = regs; -+ sii->curidx = coreidx; -+ -+ return regs; -+} -+ -+void -+ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) -+{ -+ si_info_t *sii = SI_INFO(sih); -+ chipcregs_t *cc = NULL; -+ uint32 erombase, *eromptr, *eromlim; -+ uint i, j, cidx; -+ uint32 cia, cib, nmp, nsp; -+ uint32 asd, addrl, addrh, sizel, sizeh; -+ -+ for (i = 0; i < sii->numcores; i++) { -+ if (sii->coreid[i] == CC_CORE_ID) { -+ cc = (chipcregs_t *)sii->regs[i]; -+ break; -+ } -+ } -+ if (cc == NULL) { -+ goto error; -+ } -+ -+ erombase = R_REG(sii->osh, &cc->eromptr); -+ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); -+ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); -+ -+ cidx = sii->curidx; -+ cia = sii->cia[cidx]; -+ cib = sii->cib[cidx]; -+ -+ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; -+ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; -+ -+ /* scan for cores */ -+ while (eromptr < eromlim) { -+ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && -+ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { -+ break; -+ } -+ } -+ -+ /* skip master ports */ -+ for (i = 0; i < nmp; i++) { -+ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); -+ } -+ -+ /* Skip ASDs in port 0 */ -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); -+ if (asd == 0) { -+ /* Try again to see if it is a bridge */ -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, -+ &sizel, &sizeh); -+ } -+ -+ j = 1; -+ do { -+ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, -+ &sizel, &sizeh); -+ j++; -+ } while (asd != 0); -+ -+ /* Go through the ASDs for other slave ports */ -+ for (i = 1; i < nsp; i++) { -+ j = 0; -+ do { -+ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, -+ &sizel, &sizeh); -+ if (asd == 0) { -+ break; -+ } -+ -+ if (!asidx--) { -+ *addr = addrl; -+ *size = sizel; -+ return; -+ } -+ j++; -+ } while (1); -+ -+ if (j == 0) { -+ SI_ERROR((" SP %d has no address descriptors\n", i)); -+ break; -+ } -+ } -+ -+error: -+ *size = 0; -+ return; -+} -+ -+/* Return the number of address spaces in current core */ -+int -+ai_numaddrspaces(si_t *sih) -+{ -+ /* XXX: Either save ot or parse the EROM on demand */ -+ return 2; -+} -+ -+/* Return the address of the nth address space in the current core */ -+uint32 -+ai_addrspace(si_t *sih, uint asidx) -+{ -+ si_info_t *sii; -+ uint cidx; -+ -+ sii = SI_INFO(sih); -+ cidx = sii->curidx; -+ -+ if (asidx == 0) { -+ return sii->coresba[cidx]; -+ } else if (asidx == 1) { -+ return sii->coresba2[cidx]; -+ } else { -+ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", -+ __FUNCTION__, asidx)); -+ return 0; -+ } -+} -+ -+/* Return the size of the nth address space in the current core */ -+uint32 -+ai_addrspacesize(si_t *sih, uint asidx) -+{ -+ si_info_t *sii; -+ uint cidx; -+ -+ sii = SI_INFO(sih); -+ cidx = sii->curidx; -+ -+ if (asidx == 0) { -+ return sii->coresba_size[cidx]; -+ } else if (asidx == 1) { -+ return sii->coresba2_size[cidx]; -+ } else { -+ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", -+ __FUNCTION__, asidx)); -+ return 0; -+ } -+} -+ -+uint -+ai_flag(si_t *sih) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ -+ sii = SI_INFO(sih); -+ ai = sii->curwrap; -+ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); -+} -+ -+void -+ai_setint(si_t *sih, int siflag) -+{ -+ /* XXX: Figure out OOB stuff */ -+} -+ -+uint -+ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) -+{ -+ si_info_t *sii = SI_INFO(sih); -+ uint32 *map = (uint32 *) sii->curwrap; -+ -+ if (mask || val) { -+ uint32 w = R_REG(sii->osh, map+(offset/4)); -+ w &= ~mask; -+ w |= val; -+ W_REG(sii->osh, map+(offset/4), val); -+ } -+ -+ return (R_REG(sii->osh, map+(offset/4))); -+} -+ -+uint -+ai_corevendor(si_t *sih) -+{ -+ si_info_t *sii; -+ uint32 cia; -+ -+ sii = SI_INFO(sih); -+ cia = sii->cia[sii->curidx]; -+ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); -+} -+ -+uint -+ai_corerev(si_t *sih) -+{ -+ si_info_t *sii; -+ uint32 cib; -+ -+ sii = SI_INFO(sih); -+ cib = sii->cib[sii->curidx]; -+ return ((cib & CIB_REV_MASK) >> CIB_REV_SHIFT); -+} -+ -+bool -+ai_iscoreup(si_t *sih) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ -+ sii = SI_INFO(sih); -+ ai = sii->curwrap; -+ -+ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && -+ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); -+} -+ -+/* -+ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, -+ * switch back to the original core, and return the new value. -+ * -+ * When using the silicon backplane, no fiddling with interrupts or core switches is needed. -+ * -+ * Also, when using pci/pcie, we can optimize away the core switching for pci registers -+ * and (on newer pci cores) chipcommon registers. -+ */ -+uint -+ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) -+{ -+ uint origidx = 0; -+ uint32 *r = NULL; -+ uint w; -+ uint intr_val = 0; -+ bool fast = FALSE; -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ -+ ASSERT(GOODIDX(coreidx)); -+ ASSERT(regoff < SI_CORE_SIZE); -+ ASSERT((val & ~mask) == 0); -+ -+ if (coreidx >= SI_MAXCORES) { -+ return 0; -+ } -+ -+ if (BUSTYPE(sih->bustype) == SI_BUS) { -+ /* If internal bus, we can always get at everything */ -+ fast = TRUE; -+ /* map if does not exist */ -+ if (!sii->regs[coreidx]) { -+ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], -+ SI_CORE_SIZE); -+ ASSERT(GOODREGS(sii->regs[coreidx])); -+ } -+ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); -+ } else if (BUSTYPE(sih->bustype) == PCI_BUS) { -+ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ -+ -+ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { -+ /* Chipc registers are mapped at 12KB */ -+ -+ fast = TRUE; -+ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); -+ } else if (sii->pub.buscoreidx == coreidx) { -+ /* pci registers are at either in the last 2KB of an 8KB window -+ * or, in pcie and pci rev 13 at 8KB -+ */ -+ fast = TRUE; -+ if (SI_FAST(sii)) { -+ r = (uint32 *)((char *)sii->curmap + -+ PCI_16KB0_PCIREGS_OFFSET + regoff); -+ } else { -+ r = (uint32 *)((char *)sii->curmap + -+ ((regoff >= SBCONFIGOFF) ? -+ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + -+ regoff); -+ } -+ } -+ } -+ -+ if (!fast) { -+ INTR_OFF(sii, intr_val); -+ -+ /* save current core index */ -+ origidx = si_coreidx(&sii->pub); -+ -+ /* switch core */ -+ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); -+ } -+ ASSERT(r != NULL); -+ -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_REG(sii->osh, r) & ~mask) | val; -+ W_REG(sii->osh, r, w); -+ } -+ -+ /* readback */ -+ w = R_REG(sii->osh, r); -+ -+ if (!fast) { -+ /* restore core index */ -+ if (origidx != coreidx) { -+ ai_setcoreidx(&sii->pub, origidx); -+ } -+ -+ INTR_RESTORE(sii, intr_val); -+ } -+ -+ return (w); -+} -+ -+void -+ai_core_disable(si_t *sih, uint32 bits) -+{ -+ si_info_t *sii; -+ volatile uint32 dummy; -+ uint32 status; -+ aidmp_t *ai; -+ -+ sii = SI_INFO(sih); -+ -+ ASSERT(GOODREGS(sii->curwrap)); -+ ai = sii->curwrap; -+ -+ /* if core is already in reset, just return */ -+ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) { -+ return; -+ } -+ -+ /* ensure there are no pending backplane operations */ -+ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); -+ -+ /* if pending backplane ops still, try waiting longer */ -+ if (status != 0) { -+ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */ -+ /* during driver load we may need more time */ -+ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000); -+ /* if still pending ops, continue on and try disable anyway */ -+ /* this is in big hammer path, so don't call wl_reinit in this case... */ -+#ifdef BCMDBG -+ if (status != 0) { -+ printf("%s: WARN: resetstatus=%0x on core disable\n", __FUNCTION__, status); -+ } -+#endif -+ } -+ -+ W_REG(sii->osh, &ai->ioctrl, bits); -+ dummy = R_REG(sii->osh, &ai->ioctrl); -+ BCM_REFERENCE(dummy); -+ OSL_DELAY(10); -+ -+ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); -+ dummy = R_REG(sii->osh, &ai->resetctrl); -+ BCM_REFERENCE(dummy); -+ OSL_DELAY(1); -+} -+ -+/* reset and re-enable a core -+ * inputs: -+ * bits - core specific bits that are set during and after reset sequence -+ * resetbits - core specific bits that are set only during reset sequence -+ */ -+void -+ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ volatile uint32 dummy; -+ -+ sii = SI_INFO(sih); -+ ASSERT(GOODREGS(sii->curwrap)); -+ ai = sii->curwrap; -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_ACP -+ bits = resetbits = R_REG(sii->osh, &ai->ioctrl) & 0xFFFFFFFC; -+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+ -+ /* -+ * Must do the disable sequence first to work for arbitrary current core state. -+ */ -+ ai_core_disable(sih, (bits | resetbits)); -+ -+ /* -+ * Now do the initialization sequence. -+ */ -+ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); -+ dummy = R_REG(sii->osh, &ai->ioctrl); -+ BCM_REFERENCE(dummy); -+ -+ W_REG(sii->osh, &ai->resetctrl, 0); -+ dummy = R_REG(sii->osh, &ai->resetctrl); -+ BCM_REFERENCE(dummy); -+ OSL_DELAY(1); -+ -+ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); -+ dummy = R_REG(sii->osh, &ai->ioctrl); -+ BCM_REFERENCE(dummy); -+ OSL_DELAY(1); -+} -+ -+void -+ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ uint32 w; -+ -+ sii = SI_INFO(sih); -+ -+ ASSERT(GOODREGS(sii->curwrap)); -+ ai = sii->curwrap; -+ -+ ASSERT((val & ~mask) == 0); -+ -+ if (mask || val) { -+ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); -+ W_REG(sii->osh, &ai->ioctrl, w); -+ } -+} -+ -+uint32 -+ai_core_cflags(si_t *sih, uint32 mask, uint32 val) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ uint32 w; -+ -+ sii = SI_INFO(sih); -+ -+ ASSERT(GOODREGS(sii->curwrap)); -+ ai = sii->curwrap; -+ -+ ASSERT((val & ~mask) == 0); -+ -+ if (mask || val) { -+ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); -+ W_REG(sii->osh, &ai->ioctrl, w); -+ } -+ -+ return R_REG(sii->osh, &ai->ioctrl); -+} -+ -+uint32 -+ai_core_sflags(si_t *sih, uint32 mask, uint32 val) -+{ -+ si_info_t *sii; -+ aidmp_t *ai; -+ uint32 w; -+ -+ sii = SI_INFO(sih); -+ -+ ASSERT(GOODREGS(sii->curwrap)); -+ ai = sii->curwrap; -+ -+ ASSERT((val & ~mask) == 0); -+ ASSERT((mask & ~SISF_CORE_BITS) == 0); -+ -+ if (mask || val) { -+ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); -+ W_REG(sii->osh, &ai->iostatus, w); -+ } -+ -+ return R_REG(sii->osh, &ai->iostatus); -+} -+ -+#if defined(BCMDBG) || defined(BCMDBG_DUMP) -+/* print interesting aidmp registers */ -+void -+ai_dumpregs(si_t *sih, struct bcmstrbuf *b) -+{ -+ si_info_t *sii; -+ osl_t *osh; -+ aidmp_t *ai; -+ uint i; -+ -+ sii = SI_INFO(sih); -+ osh = sii->osh; -+ -+ for (i = 0; i < sii->numcores; i++) { -+ si_setcoreidx(&sii->pub, i); -+ ai = sii->curwrap; -+ -+ bcm_bprintf(b, "core 0x%x: \n", sii->coreid[i]); -+ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" -+ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" -+ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n" -+ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" -+ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" -+ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" -+ "intstatus 0x%x config 0x%x itcr 0x%x\n", -+ R_REG(osh, &ai->ioctrlset), -+ R_REG(osh, &ai->ioctrlclear), -+ R_REG(osh, &ai->ioctrl), -+ R_REG(osh, &ai->iostatus), -+ R_REG(osh, &ai->ioctrlwidth), -+ R_REG(osh, &ai->iostatuswidth), -+ R_REG(osh, &ai->resetctrl), -+ R_REG(osh, &ai->resetstatus), -+ R_REG(osh, &ai->resetreadid), -+ R_REG(osh, &ai->resetwriteid), -+ R_REG(osh, &ai->errlogctrl), -+ R_REG(osh, &ai->errlogdone), -+ R_REG(osh, &ai->errlogstatus), -+ R_REG(osh, &ai->errlogaddrlo), -+ R_REG(osh, &ai->errlogaddrhi), -+ R_REG(osh, &ai->errlogid), -+ R_REG(osh, &ai->errloguser), -+ R_REG(osh, &ai->errlogflags), -+ R_REG(osh, &ai->intstatus), -+ R_REG(osh, &ai->config), -+ R_REG(osh, &ai->itcr)); -+ } -+} -+#endif /* BCMDBG || BCMDBG_DUMP */ -+ -+#ifdef BCMDBG -+static void -+_ai_view(osl_t *osh, aidmp_t *ai, uint32 cid, uint32 addr, bool verbose) -+{ -+ uint32 config; -+ -+ config = R_REG(osh, &ai->config); -+ SI_ERROR(("\nCore ID: 0x%x, addr 0x%x, config 0x%x\n", cid, addr, config)); -+ -+ if (config & AICFG_RST) { -+ SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n", -+ R_REG(osh, &ai->resetctrl), R_REG(osh, &ai->resetstatus), -+ R_REG(osh, &ai->resetreadid), R_REG(osh, &ai->resetwriteid))); -+ } -+ -+ if (config & AICFG_IOC) { -+ SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh, &ai->ioctrl), -+ R_REG(osh, &ai->ioctrlwidth))); -+ } -+ -+ if (config & AICFG_IOS) { -+ SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh, &ai->iostatus), -+ R_REG(osh, &ai->iostatuswidth))); -+ } -+ -+ if (config & AICFG_ERRL) { -+ SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n", -+ R_REG(osh, &ai->errlogctrl), R_REG(osh, &ai->errlogdone), -+ R_REG(osh, &ai->errlogstatus), R_REG(osh, &ai->intstatus))); -+ SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr " -+ "0x%x/0x%x\n", -+ R_REG(osh, &ai->errlogid), R_REG(osh, &ai->errloguser), -+ R_REG(osh, &ai->errlogflags), R_REG(osh, &ai->errlogaddrhi), -+ R_REG(osh, &ai->errlogaddrlo))); -+ } -+ -+ if (verbose && (config & AICFG_OOB)) { -+ SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n", -+ R_REG(osh, &ai->oobselina30), R_REG(osh, &ai->oobselina74))); -+ SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n", -+ R_REG(osh, &ai->oobselinb30), R_REG(osh, &ai->oobselinb74))); -+ SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n", -+ R_REG(osh, &ai->oobselinc30), R_REG(osh, &ai->oobselinc74))); -+ SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n", -+ R_REG(osh, &ai->oobselind30), R_REG(osh, &ai->oobselind74))); -+ SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n", -+ R_REG(osh, &ai->oobselouta30), R_REG(osh, &ai->oobselouta74))); -+ SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n", -+ R_REG(osh, &ai->oobseloutb30), R_REG(osh, &ai->oobseloutb74))); -+ SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n", -+ R_REG(osh, &ai->oobseloutc30), R_REG(osh, &ai->oobseloutc74))); -+ SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n", -+ R_REG(osh, &ai->oobseloutd30), R_REG(osh, &ai->oobseloutd74))); -+ SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n", -+ R_REG(osh, &ai->oobsynca), R_REG(osh, &ai->oobseloutaen))); -+ SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n", -+ R_REG(osh, &ai->oobsyncb), R_REG(osh, &ai->oobseloutben))); -+ SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n", -+ R_REG(osh, &ai->oobsyncc), R_REG(osh, &ai->oobseloutcen))); -+ SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n", -+ R_REG(osh, &ai->oobsyncd), R_REG(osh, &ai->oobseloutden))); -+ SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n", -+ R_REG(osh, &ai->oobaextwidth), R_REG(osh, &ai->oobainwidth), -+ R_REG(osh, &ai->oobaoutwidth))); -+ SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n", -+ R_REG(osh, &ai->oobbextwidth), R_REG(osh, &ai->oobbinwidth), -+ R_REG(osh, &ai->oobboutwidth))); -+ SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n", -+ R_REG(osh, &ai->oobcextwidth), R_REG(osh, &ai->oobcinwidth), -+ R_REG(osh, &ai->oobcoutwidth))); -+ SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n", -+ R_REG(osh, &ai->oobdextwidth), R_REG(osh, &ai->oobdinwidth), -+ R_REG(osh, &ai->oobdoutwidth))); -+ } -+} -+ -+void -+ai_view(si_t *sih, bool verbose) -+{ -+ si_info_t *sii; -+ osl_t *osh; -+ aidmp_t *ai; -+ uint32 cid, addr; -+ -+ sii = SI_INFO(sih); -+ ai = sii->curwrap; -+ osh = sii->osh; -+ -+ cid = sii->coreid[sii->curidx]; -+ addr = sii->wrapba[sii->curidx]; -+ _ai_view(osh, ai, cid, addr, verbose); -+} -+ -+void -+ai_viewall(si_t *sih, bool verbose) -+{ -+ si_info_t *sii; -+ osl_t *osh; -+ aidmp_t *ai; -+ uint32 cid, addr; -+ uint i; -+ -+ sii = SI_INFO(sih); -+ osh = sii->osh; -+ for (i = 0; i < sii->numcores; i++) { -+ si_setcoreidx(sih, i); -+ -+ ai = sii->curwrap; -+ cid = sii->coreid[sii->curidx]; -+ addr = sii->wrapba[sii->curidx]; -+ _ai_view(osh, ai, cid, addr, verbose); -+ } -+} -+#endif /* BCMDBG */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_egphy28.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_egphy28.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_egphy28.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_egphy28.c 2017-11-09 17:53:44.024296000 +0800 -@@ -0,0 +1,352 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+#include -+#include -+#include "../../../mdio/iproc_mdio.h" -+#include "bcmiproc_phy.h" -+#include "bcmiproc_egphy28.h" -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+extern u32 cmicd_schan_write(void __iomem *base, u32 ctrl, u32 addr, u32 val); -+extern u32 cmicd_schan_read(void __iomem *base, u32 ctrl, u32 addr); -+ -+ -+static int -+egphy28_rdb_reg_read(u32 phy_addr, u32 reg_addr, u16 *data) -+{ -+ int rv = SOC_E_NONE; -+ -+ /* MDIO write the RDB reg. address to reg.0x1E = */ -+ iproc_mii_write(MII_DEV_LOCAL, phy_addr, EGPHY28_REG_RDB_ADDR, -+ (0xffff & reg_addr)); -+ -+ /* MDIO read from reg.0x1F to get the RDB register's value as */ -+ iproc_mii_read(MII_DEV_LOCAL, phy_addr, EGPHY28_REG_RDB_DATA, data); -+ -+ return rv; -+} -+ -+static int -+egphy28_rdb_reg_write(u32 phy_addr, u32 reg_addr, u16 data) -+{ -+ int rv = SOC_E_NONE; -+ -+ /* MDIO write the RDB reg. address to reg.0x1E = */ -+ iproc_mii_write(MII_DEV_LOCAL, phy_addr, EGPHY28_REG_RDB_ADDR, -+ (0xffff & reg_addr)); -+ -+ /* MDIO write to reg.0x1F to set the RDB resister's value as */ -+ iproc_mii_write(MII_DEV_LOCAL, phy_addr, EGPHY28_REG_RDB_DATA, data); -+ -+ return rv; -+} -+ -+static void -+egphy28_rdb_reg_modify(u32 phy_addr, int reg_addr, u16 data, u16 mask) -+{ -+ u16 ori_data; -+ -+ egphy28_rdb_reg_read(phy_addr, reg_addr, &ori_data); -+ ori_data &= ~mask; -+ ori_data |= (data & mask); -+ egphy28_rdb_reg_write(phy_addr, reg_addr, ori_data); -+} -+ -+int -+egphy28_reg_read(u32 phy_addr, int reg_addr, u16 *data) -+{ -+ int rv = SOC_E_NONE; -+ iproc_mii_read(MII_DEV_LOCAL, phy_addr, reg_addr, data); -+ -+ return rv; -+} -+ -+int -+egphy28_reg_write(u32 phy_addr, int reg_addr, u16 data) -+{ -+ int rv = SOC_E_NONE; -+ iproc_mii_write(MII_DEV_LOCAL, phy_addr, reg_addr, data); -+ -+ return rv; -+} -+ -+static void -+egphy28_reg_modify(u32 phy_addr, int reg_addr, u16 data, u16 mask) -+{ -+ u16 ori_data; -+ -+ egphy28_reg_read(phy_addr, reg_addr, &ori_data); -+ ori_data &= ~mask; -+ ori_data |= (data & mask); -+ egphy28_reg_write(phy_addr, reg_addr, ori_data); -+} -+ -+static int -+egphy28_ge_reset(u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ u16 val; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ /* Reset the PHY */ -+ egphy28_reg_read(phy_addr, EGPHY28_COPPER_MII_CTRL, &val); -+ val |= BMCR_RESET; -+ egphy28_reg_write(phy_addr, EGPHY28_COPPER_MII_CTRL, val); -+ -+ SPINWAIT((!egphy28_reg_read(phy_addr, EGPHY28_COPPER_MII_CTRL, &val) && -+ (val & BMCR_RESET)), 100000); -+ -+ /* Check if out of reset */ -+ egphy28_reg_read(phy_addr, EGPHY28_COPPER_MII_CTRL, &val); -+ if (val & BMCR_RESET) { -+ NET_ERROR(("%s reset not complete\n", __FUNCTION__)); -+ rv = SOC_E_TIMEOUT; -+ } else { -+ NET_TRACE(("%s reset complete\n", __FUNCTION__)); -+ } -+ -+ return rv; -+} -+ -+ -+#if 0 -+static void -+cmid_schan_modify(void __iomem *base, u32 ctrl, u32 addr, u32 val, u32 mask) -+{ -+ u32 ori_val; -+ -+ ori_val = cmicd_schan_read(base, ctrl, addr); -+ ori_val &= ~mask; -+ ori_val |= (val & mask); -+ cmicd_schan_write(base, ctrl, addr, ori_val); -+} -+#endif -+ -+ -+static int -+egphy28_ge_init(void __iomem *base, u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ /* ==== Power up PHY ==== */ -+#if 0 -+ /* Give initial value */ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[23:20] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x0, 0x00F00000); -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x40000, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x040000); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ -+ /* ==== Partial Power down other 3 PHYs ==== */ -+ -+ /* Give initial value */ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[22:20] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x0, 0x00700000); -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x40000, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[22:20] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x00700000, 0x00700000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x20, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x040000, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x20, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ -+ /* TOP_QGPHY_CTRL_0.EXT_PWRDOWN[23] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033800, 0x0, 0x00800000); -+ /* TOP_QGPHY_CTRL_2.GPHY_IDDQ_GLOBAL_PWR[18] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x040000); -+ /* TOP_QGPHY_CTRL_2.IDDQ_BIAS[5] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02033400, 0x0, 0x20); -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = LOW */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x0, 0x200000); -+ -+ /* TOP_SOFT_RESET_REG.TOP_QGPHY_RST_L[21] = HIGH */ -+ cmid_schan_modify(base, 0x2c800200, 0x02030400, 0x200000, 0x200000); -+ -+ /* Reset the PHY (Register[0x00], bit 15 = 1) */ -+ egphy28_reg_modify(phy_addr, EGPHY28_COPPER_MII_CTRL, BMCR_RESET, BMCR_RESET); -+ -+ /* -+ * Enable direct RDB addressing mode, write to Expansion register -+ * 0x7E = 0x0000 -+ * - MDIO write to reg 0x17 = 0x0F7E -+ * - MDIO write to reg 0x15 = 0x0000 -+ */ -+ egphy28_reg_write(phy_addr, EGPHY28_RDB_ACCESS_ADDR_1, EGPHY28_RDB_ACCESS_DATA_1); -+ egphy28_reg_write(phy_addr, EGPHY28_RDB_ACCESS_ADDR_2, EGPHY28_RDB_ACCESS_DATA_2); -+ -+ /* Clear Reset the PHY (Register[0x00], bit 15 = 0) */ -+ egphy28_reg_modify(phy_addr, EGPHY28_COPPER_MII_CTRL, 0x0, BMCR_RESET); -+ -+ /* Set MAC PHY interface to be GMII mode */ -+ egphy28_reg_modify(phy_addr, EGPGY28_MII_ECONTROL, 0x0, (1 << 15)); -+ -+ /* Set 1000BASE-T full-duplex and switch device port (Register[0x09], bit 9,10 = 1) */ -+ egphy28_reg_write(phy_addr, EGPHY28_MII_CTRL1000, ADVERTISE_1000FULL | REPEATER_DTE); -+ -+ /* Set Full-duplex, 1000BASE-T, Auto-Negoatiation, Restartr-AN -+ * (Register[0x00], bit 8, 6, 12, 9 = 1) -+ */ -+ egphy28_reg_write(phy_addr, EGPHY28_COPPER_MII_CTRL, (BMCR_FULLDPLX | BMCR_SPEED1000 | -+ BMCR_ANENABLE | BMCR_ANRESTART)); -+ -+ /* Disable super-isolate (RDB Register[0x02a], bit 5 = 0). in default */ -+ egphy28_rdb_reg_modify(phy_addr, 0x2a, 0x0, (1 << 5)); -+ -+ /* Remove power down (Register[0x00], bit 11 = 0). in default */ -+ egphy28_reg_modify(phy_addr, EGPHY28_COPPER_MII_CTRL, ~BMCR_PDOWN, BMCR_PDOWN); -+ -+ /* Enable LEDs to indicate traffic status (Register[0x10], bit 5 = 1) */ -+ egphy28_reg_modify(phy_addr, 0x10, (1 << 5), (1 << 5)); -+ -+ /* Enable extended packet length (4.5k through 25k) (RDB Register[0x28], bit 14 = 1) */ -+ egphy28_rdb_reg_modify(phy_addr, 0x28, (1 << 14), (1 << 14)); -+ -+ egphy28_rdb_reg_modify(phy_addr, 0x16, (1 << 0), (1 << 0)); -+ egphy28_rdb_reg_modify(phy_addr, 0x1b, (1 << 1), (1 << 1)); -+ -+ /* Configure LED selectors */ -+ /* Disable carrier extension */ -+ /* IEEE compliance setup */ -+ egphy28_rdb_reg_write(phy_addr, 0x1E4, 0x00C0); -+ egphy28_rdb_reg_write(phy_addr, 0x1E7, 0xB008); -+ egphy28_rdb_reg_write(phy_addr, 0x1E2, 0x02E3); -+ egphy28_rdb_reg_write(phy_addr, 0x1E0, 0x0D11); -+ egphy28_rdb_reg_write(phy_addr, 0x1E3, 0x7FC0); -+ egphy28_rdb_reg_write(phy_addr, 0x1EB, 0x6B40); -+ egphy28_rdb_reg_write(phy_addr, 0x1E8, 0x0213); -+ egphy28_rdb_reg_write(phy_addr, 0x1E9, 0x0020); -+ egphy28_rdb_reg_write(phy_addr, 0x28, 0x4C30); -+ egphy28_rdb_reg_write(phy_addr, 0x125, 0x211B); -+ egphy28_rdb_reg_write(phy_addr, 0xE, 0x0013); -+ egphy28_rdb_reg_write(phy_addr, 0xB0, 0x000C); -+ egphy28_rdb_reg_write(phy_addr, 0xB0, 0x0000); -+ -+ /* Set Full-duplex, 1000BASE-T, Auto-Negoatiation, Restartr-AN -+ * (Register[0x00], bit 8, 6, 12, 9 = 1) -+ */ -+ egphy28_reg_write(phy_addr, EGPHY28_COPPER_MII_CTRL, (BMCR_FULLDPLX | BMCR_SPEED1000 | -+ BMCR_ANENABLE | BMCR_ANRESTART)); -+ -+ /* Automatic Master/Slave configuration (Register[0x09], bit 12 = 0) in default */ -+ egphy28_reg_modify(phy_addr, EGPHY28_MII_CTRL1000, 0x0, (1 << 12)); -+ -+ /* Ability advert set : IEEE 802.3, 10HD, 100HD, 10FD, 100FD */ -+ /* (Register[0x04] bit 0, 5, 7, 6, 8 = 1 */ -+ egphy28_reg_modify(phy_addr, EGPHY28_MII_ADVERTISE, -+ (ADVERTISE_10HALF | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_100FULL | ADVERTISE_CSMA), -+ (ADVERTISE_10HALF | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_100FULL | ADVERTISE_CSMA)); -+ /* Ability advert set : switch device port, 1000BASE-T FD, non-1000BASE-T HD */ -+ /* (Register[0x09] bit 10, 9 = 1, bit 8 = 0 */ -+ egphy28_reg_modify(phy_addr, EGPHY28_MII_CTRL1000, -+ (REPEATER_DTE | ADVERTISE_1000FULL), (REPEATER_DTE | ADVERTISE_1000FULL | ADVERTISE_1000HALF)); -+ -+ /* Set Auto-Negoatiation, Restartr-AN (Register[0x00], bit 12, 9 = 1) */ -+ egphy28_reg_modify(phy_addr, EGPHY28_COPPER_MII_CTRL, (BMCR_ANENABLE | BMCR_ANRESTART), -+ (BMCR_ANENABLE | BMCR_ANRESTART)); -+ -+ /* Clear bit 14 for automatic MDI crossover (Register[RDB 0x00] bit 14 = 0) in default */ -+ egphy28_rdb_reg_modify(phy_addr, 0x00, 0x0, (1 << 14)); -+ -+ /* Clear bit 9 to disable forced auto MDI xover */ -+ egphy28_rdb_reg_modify(phy_addr, 0x2f, 0x0, (1 << 9)); -+#endif -+ -+ return rv; -+} -+ -+ -+int -+egphy28_reset_setup(void __iomem *base, u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ rv = egphy28_ge_reset(phy_addr); -+ if (SOC_SUCCESS(rv)) { -+ rv = egphy28_ge_init(base, phy_addr); -+ } -+ -+ return rv; -+} -+ -+int -+egphy28_init(void __iomem *base, u32 phy_addr) -+{ -+ u16 phyid0, phyid1; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ egphy28_reg_read(phy_addr, EGPHY28_PHY_ID_MSB, &phyid0); -+ egphy28_reg_read(phy_addr, EGPHY28_PHY_ID_LSB, &phyid1); -+ -+ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); -+ //egphy28_reset_setup(base, phy_addr); -+ -+ return 0; -+} -+ -+int -+egphy28_enable_set(u32 phy_addr, int enable) -+{ -+ u16 val; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ egphy28_reg_read(phy_addr, EGPHY28_COPPER_MII_CTRL, &val); -+ if (enable) { -+ val &= ~BMCR_PDOWN; -+ } else { -+ val |= BMCR_PDOWN; -+ } -+ egphy28_reg_write(phy_addr, EGPHY28_COPPER_MII_CTRL, val); -+ -+ return SOC_E_NONE; -+} -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5221.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5221.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5221.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5221.c 2017-11-09 17:53:44.025293000 +0800 -@@ -0,0 +1,657 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+#include -+#include "../../../mdio/iproc_mdio.h" -+#include "bcmiproc_phy.h" -+#include "bcmiproc_phy5221.h" -+ -+/* ---- External Variable Declarations ----------------------------------- */ -+/* ---- External Function Prototypes ------------------------------------- */ -+/* ---- Public Variables ------------------------------------------------- */ -+/* ---- Private Constants and Types -------------------------------------- */ -+/* ---- Private Variables ------------------------------------------------ */ -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+ -+/* ==== Public Functions ================================================= */ -+ -+int -+phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ uint16 wr_data=*data; -+ uint16 test_reg; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data)); -+ -+ if (reg_bank) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); -+ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); -+ } else { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ } -+ return SOC_E_NONE; -+} -+ -+ -+int -+phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ uint16 test_reg; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to read phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr)); -+ -+ if (reg_bank) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); -+ -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); -+ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); -+ } else { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); -+ } -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, *data)); -+ -+ return SOC_E_NONE; -+} -+ -+ -+int -+phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask) -+{ -+ uint16 test_reg; -+ uint16 org_data, rd_data; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, data, mask)); -+ -+ if (reg_bank) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); -+ -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ org_data = rd_data; -+ rd_data &= ~(mask); -+ rd_data |= data; -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); -+ } else { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ org_data = rd_data; -+ rd_data &= ~(mask); -+ rd_data |= data; -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ } -+ -+ return SOC_E_NONE; -+} -+ -+ -+void -+phy5221_fe_reset(uint eth_num, uint phyaddr) -+{ -+ uint16 ctrl; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ /* set reset flag */ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ ctrl |= MII_CTRL_RESET; -+ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ -+ SPINWAIT( (!phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) -+ && (ctrl & MII_CTRL_RESET)), 100000); -+ /* check if out of reset */ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ if (ctrl & MII_CTRL_RESET) { -+ /* timeout */ -+ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); -+ } else { -+ NET_ERROR(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); -+ } -+ -+ return; -+} -+ -+ -+/* -+ * Function: -+ * phy5221_fe_init -+ * Purpose: -+ * Initialize the PHY (MII mode) to a known good state. -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * Returns: -+ * SOC_E_XXX -+ -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5221_fe_init(uint eth_num, uint phyaddr) -+{ -+ uint16 mii_ana, mii_ctrl; -+ -+ /* Reset PHY */ -+ phy5221_fe_reset(eth_num, phyaddr); -+ -+ mii_ana = MII_ANA_HD_10 | MII_ANA_FD_10 | MII_ANA_HD_100 | -+ MII_ANA_FD_100 | MII_ANA_ASF_802_3; -+ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_100 | MII_CTRL_AE | MII_CTRL_RAN; -+ -+ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ -+ return SOC_E_NONE; -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * phy5221_fe_speed_set -+ * Purpose: -+ * Set the current operating speed (forced). -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * duplex - (OUT) Boolean, true indicates full duplex, false -+ * indicates half. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. Autonegotiation is -+ * not manipulated. -+ */ -+int -+phy5221_fe_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ uint16 mii_ctrl; -+ -+ if (speed == 0) { -+ return SOC_E_NONE; -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ mii_ctrl &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); -+ switch(speed) { -+ case 10: -+ mii_ctrl |= MII_CTRL_SS_10; -+ break; -+ case 100: -+ mii_ctrl |= MII_CTRL_SS_100; -+ break; -+ case 1000: -+ mii_ctrl |= MII_CTRL_SS_1000; -+ break; -+ default: -+ return SOC_E_CONFIG; -+ } -+ -+ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return SOC_E_NONE; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+/* -+ * Function: -+ * phy5221_init -+ * Purpose: -+ * Initialize xgxs6 phys -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * Returns: -+ * 0 -+ */ -+int -+phy5221_init(uint eth_num, uint phyaddr) -+{ -+ uint16 phyid0, phyid1; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); -+ -+ NET_TRACE(("%s phyaddr(0x%x) Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyaddr, phyid1, phyid0)); -+ -+ phy5221_fe_init(eth_num, phyaddr); -+ -+ return 0; -+} -+ -+/* -+ * Function: -+ * phy5221_link_get -+ * Purpose: -+ * Determine the current link up/down status -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5221_link_get(uint eth_num, uint phyaddr, int *link) -+{ -+ uint16 mii_ctrl, mii_stat; -+ uint32 wait; -+ -+ *link = FALSE; /* Default */ -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ /* the first read of status register will not show link up, second read will show link up */ -+ if (!(mii_stat & MII_STAT_LA) ) { -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ } -+ -+ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { -+ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ -+ return SOC_E_NONE; -+ } -+ -+ /* Link appears to be up; we are done if autoneg is off. */ -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ if (!(mii_ctrl & MII_CTRL_AE)) { -+ *link = TRUE; -+ return SOC_E_NONE; -+ } -+ -+ /* -+ * If link appears to be up but autonegotiation is still in -+ * progress, wait for it to complete. For BCM5228, autoneg can -+ * still be busy up to about 200 usec after link is indicated. Also -+ * continue to check link state in case it goes back down. -+ * wait 500ms (500000us/10us = 50000 ) -+ */ -+ for (wait=0; wait<50000; wait++) { -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (!(mii_stat & MII_STAT_LA)) { -+ /* link is down */ -+ return SOC_E_NONE; -+ } -+ -+ if (mii_stat & MII_STAT_AN_DONE) { -+ /* AutoNegotiation done */ -+ break; -+ } -+ -+ OSL_DELAY(10); -+ } -+ if (wait>=50000) { -+ /* timeout */ -+ return SOC_E_BUSY; -+ } -+ -+ /* Return link state at end of polling */ -+ *link = ((mii_stat & MII_STAT_LA) != 0); -+ -+ return SOC_E_NONE; -+} -+ -+ -+/* -+ * Function: -+ * phy5221_enable_set -+ * Purpose: -+ * Enable/Disable phy -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * enable - on/off state to set -+ * Returns: -+ * 0 -+ */ -+int -+phy5221_enable_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 data; /* New value to write to PHY register */ -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ data = enable ? 0 : MII_ECR_TD; /* Transmitt enable/disable */ -+ phy5221_mod_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, data, MII_ECR_TD); -+ -+ data = enable ? 0 : PHY522X_SUPER_ISOLATE_MODE; -+ /* Device needs to be put in super-isolate mode in order to disable -+ * the link in 10BaseT mode -+ */ -+ phy5221_mod_reg(eth_num, phyaddr, PHY_AUX_MULTIPLE_PHYr_BANK, PHY_AUX_MULTIPLE_PHYr_ADDR, -+ data, PHY522X_SUPER_ISOLATE_MODE); -+ -+ return SOC_E_NONE; -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * phy5221_speed_set -+ * Purpose: -+ * Set PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5221_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5221_fe_speed_set(eth_num, phyaddr, speed); -+ -+ return 0; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+/* -+ * Function: -+ * phy5221_auto_negotiate_gcd (greatest common denominator). -+ * Purpose: -+ * Determine the current greatest common denominator between -+ * two ends of a link -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * speed - (OUT) greatest common speed. -+ * duplex - (OUT) greatest common duplex. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+static int -+phy5221_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int t_speed, t_duplex; -+ uint16 mii_ana, mii_anp, mii_stat; -+ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; -+ -+ mii_gb_stat = 0; /* Start off 0 */ -+ mii_gb_ctrl = 0; /* Start off 0 */ -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ -+ /* -+ * If the PHY supports extended status, check if it is 1000MB -+ * capable. If it is, check the 1000Base status register to see -+ * if 1000MB negotiated. -+ */ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); -+ -+ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | -+ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); -+ } -+ } -+ -+ /* -+ * At this point, if we did not see Gig status, one of mii_gb_stat or -+ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to -+ * fail and fall into the default 10/100 cases. -+ */ -+ -+ mii_ana &= mii_anp; -+ -+ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { -+ t_speed = 1000; -+ t_duplex = 1; -+ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { -+ t_speed = 1000; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ -+ t_speed = 100; -+ t_duplex = 1; -+ } else if (mii_ana & MII_ANA_T4) { /* [b] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ -+ t_speed = 10; -+ t_duplex = 1 ; -+ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ -+ t_speed = 10; -+ t_duplex = 0; -+ } else { -+ return(SOC_E_FAIL); -+ } -+ -+ if (speed) *speed = t_speed; -+ if (duplex) *duplex = t_duplex; -+ -+ return(SOC_E_NONE); -+} -+ -+ -+/* -+ * Function: -+ * phy5221_speed_get -+ * Purpose: -+ * Get PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - current link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int rv; -+ uint16 mii_ctrl, mii_stat; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ *speed = 0; -+ *duplex = 0; -+ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ -+ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ -+ rv = SOC_E_NONE; -+ } else { -+ rv = phy5221_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); -+ } -+ } else { /* Auto-negotiation disabled */ -+ /* -+ * Simply pick up the values we force in CTRL register. -+ */ -+ if (mii_ctrl & MII_CTRL_FD) -+ *duplex = 1; -+ -+ switch(MII_CTRL_SS(mii_ctrl)) { -+ case MII_CTRL_SS_10: -+ *speed = 10; -+ break; -+ case MII_CTRL_SS_100: -+ *speed = 100; -+ break; -+ case MII_CTRL_SS_1000: -+ *speed = 1000; -+ break; -+ default: /* Just pass error back */ -+ return(SOC_E_UNAVAIL); -+ } -+ rv = SOC_E_NONE; -+ } -+ -+ return(rv); -+} -+ -+ -+#ifdef BCMINTERNAL -+int -+phy5221_lb_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 mii_ctrl; -+ -+ /* set reset flag */ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ mii_ctrl &= ~MII_CTRL_LE; -+ mii_ctrl |= enable ? MII_CTRL_LE : 0; -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return 0; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+#ifdef BCMINTERNAL -+void -+phy5221_disp_status(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0, tmp1, tmp2; -+ int speed, duplex; -+ -+ printf("et%d: %s: phyaddr:%d\n", eth_num, __FUNCTION__, phyaddr); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &tmp0); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &tmp1); -+ printf(" MII-Control: 0x%x; MII-Status: 0x%x\n", tmp0, tmp1); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &tmp0); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &tmp1); -+ printf(" Phy ChipID: 0x%04x:0x%04x\n", tmp0, tmp1); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &tmp0); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &tmp1); -+ phy5221_speed_get(eth_num, phyaddr, &speed, &duplex); -+ printf(" AutoNeg Ad: 0x%x; AutoNeg Partner: 0x%x; speed:%d; duplex:%d\n", tmp0, tmp1, speed, duplex); -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &tmp0); -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &tmp1); -+ phy5221_rd_reg(eth_num, phyaddr, 0x0000, 0x11, &tmp2); -+ printf(" Reg0x0f: 0x%x; 100Base-X AUX ctrl: 0x%x; 100Base-X AUX stat: 0x%x\n", tmp0, tmp1, tmp2); -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0x0000, 0x12, &tmp0); -+ phy5221_rd_reg(eth_num, phyaddr, 0x0000, 0x13, &tmp1); -+ phy5221_rd_reg(eth_num, phyaddr, 0x0000, 0x14, &tmp2); -+ printf(" 100Base-X RCV ERR: 0x%x; 100Base-X FALSE CARRIER: 0x%x; 100Base-X DISCON: 0x%x\n", tmp0, tmp1, tmp2); -+} -+#endif /* BCMINTERNAL */ -+ -+ -+#ifdef BCMINTERNAL -+void -+phy5221_chk_err(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0; -+ -+ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &tmp0); -+ if (!(tmp0 & MII_STAT_LA)) { -+ printf("ERROR: reg 0x01 (LINK down): 0x%x\n", tmp0); -+ } -+ if (tmp0 & (MII_STAT_JBBR|MII_STAT_RF)) { -+ printf("ERROR: reg 0x01: 0x%x\n", tmp0); -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0, 0x11, &tmp0); -+ if (!(tmp0 & 0x100)) { -+ printf("ERROR: reg 0x11 (LINK down): 0x%x\n", tmp0); -+ } -+ if (tmp0 & 0x8bf) { -+ printf("ERROR: reg 0x11: 0x%x\n", tmp0); -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0, 0x12, &tmp0); -+ if (tmp0) { -+ printf("ERROR: reg 0x12 (RCV ERR CNT): 0x%x\n", tmp0); -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0, 0x13, &tmp0); -+ if (tmp0) { -+ printf("ERROR: reg 0x13 (FALSE CARRIER CNT): 0x%x\n", tmp0); -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0, 0x14, &tmp0); -+ if (tmp0 & 0xc000) { -+ printf("ERROR: reg 0x14: 0x%x\n", tmp0); -+ } -+ -+ phy5221_rd_reg(eth_num, phyaddr, 0, 0x19, &tmp0); -+ if (!(tmp0 & 0x4)) { -+ printf("ERROR: reg 0x19 (LINK down): 0x%x\n", tmp0); -+ } -+ if (tmp0 & 0xc0) { -+ printf("ERROR: reg 0x19: 0x%x\n", tmp0); -+ } -+} -+#endif /* BCMINTERNAL */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5461s.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5461s.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5461s.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5461s.c 2017-11-09 17:53:44.027292000 +0800 -@@ -0,0 +1,896 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+#include -+#include "../../../mdio/iproc_mdio.h" -+#include "bcmiproc_phy.h" -+#include "bcmiproc_phy5461s.h" -+ -+/* ---- External Variable Declarations ----------------------------------- */ -+/* ---- External Function Prototypes ------------------------------------- */ -+/* ---- Public Variables ------------------------------------------------- */ -+/* ---- Private Constants and Types -------------------------------------- */ -+/* ---- Private Variables ------------------------------------------------ */ -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+ -+/* ==== Public Functions ================================================= */ -+ -+int -+phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ int rv = SOC_E_NONE; -+ uint16 wr_data=*data; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to write phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data)); -+ //printf("%s phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ // __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data); -+ -+ if (flags & SOC_PHY_REG_1000X) { -+ if (reg_addr <= 0x000f) { -+ uint16 blk_sel; -+ -+ /* Map 1000X page */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); -+ -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); -+ -+ /* write 1000X IEEE register */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ -+ /* Restore IEEE mapping */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); -+ } else if (flags & _SOC_PHY_REG_DIRECT) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ } else { -+ switch(reg_addr) { -+ /* Map shadow registers */ -+#ifdef BCMINTERNAL -+ case 0x15: -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x17, reg_bank); -+ break; -+#endif /* BCMINTERNAL */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ if (reg_bank == 0x0007) { -+ wr_data |= 0x8000; -+ } -+ wr_data = (wr_data & ~(0x0007)) | reg_bank; -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x001F) { -+ wr_data = 0x8000 | (reg_bank << 10) | (wr_data & 0x03FF); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#ifdef BCMINTERNAL -+ case 0x1D: -+ if (reg_bank == 0x0000) { -+ wr_data = wr_data & 0x07FFF; -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#endif /* BCMINTERNAL */ -+ default: -+ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { -+ /* Must not write to reserved registers */ -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ } -+ break; -+ } -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ } -+ } -+ if (SOC_FAILURE(rv)) { -+ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); -+ } -+ return rv; -+} -+ -+ -+int -+phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ int rv = SOC_E_NONE; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to read phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", -+ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr)); -+ if (flags & SOC_PHY_REG_1000X) { -+ if (reg_addr <= 0x000f) { -+ uint16 blk_sel; -+ -+ /* Map 1000X page */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); -+ -+ /* Read 1000X IEEE register */ -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); -+ -+ /* Restore IEEE mapping */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ } else { -+ switch(reg_addr) { -+ /* Map shadow registers */ -+#ifdef BCMINTERNAL -+ case 0x15: -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x17, reg_bank); -+ break; -+#endif /* BCMINTERNAL */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x001F) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#ifdef BCMINTERNAL -+ case 0x1D: -+ if (reg_bank <= 0x0001) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 15)); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#endif /* BCMINTERNAL */ -+ default: -+ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { -+ /* Must not read from reserved registers */ -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ } -+ break; -+ } -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); -+ } -+ } -+ if (SOC_FAILURE(rv)) { -+ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); -+ } else { -+ //printf("%s phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); -+ } -+ -+ return rv; -+} -+ -+ -+int -+phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask) -+{ -+ int rv = SOC_E_NONE; -+ uint16 org_data, rd_data; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", -+ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, data, mask)); -+ -+ if (flags & SOC_PHY_REG_1000X) { -+ if (reg_addr <= 0x000f) { -+ uint16 blk_sel; -+ -+ /* Map 1000X page */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); -+ iproc_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); -+ -+ /* Modify 1000X IEEE register */ -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ org_data = rd_data; -+ rd_data &= ~(mask); -+ rd_data |= data; -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ -+ /* Restore IEEE mapping */ -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ } else { -+ switch(reg_addr) { -+ /* Map shadow registers */ -+#ifdef BCMINTERNAL -+ case 0x15: -+ iproc_mii_write(MII_DEV_EXT, phyaddr, 0x17, reg_bank); -+ break; -+#endif /* BCMINTERNAL */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); -+ -+ if (reg_bank == 0x0007) { -+ data |= 0x8000; -+ mask |= 0x8000; -+ } -+ mask &= ~(0x0007); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x001F) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); -+ data |= 0x8000; -+ mask |= 0x8000; -+ mask &= ~(0x1F << 10); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#ifdef BCMINTERNAL -+ case 0x1D: -+ if (reg_bank == 0x0000) { -+ mask &= 0x07FFF; -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+#endif /* BCMINTERNAL */ -+ default: -+ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { -+ /* Must not write to reserved registers */ -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ } -+ break; -+ } -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ org_data = rd_data; -+ rd_data &= ~(mask); -+ rd_data |= data; -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ } -+ } -+ -+ if (SOC_FAILURE(rv)) { -+ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); -+ } else { -+ //printf("%s modified(0x%x to 0x%x at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", -+ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); -+ } -+ -+ return rv; -+} -+ -+ -+void -+phy5461_ge_reset(uint eth_num, uint phyaddr) -+{ -+ uint16 ctrl; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ /* set reset flag */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ ctrl |= MII_CTRL_RESET; -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ -+ SPINWAIT( (!phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) -+ && (ctrl & MII_CTRL_RESET)), 100000); -+ /* check if out of reset */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ if (ctrl & MII_CTRL_RESET) { -+ /* timeout */ -+ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); -+ } else { -+ NET_TRACE(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); -+ } -+} -+ -+ -+/* -+ * Function: -+ * phy5461_ge_interface_set -+ * Purpose: -+ * Set the current operating mode of the PHY. -+ * (Pertaining to the MAC/PHY interface, not the line interface). -+ * For example: TBI or MII/GMII. -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * pif - one of SOC_PORT_IF_* -+ * Returns: -+ * SOC_E_XXX -+ */ -+int -+phy5461_ge_interface_set(uint eth_num, uint phyaddr, soc_port_if_t pif) -+{ -+ uint16 mii_ecr; -+ int mii; /* MII if true, TBI otherwise */ -+ -+ switch (pif) { -+ case SOC_PORT_IF_MII: -+ case SOC_PORT_IF_GMII: -+ case SOC_PORT_IF_SGMII: -+ mii = TRUE; -+ break; -+ case SOC_PORT_IF_NOCXN: -+ return (SOC_E_NONE); -+ case SOC_PORT_IF_TBI: -+ mii = FALSE; -+ break; -+ default: -+ return SOC_E_UNAVAIL; -+ } -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); -+ -+ if (mii) { -+ mii_ecr &= ~MII_ECR_10B; -+ } else { -+ mii_ecr |= MII_ECR_10B; -+ } -+ -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); -+ -+ return(SOC_E_NONE); -+} -+ -+ -+/* -+ * Function: -+ * phy5461_ge_init -+ * Purpose: -+ * Initialize the PHY (MII mode) to a known good state. -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * Returns: -+ * SOC_E_XXX -+ -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5461_ge_init(uint eth_num, uint phyaddr) -+{ -+ uint16 mii_ctrl, mii_gb_ctrl; -+ uint16 mii_ana; -+ soc_port_if_t pif; -+ -+ /* Reset PHY */ -+ phy5461_ge_reset(eth_num, phyaddr); -+ -+ /* set advertized bits */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ mii_ana |= MII_ANA_FD_100 | MII_ANA_FD_10; -+ mii_ana |= MII_ANA_HD_100 | MII_ANA_HD_10; -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ -+ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; -+ mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; -+ -+ pif = SOC_PORT_IF_GMII; -+ -+ phy5461_ge_interface_set(eth_num, phyaddr, pif); -+ -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return(SOC_E_NONE); -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * phy5461_ge_speed_set -+ * Purpose: -+ * Set the current operating speed (forced). -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * duplex - (OUT) Boolean, true indicates full duplex, false -+ * indicates half. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. Autonegotiation is -+ * not manipulated. -+ */ -+int -+phy5461_ge_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ uint16 mii_ctrl; -+ -+ if (speed == 0) { -+ return SOC_E_NONE; -+ } -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ mii_ctrl &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); -+ switch(speed) { -+ case 10: -+ mii_ctrl |= MII_CTRL_SS_10; -+ break; -+ case 100: -+ mii_ctrl |= MII_CTRL_SS_100; -+ break; -+ case 1000: -+ mii_ctrl |= MII_CTRL_SS_1000; -+ break; -+ default: -+ return SOC_E_CONFIG; -+ } -+ -+ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return SOC_E_NONE; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+void -+phy5461_reset_setup(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ phy5461_ge_init(eth_num, phyaddr); -+ -+ /* copper regs */ -+ /* remove power down */ -+ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, 0, MII_CTRL_PD); -+ /* Disable super-isolate */ -+ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_POWER_CTRLr_FLAGS, PHY_MII_POWER_CTRLr_BANK, PHY_MII_POWER_CTRLr_ADDR, 0, 1U<<5); -+ /* Enable extended packet length */ -+ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_AUX_CTRLr_FLAGS, PHY_MII_AUX_CTRLr_BANK, PHY_MII_AUX_CTRLr_ADDR, 0x4000, 0x4000); -+ -+ /* Configure interface to MAC */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); -+ /* phy5461_ge_init has reset the phy, powering down the unstrapped interface */ -+ /* make sure enabled interfaces are powered up */ -+ /* SGMII (passthrough fiber) or GMII fiber regs */ -+ tmp &= ~MII_CTRL_PD; /* remove power down */ -+ /* -+ * Enable SGMII autonegotiation on the switch side so that the -+ * link status changes are reflected in the switch. -+ * On Bradley devices, LAG failover feature depends on the SerDes -+ * link staus to activate failover recovery. -+ */ -+ tmp |= MII_CTRL_AE; -+ phy5461_wr_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); -+ -+ return; -+} -+ -+ -+/* -+ * Function: -+ * phy5461_init -+ * Purpose: -+ * Initialize xgxs6 phys -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * Returns: -+ * 0 -+ */ -+int -+phy5461_init(uint eth_num, uint phyaddr) -+{ -+ uint16 phyid0, phyid1; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_FLAGS, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_FLAGS, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); -+ -+ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); -+ -+ phy5461_reset_setup(eth_num, phyaddr); -+ -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * phy5461_link_get -+ * Purpose: -+ * Determine the current link up/down status -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5461_link_get(uint eth_num, uint phyaddr, int *link) -+{ -+ uint16 mii_ctrl, mii_stat; -+ uint32 wait; -+ -+ *link = FALSE; /* Default */ -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ /* the first read of status register will not show link up, second read will show link up */ -+ if (!(mii_stat & MII_STAT_LA) ) { -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ } -+ -+ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { -+ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ -+ return SOC_E_NONE; -+ } -+ -+ /* Link appears to be up; we are done if autoneg is off. */ -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ if (!(mii_ctrl & MII_CTRL_AE)) { -+ *link = TRUE; -+ return SOC_E_NONE; -+ } -+ -+ /* -+ * If link appears to be up but autonegotiation is still in -+ * progress, wait for it to complete. For BCM5228, autoneg can -+ * still be busy up to about 200 usec after link is indicated. Also -+ * continue to check link state in case it goes back down. -+ */ -+ for (wait=0; wait<50000; wait++) { -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (!(mii_stat & MII_STAT_LA)) { -+ /* link is down */ -+ return SOC_E_NONE; -+ } -+ -+ if (mii_stat & MII_STAT_AN_DONE) { -+ /* AutoNegotiation done */ -+ break; -+ } -+ -+ OSL_DELAY(10); -+ } -+ if (wait>=50000) { -+ /* timeout */ -+ return SOC_E_BUSY; -+ } -+ -+ /* Return link state at end of polling */ -+ *link = ((mii_stat & MII_STAT_LA) != 0); -+ -+ return SOC_E_NONE; -+} -+ -+ -+/* -+ * Function: -+ * phy5461_enable_set -+ * Purpose: -+ * Enable/Disable phy -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * enable - on/off state to set -+ * Returns: -+ * 0 -+ */ -+int -+phy5461_enable_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 power_down; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ power_down = (enable) ? 0 : MII_CTRL_PD; -+ -+ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, power_down, MII_CTRL_PD); -+ -+ return SOC_E_NONE; -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * phy5461_speed_set -+ * Purpose: -+ * Set PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5461_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5461_ge_speed_set(eth_num, phyaddr, speed); -+ -+ return 0; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+/* -+ * Function: -+ * phy5461_auto_negotiate_gcd (greatest common denominator). -+ * Purpose: -+ * Determine the current greatest common denominator between -+ * two ends of a link -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * speed - (OUT) greatest common speed. -+ * duplex - (OUT) greatest common duplex. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+static int -+phy5461_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int t_speed, t_duplex; -+ uint16 mii_ana, mii_anp, mii_stat; -+ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; -+ -+ mii_gb_stat = 0; /* Start off 0 */ -+ mii_gb_ctrl = 0; /* Start off 0 */ -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_FLAGS, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ -+ /* -+ * If the PHY supports extended status, check if it is 1000MB -+ * capable. If it is, check the 1000Base status register to see -+ * if 1000MB negotiated. -+ */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_FLAGS, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); -+ -+ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | -+ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_FLAGS, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); -+ } -+ } -+ -+ /* -+ * At this point, if we did not see Gig status, one of mii_gb_stat or -+ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to -+ * fail and fall into the default 10/100 cases. -+ */ -+ -+ mii_ana &= mii_anp; -+ -+ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { -+ t_speed = 1000; -+ t_duplex = 1; -+ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { -+ t_speed = 1000; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ -+ t_speed = 100; -+ t_duplex = 1; -+ } else if (mii_ana & MII_ANA_T4) { /* [b] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ -+ t_speed = 10; -+ t_duplex = 1 ; -+ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ -+ t_speed = 10; -+ t_duplex = 0; -+ } else { -+ return(SOC_E_FAIL); -+ } -+ -+ if (speed) *speed = t_speed; -+ if (duplex) *duplex = t_duplex; -+ -+ return(SOC_E_NONE); -+} -+ -+ -+/* -+ * Function: -+ * phy5461_speed_get -+ * Purpose: -+ * Get PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - current link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int rv; -+ uint16 mii_ctrl, mii_stat; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ *speed = 0; -+ *duplex = 0; -+ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ -+ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ -+ rv = SOC_E_NONE; -+ } else { -+ rv = phy5461_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); -+ } -+ } else { /* Auto-negotiation disabled */ -+ /* -+ * Simply pick up the values we force in CTRL register. -+ */ -+ if (mii_ctrl & MII_CTRL_FD) -+ *duplex = 1; -+ -+ switch(MII_CTRL_SS(mii_ctrl)) { -+ case MII_CTRL_SS_10: -+ *speed = 10; -+ break; -+ case MII_CTRL_SS_100: -+ *speed = 100; -+ break; -+ case MII_CTRL_SS_1000: -+ *speed = 1000; -+ break; -+ default: /* Just pass error back */ -+ return(SOC_E_UNAVAIL); -+ } -+ rv = SOC_E_NONE; -+ } -+ -+ return(rv); -+} -+ -+ -+#ifdef BCMINTERNAL -+int -+phy5461_lb_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 mii_ctrl; -+ -+ /* set reset flag */ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ mii_ctrl &= ~MII_CTRL_LE; -+ mii_ctrl |= enable ? MII_CTRL_LE : 0; -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return 0; -+} -+ -+ -+void -+phy5461_disp_status(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0, tmp1, tmp2; -+ int speed, duplex; -+ -+ printf("et%d: %s: phyaddr:%d\n", eth_num, __FUNCTION__, phyaddr); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &tmp1); -+ printf(" MII-Control: 0x%x; MII-Status: 0x%x\n", tmp0, tmp1); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_FLAGS, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_FLAGS, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &tmp1); -+ printf(" Phy ChipID: 0x%04x:0x%04x\n", tmp0, tmp1); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_FLAGS, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &tmp1); -+ phy5461_speed_get(eth_num, phyaddr, &speed, &duplex); -+ printf(" AutoNeg Ad: 0x%x; AutoNeg Partner: 0x%x; speed:%d; duplex:%d\n", tmp0, tmp1, speed, duplex); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_FLAGS, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &tmp1); -+ printf(" MII GB ctrl: 0x%x; MII GB stat: 0x%x\n", tmp0, tmp1); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_FLAGS, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &tmp1); -+ phy5461_rd_reg(eth_num, phyaddr, 0x00, 0x0000, 0x11, &tmp2); -+ printf(" IEEE Ext stat: 0x%x; PHY Ext ctrl: 0x%x; PHY Ext stat: 0x%x\n", tmp0, tmp1, tmp2); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_MODE_CTRLr_FLAGS, PHY_MODE_CTRLr_BANK, PHY_MODE_CTRLr_ADDR, &tmp0); -+ printf(" Mode Control (Addr 1c shadow 1f): 0x%x\n", tmp0); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, 0x01, &tmp1); -+ printf(" 1000-x MII ctrl: 0x%x; 1000-x MII stat: 0x%x\n", tmp0, tmp1); -+ -+ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, 0x04, &tmp0); -+ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, 0x05, &tmp1); -+ printf(" 1000-x AutoNeg Ad: 0x%x; 1000-x AutoNeg Partner: 0x%x\n", tmp0, tmp1); -+ -+} -+#endif /* BCMINTERNAL */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5481.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5481.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5481.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_phy5481.c 2017-11-09 17:53:44.028289000 +0800 -@@ -0,0 +1,728 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+#include -+#include "../../../mdio/iproc_mdio.h" -+#include "bcmiproc_phy.h" -+#include "bcmiproc_phy5481.h" -+ -+/* ---- External Variable Declarations ----------------------------------- */ -+/* ---- External Function Prototypes ------------------------------------- */ -+/* ---- Public Variables ------------------------------------------------- */ -+/* ---- Private Constants and Types -------------------------------------- */ -+/* ---- Private Variables ------------------------------------------------ */ -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+ -+/* ==== Public Functions ================================================= */ -+ -+int -+phy5481_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ int rv = SOC_E_NONE; -+ uint16 wr_data=*data; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data)); -+ -+ switch(reg_addr) { -+ /* Map shadow registers */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ if (reg_bank == 0x0007) { -+ wr_data |= 0x8000; -+ } -+ wr_data = (wr_data & ~(0x0007)) | reg_bank; -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x000F) { -+ wr_data = 0x8000 | (reg_bank << 10) | (wr_data & 0x03FF); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ default: -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ } -+ -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); -+ } -+ -+ return rv; -+} -+ -+ -+int -+phy5481_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 *data) -+{ -+ int rv = SOC_E_NONE; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to read phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr)); -+ -+ switch(reg_addr) { -+ /* Map shadow registers */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x00F) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ default: -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ } -+ -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, *data)); -+ } -+ -+ return rv; -+} -+ -+ -+int -+phy5481_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, -+ uint8 reg_addr, uint16 data, uint16 mask) -+{ -+ int rv = SOC_E_NONE; -+ uint16 org_data, rd_data; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, data, mask)); -+ -+ switch(reg_addr) { -+ /* Map shadow registers */ -+ case 0x18: -+ if (reg_bank <= 0x0007) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); -+ if (reg_bank == 0x0007) { -+ data |= 0x8000; -+ mask |= 0x8000; -+ } -+ mask &= ~(0x0007); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ case 0x1C: -+ if (reg_bank <= 0x001F) { -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); -+ data |= 0x8000; -+ mask |= 0x8000; -+ mask &= ~(0x1F << 10); -+ } else { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ default: -+ if (reg_addr > 0x001e) { -+ rv = SOC_E_PARAM; -+ } -+ break; -+ } -+ -+ if (SOC_SUCCESS(rv)) { -+ iproc_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ org_data = rd_data; -+ rd_data &= ~(mask); -+ rd_data |= data; -+ iproc_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); -+ } -+ -+ return rv; -+} -+ -+void -+phy5481_ge_reset(uint eth_num, uint phyaddr) -+{ -+ uint16 ctrl; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ /* set reset flag */ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ ctrl |= MII_CTRL_RESET; -+ phy5481_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ -+ SPINWAIT( (!phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) -+ && (ctrl & MII_CTRL_RESET)), 100000); -+ /* check if out of reset */ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); -+ if (ctrl & MII_CTRL_RESET) { -+ /* timeout */ -+ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); -+ } else { -+ NET_ERROR(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); -+ } -+ -+ return; -+} -+ -+ -+/* -+ * Function: -+ * phy5481_ge_init -+ * Purpose: -+ * Initialize the PHY (MII mode) to a known good state. -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * Returns: -+ * SOC_E_XXX -+ -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5481_ge_init(uint eth_num, uint phyaddr) -+{ -+ uint16 mii_ana, mii_ctrl, mii_gb_ctrl; -+ -+ /* Reset PHY */ -+ phy5481_ge_reset(eth_num, phyaddr); -+ -+ /* set advertized bits */ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ mii_ana |= MII_ANA_FD_100 | MII_ANA_FD_10; -+ mii_ana |= MII_ANA_HD_100 | MII_ANA_HD_10; -+ phy5481_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ -+ -+ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; -+ mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; -+ -+ phy5481_wr_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); -+ phy5481_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ -+ return SOC_E_NONE; -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * phy5481_ge_speed_set -+ * Purpose: -+ * Set the current operating speed (forced). -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * duplex - (OUT) Boolean, true indicates full duplex, false -+ * indicates half. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. Autonegotiation is -+ * not manipulated. -+ */ -+int -+phy5481_ge_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ uint16 mii_ctrl; -+ -+ if (speed == 0) { -+ return SOC_E_NONE; -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ mii_ctrl &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); -+ switch(speed) { -+ case 10: -+ mii_ctrl |= MII_CTRL_SS_10; -+ break; -+ case 100: -+ mii_ctrl |= MII_CTRL_SS_100; -+ break; -+ case 1000: -+ mii_ctrl |= MII_CTRL_SS_1000; -+ break; -+ default: -+ return SOC_E_CONFIG; -+ } -+ -+ phy5481_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return SOC_E_NONE; -+} -+#endif /* BCMINTERNAL */ -+ -+void -+phy5481_reset_setup(uint eth_num, uint phyaddr) -+{ -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ phy5481_ge_init(eth_num, phyaddr); -+ -+ /* copper regs */ -+ /* remove power down */ -+ phy5481_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, 0, MII_CTRL_PD); -+ /* Disable super-isolate */ -+ phy5481_mod_reg(eth_num, phyaddr, PHY_MII_POWER_CTRLr_BANK, PHY_MII_POWER_CTRLr_ADDR, 0, PHY5481_SUPER_ISOLATE_MODE); -+ /* Enable extended packet length */ -+ phy5481_mod_reg(eth_num, phyaddr, PHY_MII_AUX_CTRLr_BANK, PHY_MII_AUX_CTRLr_ADDR, 0x4000, 0x4000); -+ -+ return; -+} -+ -+ -+/* -+ * Function: -+ * phy5481_init -+ * Purpose: -+ * Initialize xgxs6 phys -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * Returns: -+ * 0 -+ */ -+int -+phy5481_init(uint eth_num, uint phyaddr) -+{ -+ uint16 phyid0, phyid1; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); -+ -+ printf("%s phyaddr(0x%x) Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyaddr, phyid1, phyid0); -+ -+ phy5481_reset_setup(eth_num, phyaddr); -+ -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * phy5481_link_get -+ * Purpose: -+ * Determine the current link up/down status -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+int -+phy5481_link_get(uint eth_num, uint phyaddr, int *link) -+{ -+ uint16 mii_ctrl, mii_stat; -+ uint32 wait; -+ -+ *link = FALSE; /* Default */ -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ /* the first read of status register will not show link up, second read will show link up */ -+ if (!(mii_stat & MII_STAT_LA) ) { -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ } -+ -+ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { -+ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ -+ return SOC_E_NONE; -+ } -+ -+ /* Link appears to be up; we are done if autoneg is off. */ -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ if (!(mii_ctrl & MII_CTRL_AE)) { -+ *link = TRUE; -+ return SOC_E_NONE; -+ } -+ -+ /* -+ * If link appears to be up but autonegotiation is still in -+ * progress, wait for it to complete. For BCM5228, autoneg can -+ * still be busy up to about 200 usec after link is indicated. Also -+ * continue to check link state in case it goes back down. -+ * wait 500ms (500000us/10us = 50000 ) -+ */ -+ for (wait=0; wait<50000; wait++) { -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (!(mii_stat & MII_STAT_LA)) { -+ /* link is down */ -+ return SOC_E_NONE; -+ } -+ -+ if (mii_stat & MII_STAT_AN_DONE) { -+ /* AutoNegotiation done */ -+ break; -+ } -+ -+ OSL_DELAY(10); -+ } -+ if (wait>=50000) { -+ /* timeout */ -+ return SOC_E_BUSY; -+ } -+ -+ /* Return link state at end of polling */ -+ *link = ((mii_stat & MII_STAT_LA) != 0); -+ -+ return SOC_E_NONE; -+} -+ -+/* -+ * Function: -+ * phy5481_enable_set -+ * Purpose: -+ * Enable/Disable phy -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * enable - on/off state to set -+ * Returns: -+ * 0 -+ */ -+int -+phy5481_enable_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 power_down; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ power_down = (enable) ? 0 : MII_CTRL_PD; -+ -+ phy5481_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, power_down, MII_CTRL_PD); -+ -+ return SOC_E_NONE; -+} -+ -+ -+#ifdef BCMINTERNAL -+ -+/* -+ * Function: -+ * phy5481_speed_set -+ * Purpose: -+ * Set PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5481_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5481_ge_speed_set(eth_num, phyaddr, speed); -+ -+ return 0; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+/* -+ * Function: -+ * phy5481_auto_negotiate_gcd (greatest common denominator). -+ * Purpose: -+ * Determine the current greatest common denominator between -+ * two ends of a link -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * speed - (OUT) greatest common speed. -+ * duplex - (OUT) greatest common duplex. -+ * link - (OUT) Boolean, true indicates link established. -+ * Returns: -+ * SOC_E_XXX -+ * Notes: -+ * No synchronization performed at this level. -+ */ -+static int -+phy5481_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int t_speed, t_duplex; -+ uint16 mii_ana, mii_anp, mii_stat; -+ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; -+ -+ mii_gb_stat = 0; /* Start off 0 */ -+ mii_gb_ctrl = 0; /* Start off 0 */ -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ -+ /* -+ * If the PHY supports extended status, check if it is 1000MB -+ * capable. If it is, check the 1000Base status register to see -+ * if 1000MB negotiated. -+ */ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); -+ -+ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | -+ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); -+ } -+ } -+ -+ /* -+ * At this point, if we did not see Gig status, one of mii_gb_stat or -+ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to -+ * fail and fall into the default 10/100 cases. -+ */ -+ -+ mii_ana &= mii_anp; -+ -+ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { -+ t_speed = 1000; -+ t_duplex = 1; -+ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && -+ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { -+ t_speed = 1000; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ -+ t_speed = 100; -+ t_duplex = 1; -+ } else if (mii_ana & MII_ANA_T4) { /* [b] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ -+ t_speed = 100; -+ t_duplex = 0; -+ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ -+ t_speed = 10; -+ t_duplex = 1 ; -+ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ -+ t_speed = 10; -+ t_duplex = 0; -+ } else { -+ return(SOC_E_FAIL); -+ } -+ -+ if (speed) *speed = t_speed; -+ if (duplex) *duplex = t_duplex; -+ -+ return(SOC_E_NONE); -+} -+ -+ -+/* -+ * Function: -+ * phy5481_speed_get -+ * Purpose: -+ * Get PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - current link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+phy5481_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) -+{ -+ int rv; -+ uint16 mii_ctrl, mii_stat; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); -+ -+ *speed = 0; -+ *duplex = 0; -+ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ -+ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ -+ rv = SOC_E_NONE; -+ } else { -+ rv = phy5481_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); -+ } -+ } else { /* Auto-negotiation disabled */ -+ /* -+ * Simply pick up the values we force in CTRL register. -+ */ -+ if (mii_ctrl & MII_CTRL_FD) -+ *duplex = 1; -+ -+ switch(MII_CTRL_SS(mii_ctrl)) { -+ case MII_CTRL_SS_10: -+ *speed = 10; -+ break; -+ case MII_CTRL_SS_100: -+ *speed = 100; -+ break; -+ case MII_CTRL_SS_1000: -+ *speed = 1000; -+ break; -+ default: /* Just pass error back */ -+ return(SOC_E_UNAVAIL); -+ } -+ rv = SOC_E_NONE; -+ } -+ -+ return(rv); -+} -+ -+ -+#ifdef BCMINTERNAL -+int -+phy5481_lb_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 mii_ctrl; -+ -+ /* set reset flag */ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ mii_ctrl &= ~MII_CTRL_LE; -+ mii_ctrl |= enable ? MII_CTRL_LE : 0; -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); -+ -+ return 0; -+} -+#endif /* BCMINTERNAL */ -+ -+ -+#ifdef BCMINTERNAL -+void -+phy5481_disp_status(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0, tmp1, tmp2; -+ int speed, duplex; -+ -+ printf("et%d: %s: phyaddr:%d\n", eth_num, __FUNCTION__, phyaddr); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &tmp0); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &tmp1); -+ printf(" MII-Control: 0x%x; MII-Status: 0x%x\n", tmp0, tmp1); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &tmp0); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &tmp1); -+ printf(" Phy ChipID: 0x%04x:0x%04x\n", tmp0, tmp1); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &tmp0); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &tmp1); -+ phy5481_speed_get(eth_num, phyaddr, &speed, &duplex); -+ printf(" AutoNeg Ad: 0x%x; AutoNeg Partner: 0x%x; speed:%d; duplex:%d\n", tmp0, tmp1, speed, duplex); -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &tmp0); -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &tmp1); -+ phy5481_rd_reg(eth_num, phyaddr, 0x0000, 0x11, &tmp2); -+ printf(" Reg0x0f: 0x%x; 100Base-X AUX ctrl: 0x%x; 100Base-X AUX stat: 0x%x\n", tmp0, tmp1, tmp2); -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0x0000, 0x12, &tmp0); -+ phy5481_rd_reg(eth_num, phyaddr, 0x0000, 0x13, &tmp1); -+ phy5481_rd_reg(eth_num, phyaddr, 0x0000, 0x14, &tmp2); -+ printf(" 100Base-X RCV ERR: 0x%x; 100Base-X FALSE CARRIER: 0x%x; 100Base-X DISCON: 0x%x\n", tmp0, tmp1, tmp2); -+} -+#endif /* BCMINTERNAL */ -+ -+ -+#ifdef BCMINTERNAL -+void -+phy5481_chk_err(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0; -+ -+ phy5481_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &tmp0); -+ if (!(tmp0 & MII_STAT_LA)) -+ printf("ERROR: reg 0x01 (LINK down): 0x%x\n", tmp0); -+ if (tmp0 & (MII_STAT_JBBR|MII_STAT_RF)) { -+ printf("ERROR: reg 0x01: 0x%x\n", tmp0); -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0, 0x11, &tmp0); -+ if (!(tmp0 & 0x100)) { -+ printf("ERROR: reg 0x11 (LINK down): 0x%x\n", tmp0); -+ } -+ if (tmp0 & 0x8bf) { -+ printf("ERROR: reg 0x11: 0x%x\n", tmp0); -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0, 0x12, &tmp0); -+ if (tmp0) { -+ printf("ERROR: reg 0x12 (RCV ERR CNT): 0x%x\n", tmp0); -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0, 0x13, &tmp0); -+ if (tmp0) { -+ printf("ERROR: reg 0x13 (FALSE CARRIER CNT): 0x%x\n", tmp0); -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0, 0x14, &tmp0); -+ if (tmp0 & 0xc000) { -+ printf("ERROR: reg 0x14: 0x%x\n", tmp0); -+ } -+ -+ phy5481_rd_reg(eth_num, phyaddr, 0, 0x19, &tmp0); -+ if (!(tmp0 & 0x4)) { -+ printf("ERROR: reg 0x19 (LINK down): 0x%x\n", tmp0); -+ } -+ if (tmp0 & 0xc0) { -+ printf("ERROR: reg 0x19: 0x%x\n", tmp0); -+ } -+} -+#endif /* BCMINTERNAL */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_serdes.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_serdes.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_serdes.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmiproc_serdes.c 2017-11-09 17:53:44.029293000 +0800 -@@ -0,0 +1,879 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the serdes -+ * -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+#include -+#include "bcmiproc_serdes.h" -+#include "bcmiproc_serdes_def.h" -+#include "../../../mdio/iproc_mdio.h" -+ -+/* ---- External Variable Declarations ----------------------------------- */ -+/* ---- External Function Prototypes ------------------------------------- */ -+/* ---- Public Variables ------------------------------------------------- */ -+/* ---- Private Constants and Types -------------------------------------- */ -+/* ---- Private Variables ------------------------------------------------ */ -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+ -+#if defined(CONFIG_MACH_SB2) -+/* CL22 register access for VIPERCORE in Saber2 */ -+#define PHY_AER_REG_ADDR_AER(_addr) (((_addr) >> 16) & 0x0000FFFF) -+#define PHY_AER_REG_ADDR_BLK(_addr) (((_addr) & 0x0000FFF0)) -+#define PHY_AER_REG_ADDR_REGAD(_addr) ((((_addr) & 0x00008000) >> 11) | \ -+ ((_addr) & 0x0000000F)) -+#endif -+ -+/* ==== Public Functions ================================================= */ -+ -+void -+serdes_set_blk(uint eth_num, uint phyaddr, uint blk) -+{ -+ uint16 blkaddr; -+ uint16 destblk = (uint16)blk; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ NET_REG_TRACE(("%s phyaddr(0x%x) blk(0x%x)\n", -+ __FUNCTION__, phyaddr, blk)); -+ -+ /* check if need to update blk addr */ -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, &blkaddr); -+ if (blkaddr!=destblk) { -+ /* write block address */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, destblk); -+ } -+} -+ -+ -+void -+serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data) -+{ -+ uint16 tmpdata=(uint16)data; -+#if defined(CONFIG_MACH_SB2) -+ uint16 phy_reg_aer = 0, phy_reg_blk = 0, phy_reg_addr = 0; -+ -+ phy_reg_aer = PHY_AER_REG_ADDR_AER(reg); /* upper 16 bits */ -+ phy_reg_blk = PHY_AER_REG_ADDR_BLK(reg); /* 12 bits mask=0xfff0 */ -+ phy_reg_addr = PHY_AER_REG_ADDR_REGAD(reg); /* 5 bits {15,3,2,1,0} */ -+ -+ if (phy_reg_aer != 0) { -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, phy_reg_aer); -+ } -+ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, phy_reg_blk); /* Map block */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, phy_reg_addr, tmpdata); /* write register */ -+ -+ if (phy_reg_aer != 0) { -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x0); -+ } -+#else -+ uint blk = reg&0x7ff0; -+ uint off = reg&0x000f; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ if (reg&0x8000) -+ off|=0x10; -+ -+ /* set block address */ -+ serdes_set_blk(eth_num, phyaddr, blk); -+ -+ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg, tmpdata)); -+ //printf("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", -+ // __FUNCTION__, phyaddr, reg, tmpdata); -+ /* write register */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, off, tmpdata); -+#endif -+} -+ -+ -+uint16 -+serdes_rd_reg(uint eth_num, uint phyaddr, uint reg) -+{ -+ uint16 data; -+#if defined(CONFIG_MACH_SB2) -+ uint16 phy_reg_aer = 0, phy_reg_blk = 0, phy_reg_addr = 0; -+ -+ phy_reg_aer = PHY_AER_REG_ADDR_AER(reg); /* upper 16 bits */ -+ phy_reg_blk = PHY_AER_REG_ADDR_BLK(reg); /* 12 bits mask=0xfff0 */ -+ phy_reg_addr = PHY_AER_REG_ADDR_REGAD(reg); /* 5 bits {15,3,2,1,0} */ -+ -+ if (phy_reg_aer != 0) { -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, phy_reg_aer); -+ } -+ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, phy_reg_blk); /* Map block */ -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, phy_reg_addr, &data); /* read register */ -+ -+ if (phy_reg_aer != 0) { -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x0); -+ } -+#else -+ uint blk = reg&0x7ff0; -+ uint off = reg&0x000f; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ if (reg&0x8000) -+ off|=0x10; -+ -+ /* set block address */ -+ serdes_set_blk(eth_num, phyaddr, blk); -+ -+ /* read register */ -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, off, &data); -+ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", -+ __FUNCTION__, phyaddr, reg, data)); -+ //printf("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", -+ // __FUNCTION__, phyaddr, reg, data); -+#endif -+ -+ return data; -+} -+ -+ -+uint16 -+serdes_get_id(uint eth_num, uint phyaddr, uint off) -+{ -+ -+ ASSERT(phyaddr < MAXEPHY); -+ -+ if (phyaddr == EPHY_NOREG) -+ return 0; -+ -+ /* read the id high */ -+ return serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID0r+off); -+} -+ -+ -+void -+serdes_reset(uint eth_num, uint phyaddr) -+{ -+ uint16 ctrl; -+ -+ ASSERT(phyaddr < MAXEPHY); -+ -+ if (phyaddr == EPHY_NOREG) -+ return; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ /* set reset flag */ -+ ctrl = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); -+ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r, ctrl); -+ udelay(100); -+ /* check if out of reset */ -+ if (serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r) & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { -+ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); -+ } -+} -+ -+ -+int -+serdes_reset_core(uint eth_num, uint phyaddr) -+{ -+ uint16 data16; -+ uint16 serdes_id2; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ /* get serdes id */ -+ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); -+ printf("et%d %s pbyaddr(0x%x) id2(0x%x)\n", eth_num, __FUNCTION__, phyaddr, serdes_id2); -+ -+ /* unlock lane */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, WC40_DIGITAL4_MISC3r); -+ data16 &= ~(DIGITAL4_MISC3_LANEDISABLE_MASK); -+ serdes_wr_reg(eth_num, phyaddr, WC40_DIGITAL4_MISC3r, data16); -+ -+ if ( phyaddr == 1 ) { -+ /* Reset the core */ -+ /* Stop PLL Sequencer and configure the core into correct mode */ -+ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << -+ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | -+ XGXSBLK0_XGXSCONTROL_HSTL_MASK | -+ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | -+ XGXSBLK0_XGXSCONTROL_EDEN_MASK | -+ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | -+ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); -+ -+ /* Disable IEEE block select auto-detect. -+ * The driver will select desired block as necessary. -+ * By default, the driver keeps the XAUI block in -+ * IEEE address space. -+ */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); -+ if (XGXS16G_2p5G_ID(serdes_id2)) { -+ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | -+ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); -+ } else { -+ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | -+ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); -+#if (!defined(CONFIG_MACH_KT2)) -+ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; -+#endif /* (!defined(CONFIG_MACH_KT2)) */ -+ } -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r, data16); -+ -+ /* disable in-band MDIO. PHY-443 */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8111); -+ /* rx_inBandMdio_rst */ -+ data16 |= 1 << 3; -+ serdes_wr_reg(eth_num, phyaddr, 0x8111, data16); -+ } -+ return 0; -+} -+ -+ -+int -+serdes_start_pll(uint eth_num, uint phyaddr) -+{ -+ uint16 data16; -+ -+ if ( phyaddr == 1 ) { -+ uint32 count=250; -+ /* Start PLL Sequencer and wait for PLL to lock */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); -+ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); -+ -+ /* wait for PLL to lock */ -+ while (count!=0) { -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSSTATUSr); -+ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { -+ break; -+ } -+ /* wait 1 usec then dec counter */ -+ udelay(10); -+ count--; -+ } -+ if (count == 0) { -+ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); -+ } -+ } -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * serdes_init -+ * Purpose: -+ * Initialize xgxs6 phys -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * Returns: -+ * 0 -+ */ -+int -+serdes_init(uint eth_num, uint phyaddr) -+{ -+#if defined(CONFIG_MACH_SB2) -+ -+#if 0 -+ /* Speed = 10M */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0c2f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8300); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0120); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0000); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x1100); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x0100); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x2c2f); -+#endif -+ -+#if 0 -+ /* Speed = 100M */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0c2f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8300); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0120); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0000); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x3100); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x2100); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x2c2f); -+#endif -+ -+#if 0 -+ /* Speed = 1G SGMII */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0c2f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8300); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0120); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0000); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x1140); /* Mode = AN */ -+ // iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x0140); /* Mode = Force */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x2c3f); -+#endif -+ -+#if 1 -+ /* Auto Negotiation 10M/100M/1G ¡V SGMII Slave */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0c2f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8300); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0100); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x1140); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x2c3f); -+#endif -+ -+#else -+ -+ uint16 data16; -+ uint16 serdes_id0, serdes_id1, serdes_id2; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ /* get serdes id */ -+ serdes_id0 = serdes_get_id(eth_num, phyaddr, 0); -+ serdes_id1 = serdes_get_id(eth_num, phyaddr, 1); -+ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); -+ printf("%s phyaddr(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1, serdes_id2); -+ -+ /* get more ids */ -+ serdes_id0 = serdes_rd_reg(eth_num, phyaddr, 2); -+ serdes_id1 = serdes_rd_reg(eth_num, phyaddr, 3); -+ //printf("%s phyaddr(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1); -+ -+ /* unlock lane */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, WC40_DIGITAL4_MISC3r); -+ data16 &= ~(DIGITAL4_MISC3_LANEDISABLE_MASK); -+ serdes_wr_reg(eth_num, phyaddr, WC40_DIGITAL4_MISC3r, data16); -+ -+ /* disable CL73 BAM */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8372); -+ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); -+ serdes_wr_reg(eth_num, phyaddr, 0x8372, data16); -+ -+ /* Set Local Advertising Configuration */ -+ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_AUTONEGADVr, data16); -+ -+ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ -+ data16 = 0; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, data16); -+ -+ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | -+ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; -+ /* -+ * Put the Serdes in SGMII mode -+ * bit0 = 0; in SGMII mode -+ */ -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, data16); -+ -+ /* set autoneg */ -+ data16 = MII_CTRL_AE | MII_CTRL_RAN; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); -+ -+ /* Disable 10G parallel detect */ -+ data16 = 0; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_AN73_PDET_PARDET10GCONTROLr, data16); -+ -+ /* Disable BAM mode and Teton mode */ -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); -+ -+ /* Enable lanes */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r); -+ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | -+ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r, data16); -+ -+ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; -+ data16 |= (1 << 2); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); -+ -+ /* Enabble LPI passthru' for native mode EEE */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r); -+ data16 |= 0xc000; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r, data16); -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr); -+ data16 |= 0x0007; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr, data16); -+#endif -+ -+ return 0; -+} -+ -+ -+#ifdef BCMINTERNAL -+/* -+ * Function: -+ * serdes_enable_set -+ * Purpose: -+ * Enable/Disable phy -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * enable - on/off state to set -+ * Returns: -+ * 0 -+ */ -+int -+serdes_enable_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 data16, mask16; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL3r); -+ mask16 = (1 << (phyaddr-1)); /* rx lane */ -+ mask16 |= (mask16 << 4); /* add tx lane */ -+ mask16 |= 0x800; -+ if (enable) { -+ data16 &= ~(mask16); -+ } else { -+ data16 &= ~(mask16); -+ data16 |= mask16; -+ } -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL3r, data16); -+ -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * serdes_speed_set -+ * Purpose: -+ * Set PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+serdes_speed_set(uint eth_num, uint phyaddr, int speed) -+{ -+ uint16 speed_val, mask; -+ uint16 data16; -+ uint16 speed_mii; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ if (speed > 1000) { -+ return -1; -+ } -+ -+ speed_val = 0; -+ speed_mii = 0; -+ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | -+ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; -+ -+ switch (speed) { -+ case 0: -+ /* Do not change speed */ -+ return 0; -+ case 10: -+ speed_mii = MII_CTRL_SS_10; -+ break; -+ case 100: -+ speed_mii = MII_CTRL_SS_100; -+ break; -+ case 1000: -+ speed_mii = MII_CTRL_SS_1000; -+ break; -+ default: -+ return -1; -+ } -+ -+ /* Hold rxSeqStart */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); -+ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); -+ -+ /* hold TX FIFO in reset */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); -+ data16 &= ~(mask); -+ data16 |= speed_val; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); -+ data16 &= ~(MII_CTRL_AE | MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); -+ data16 |= speed_mii; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); -+ -+ /* release rxSeqStart */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); -+ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); -+ -+ /* release TX FIFO reset */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); -+ -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * serdes_speed_get -+ * Purpose: -+ * Get PHY speed -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - current link speed in Mbps -+ * Returns: -+ * 0 -+ */ -+int -+serdes_speed_get(uint eth_num, uint phyaddr, int *speed) -+{ -+ uint16 data16; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_STATUS1000X1r); -+ -+ data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK; -+ data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; -+ -+ if (data16 == 3) { -+ *speed= 2500; -+ } else if (data16 == 2) { -+ *speed= 1000; -+ } else if (data16 == 1) { -+ *speed= 100; -+ } else { -+ *speed= 10; -+ } -+ -+ return 0; -+} -+ -+ -+/* -+ * Function: -+ * phy_xgxs16g1l_lb_set -+ * Purpose: -+ * Put XGXS6/FusionCore in PHY loopback -+ * Parameters: -+ * unit - StrataSwitch unit #. -+ * port - StrataSwitch port #. -+ * enable - binary value for on/off (1/0) -+ * Returns: -+ * 0 -+ */ -+int -+serdes_lb_set(uint eth_num, uint phyaddr, int enable) -+{ -+ uint16 misc_ctrl, data16; -+ uint16 lb_bit; -+ uint16 lb_mask; -+ -+ /* Configure Loopback in XAUI */ -+ misc_ctrl = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); -+ if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK) { -+ /* PCS */ -+ lb_bit = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0; -+ lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK; -+ } else if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK) { -+ /* PMA/PMD */ -+ lb_bit = (enable) ? 1 : 0; -+ lb_mask = 1; -+ } else { -+ /* PHY XS, DTE XS */ -+ lb_bit = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0; -+ lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK; -+ } -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); -+ data16 &= ~(lb_mask); -+ data16 |= lb_bit; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r, data16); -+ -+ /* Configure Loopback in SerDes */ -+ lb_bit = (enable) ? MII_CTRL_LE : 0; -+ lb_mask = MII_CTRL_LE; -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); -+ data16 &= ~(lb_mask); -+ data16 |= lb_bit; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); -+ data16 |= 0x10; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8017); -+ data16 = 0xff0f; -+ serdes_wr_reg(eth_num, phyaddr, 0x8017, data16); -+ -+ return 0; -+} -+ -+void -+serdes_disp_status(uint eth_num, uint phyaddr) -+{ -+ uint16 tmp0, tmp1, tmp2, tmp3; -+ -+ printf("et%d: %s: phyaddr:%d\n", eth_num, __FUNCTION__, phyaddr); -+ -+ tmp0 = serdes_get_id(eth_num, phyaddr, 0); -+ tmp1 = serdes_get_id(eth_num, phyaddr, 1); -+ tmp2 = serdes_get_id(eth_num, phyaddr, 2); -+ printf(" id0(0x%x) id1(0x%x) id2(0x%x)\n", tmp0, tmp1, tmp2); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r+1); -+ printf(" MII-Control(0): 0x%x; MII-Status(1): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 2); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, 3); -+ printf(" Phy ChipID(2:3): 0x%04x:0x%04x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 4); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, 5); -+ tmp2 = serdes_rd_reg(eth_num, phyaddr, 0xf); -+ printf(" AN AD(4): 0x%x; AN LNK PARTNER(5): 0x%x; EXT STAT(f): 0x%x\n", tmp0, tmp1, tmp2); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSSTATUSr); -+ printf(" XGXS-Control(8000): 0x%x; XGXS-Status(8001): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MMDSELECTr); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); -+ printf(" XGXS BLK0 MMD Select(800d): 0x%x; XGXS BLK0 MISC CTRL(800e): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL3r); -+ printf(" XGXS BLK1 LNCTRL0(8015): 0x%x; XGXS BLK1_LNCTRL3(8018): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_AN73_PDET_PARDET10GCONTROLr); -+ tmp2 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr); -+ printf(" XGXS RX0 CTRL(80b1): 0x%x; XGXS AN73 PARDET CTRL(8131): 0x%x; XGXS BLK7 EEECTRL(8150): 0x%x\n", tmp0, tmp1, tmp2); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 0x8111); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, 0x8372); -+ printf(" (8111): 0x%x; (8372): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X1r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X2r); -+ tmp2 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ printf(" XGXS SERDES DIG CTRL 1000X1(8300): 0x%x; XGXS SERDES DIG CTRL 1000X2(8301): 0x%x; XGXS SERDES DIGITAL CTRL 1000X3r(8302): 0x%x\n", tmp0, tmp1, tmp2); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_STATUS1000X1r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); -+ printf(" XGXS SERDES DIG STATUS 1000X1(8304): 0x%x; XGXS SERDES DIG MISC1(8308): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID0r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID1r); -+ printf(" XGXS SERDESID0(8310): 0x%x; XGXS SERDESID1(8311): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID2r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID3r); -+ printf(" XGXS SERDESID0(8312): 0x%x; XGXS SERDESID1(8313): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC3r); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r); -+ printf(" XGXS REMOTEPHY MISC3(833c): 0x%x; XGXS REMOTEPHY MISC5(833e): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_UD_FIELDr); -+ printf(" XGXS BAM MP5_NEXTPAGECTRL(8350): 0x%x; XGXS BAM NP UD FIELDr(8357): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_AUTONEGADVr); -+ printf(" XGXS COMBO IEEE0 MIICNTL(ffe0): 0x%x; XGXS COMBO IEEE0 AUTONEGADVr(ffe4): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 0x8050); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, 0x8122); -+ printf(" (8050): 0x%x; (8122): 0x%x\n", tmp0, tmp1); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 0x80b0); -+ tmp1 = serdes_rd_reg(eth_num, phyaddr, 0x80c0); -+ tmp2 = serdes_rd_reg(eth_num, phyaddr, 0x80d0); -+ tmp3 = serdes_rd_reg(eth_num, phyaddr, 0x80e0); -+ printf(" (80b0): 0x%x; (80c0): 0x%x; (80d0): 0x%x, (80e0): 0x%x\n", tmp0, tmp1, tmp2, tmp3); -+ -+ tmp0 = serdes_rd_reg(eth_num, phyaddr, 0xffe1); -+ printf(" (ffe1): 0x%x\n", tmp0); -+ -+} -+#endif /* BCMINTERNAL */ -+ -+ -+#if (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) -+/* -+ * Function: -+ * serdes_speeddpx_set -+ * Purpose: -+ * Set serdes speed dpx -+ * Parameters: -+ * eth_num - ethernet data -+ * phyaddr - physical address -+ * speed - link speed in Mbps -+ * fulldpx - link dpx -+ * Returns: -+ * 0 -+ */ -+int -+serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx) -+{ -+ uint16 speed_val, mask; -+ uint16 data16; -+ uint16 speed_mii; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ if (speed > 1000) { -+ return -1; -+ } -+ -+ speed_val = 0; -+ speed_mii = 0; -+ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | -+ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; -+ -+ switch (speed) { -+ case 0: -+ /* Do not change speed */ -+ return 0; -+ case 10: -+ speed_mii = MII_CTRL_SS_10; -+ break; -+ case 100: -+ speed_mii = MII_CTRL_SS_100; -+ break; -+ case 1000: -+ speed_mii = MII_CTRL_SS_1000; -+ break; -+ default: -+ return -1; -+ } -+ -+ if (fulldpx) -+ speed_mii |= MII_CTRL_FD; -+ -+ /* Hold rxSeqStart */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); -+ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); -+ -+ /* hold TX FIFO in reset */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); -+ data16 &= ~(mask); -+ data16 |= speed_val; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); -+ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); -+ data16 &= ~(MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_SS_LSB | MII_CTRL_SS_MSB | MII_CTRL_FD); -+ data16 |= speed_mii; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); -+ -+ /* release rxSeqStart */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); -+ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); -+ -+ /* release TX FIFO reset */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); -+ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); -+ -+ return 0; -+} -+ -+int -+serdes_set_asym_mode(uint eth_num, uint phyaddr) -+{ -+ uint16 data16; -+ uint32 txclkctrlreg[] = {0x0000, 0x8065, 0x8075, 0x8085}; -+ uint32 rxclkctrlreg[] = {0x0000, 0x80bc, 0x80cc, 0x80dc}; -+ uint32 spd[] = {0x0000, 0x7120, 0x7120, 0x7110}; -+ uint32 clkctrlmsk[] = {0x0000, 0x0040, 0x0040, 0x0040}; -+ uint32 clkctrlval[] = {0x0000, 0x0040, 0x0040, 0x0000}; -+ -+ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); -+ -+ printk("et%d: %s: setting serdes asymmetrice mode\n", eth_num, __FUNCTION__); -+ -+ /* set speed */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); -+ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); -+ data16 &= 0x0f00; -+ data16 |= spd[phyaddr]; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); -+ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); -+ -+ /* Enable asymmetric mode */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r); -+ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); -+ data16 |= 0x0100; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r, data16); -+ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); -+ -+ /* set tx clock control bit */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, txclkctrlreg[phyaddr]); -+ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); -+ data16 &= ~(clkctrlmsk[phyaddr]); -+ data16 |= clkctrlval[phyaddr]; -+ serdes_wr_reg(eth_num, phyaddr, txclkctrlreg[phyaddr], data16); -+ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); -+ -+ /* set rx clock control bit */ -+ data16 = serdes_rd_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr]); -+ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); -+ data16 &= ~(clkctrlmsk[phyaddr]); -+ data16 |= clkctrlval[phyaddr]; -+ serdes_wr_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr], data16); -+ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); -+ -+ data16 = 0xffff; -+ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL1r, data16); -+ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_XGXSBLK1_LANECTRL1r); -+ -+ return 0; -+} -+ -+#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmutils.c b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmutils.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/bcmutils.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/bcmutils.c 2017-11-09 17:53:44.032290000 +0800 -@@ -0,0 +1,3389 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Driver O/S-independent utility routines -+ * -+ * $Id: bcmutils.c 325951 2012-04-05 06:03:27Z $ -+ */ -+ -+#include -+#include -+#include -+#if defined(__FreeBSD__) || defined(__NetBSD__) -+#include -+#else -+#include -+#endif -+#ifdef BCMDRIVER -+ -+#include -+#include -+#include -+#include -+ -+#else /* !BCMDRIVER */ -+ -+#include -+#include -+#include -+ -+#if defined(BCMEXTSUP) -+#include -+#endif -+ -+#endif /* !BCMDRIVER */ -+ -+#if defined(_WIN32) || defined(NDIS) || defined(__vxworks) || defined(_CFE_) -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef BCMPERFSTATS -+#include -+#endif -+#include -+void *_bcmutils_dummy_fn = NULL; -+ -+#ifdef BCMDRIVER -+ -+#ifdef WLC_LOW -+/* nvram vars cache */ -+static char *nvram_vars = NULL; -+static int vars_len = -1; -+#endif /* WLC_LOW */ -+ -+int -+pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx) -+{ -+ int i, err = BCME_OK; -+ void *p; -+ int pktplen; -+ -+ ASSERT(pktp != NULL); -+ ASSERT(osh != NULL); -+ ASSERT(pplen != NULL); -+ -+ pktplen = *pplen; -+ -+ bzero(pktp, sizeof(pktpool_t)); -+ pktp->inited = TRUE; -+ pktp->istx = istx ? TRUE : FALSE; -+ pktp->plen = (uint16)plen; -+ *pplen = 0; -+ -+ pktp->maxlen = PKTPOOL_LEN_MAX; -+ if (pktplen > pktp->maxlen) -+ pktplen = pktp->maxlen; -+ -+ for (i = 0; i < pktplen; i++) { -+ p = PKTGET(osh, plen, pktp->istx); -+ if (p == NULL) { -+ /* Not able to allocate all requested pkts -+ * so just return what was actually allocated -+ * We can add to the pool later -+ */ -+ if (pktp->w == 0) { -+ err = BCME_NOMEM; -+ } -+ -+ goto exit; -+ } -+ -+ PKTSETPOOL(osh, p, TRUE, pktp); -+ pktp->q[i] = p; -+ pktp->w++; -+ pktp->len++; -+#ifdef BCMDBG_POOL -+ pktp->dbg_q[pktp->dbg_qlen++].p = p; -+#endif -+ } -+ -+exit: -+ *pplen = pktp->w; -+ pktp->len++; /* Add one for end */ -+ return err; -+} -+ -+int -+pktpool_deinit(osl_t *osh, pktpool_t *pktp) -+{ -+ int i; -+ int cnt; -+ -+ ASSERT(osh != NULL); -+ ASSERT(pktp != NULL); -+ -+ cnt = pktp->len; -+ for (i = 0; i < cnt; i++) { -+ if (pktp->q[i] != NULL) { -+ PKTSETPOOL(osh, pktp->q[i], FALSE, NULL); -+ PKTFREE(osh, pktp->q[i], pktp->istx); -+ pktp->q[i] = NULL; -+ pktp->len--; -+ } -+#ifdef BCMDBG_POOL -+ if (pktp->dbg_q[i].p != NULL) { -+ pktp->dbg_q[i].p = NULL; -+ } -+#endif -+ } -+ pktp->inited = FALSE; -+ -+ /* Are there still pending pkts? */ -+ ASSERT(pktpool_len(pktp) == 0); -+ -+ return 0; -+} -+ -+int -+pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) -+{ -+ void *p; -+ int err = 0; -+ int len, psize, maxlen; -+ -+ ASSERT(pktpool_plen(pktp) != 0); -+ -+ maxlen = pktpool_maxlen(pktp); -+ psize = minimal ? (maxlen >> 2) : maxlen; -+ len = pktpool_len(pktp); -+ for (; len < psize; len++) { -+ p = PKTGET(osh, pktpool_plen(pktp), FALSE); -+ if (p == NULL) { -+ err = BCME_NOMEM; -+ break; -+ } -+ -+ if (pktpool_add(pktp, p) != BCME_OK) { -+ PKTFREE(osh, p, FALSE); -+ err = BCME_ERROR; -+ break; -+ } -+ } -+ -+ return err; -+} -+ -+uint16 -+pktpool_avail(pktpool_t *pktp) -+{ -+ if (pktp->w == pktp->r) { -+ return 0; -+ } -+ -+ return (pktp->w > pktp->r) ? (pktp->w - pktp->r) : ((pktp->len) - (pktp->r - pktp->w)); -+} -+ -+static void * -+pktpool_deq(pktpool_t *pktp) -+{ -+ void *p; -+ -+ if (pktp->r == pktp->w) { -+ return NULL; -+ } -+ -+ p = pktp->q[pktp->r]; -+ ASSERT(p != NULL); -+ -+ pktp->q[pktp->r++] = NULL; -+ pktp->r %= (pktp->len); -+ -+ return p; -+} -+ -+static void -+pktpool_enq(pktpool_t *pktp, void *p) -+{ -+ uint16 next; -+ -+ ASSERT(p != NULL); -+ -+ next = (pktp->w + 1) % (pktp->len); -+ if (next == pktp->r) { -+ /* Should not happen; otherwise pkt leak */ -+ ASSERT(0); -+ return; -+ } -+ -+ ASSERT(pktp->q[pktp->w] == NULL); -+ -+ pktp->q[pktp->w] = p; -+ pktp->w = next; -+} -+ -+int -+pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) -+{ -+ int i; -+ -+ ASSERT(cb != NULL); -+ -+ i = pktp->cbcnt; -+ if (i == PKTPOOL_CB_MAX) { -+ return BCME_ERROR; -+ } -+ -+ ASSERT(pktp->cbs[i].cb == NULL); -+ pktp->cbs[i].cb = cb; -+ pktp->cbs[i].arg = arg; -+ pktp->cbcnt++; -+ -+ return 0; -+} -+ -+int -+pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) -+{ -+ int i; -+ -+ ASSERT(cb != NULL); -+ -+ i = pktp->ecbcnt; -+ if (i == PKTPOOL_CB_MAX) { -+ return BCME_ERROR; -+ } -+ -+ ASSERT(pktp->ecbs[i].cb == NULL); -+ pktp->ecbs[i].cb = cb; -+ pktp->ecbs[i].arg = arg; -+ pktp->ecbcnt++; -+ -+ return 0; -+} -+ -+static int -+pktpool_empty_notify(pktpool_t *pktp) -+{ -+ int i; -+ -+ pktp->empty = TRUE; -+ for (i = 0; i < pktp->ecbcnt; i++) { -+ ASSERT(pktp->ecbs[i].cb != NULL); -+ pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg); -+ } -+ pktp->empty = FALSE; -+ -+ return 0; -+} -+ -+#ifdef BCMDBG_POOL -+int -+pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) -+{ -+ int i; -+ -+ ASSERT(cb); -+ -+ i = pktp->dbg_cbcnt; -+ if (i == PKTPOOL_CB_MAX) -+ return BCME_ERROR; -+ -+ ASSERT(pktp->dbg_cbs[i].cb == NULL); -+ pktp->dbg_cbs[i].cb = cb; -+ pktp->dbg_cbs[i].arg = arg; -+ pktp->dbg_cbcnt++; -+ -+ return 0; -+} -+ -+int pktpool_dbg_notify(pktpool_t *pktp); -+ -+int -+pktpool_dbg_notify(pktpool_t *pktp) -+{ -+ int i; -+ -+ for (i = 0; i < pktp->dbg_cbcnt; i++) { -+ ASSERT(pktp->dbg_cbs[i].cb); -+ pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg); -+ } -+ -+ return 0; -+} -+ -+int -+pktpool_dbg_dump(pktpool_t *pktp) -+{ -+ int i; -+ -+ printf("pool len=%d maxlen=%d\n", pktp->dbg_qlen, pktp->maxlen); -+ for (i = 0; i < pktp->dbg_qlen; i++) { -+ ASSERT(pktp->dbg_q[i].p); -+ printf("%d, p: 0x%x dur:%lu us state:%d\n", i, -+ pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p)); -+ } -+ -+ return 0; -+} -+ -+int -+pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats) -+{ -+ int i; -+ int state; -+ -+ bzero(stats, sizeof(pktpool_stats_t)); -+ for (i = 0; i < pktp->dbg_qlen; i++) { -+ ASSERT(pktp->dbg_q[i].p != NULL); -+ -+ state = PKTPOOLSTATE(pktp->dbg_q[i].p); -+ switch (state) { -+ case POOL_TXENQ: -+ stats->enq++; break; -+ case POOL_TXDH: -+ stats->txdh++; break; -+ case POOL_TXD11: -+ stats->txd11++; break; -+ case POOL_RXDH: -+ stats->rxdh++; break; -+ case POOL_RXD11: -+ stats->rxd11++; break; -+ case POOL_RXFILL: -+ stats->rxfill++; break; -+ case POOL_IDLE: -+ stats->idle++; break; -+ } -+ } -+ -+ return 0; -+} -+ -+int -+pktpool_start_trigger(pktpool_t *pktp, void *p) -+{ -+ uint32 cycles, i; -+ -+ if (!PKTPOOL(NULL, p)) { -+ return 0; -+ } -+ -+ OSL_GETCYCLES(cycles); -+ -+ for (i = 0; i < pktp->dbg_qlen; i++) { -+ ASSERT(pktp->dbg_q[i].p != NULL); -+ -+ if (pktp->dbg_q[i].p == p) { -+ pktp->dbg_q[i].cycles = cycles; -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+int pktpool_stop_trigger(pktpool_t *pktp, void *p); -+int -+pktpool_stop_trigger(pktpool_t *pktp, void *p) -+{ -+ uint32 cycles, i; -+ -+ if (!PKTPOOL(NULL, p)) { -+ return 0; -+ } -+ -+ OSL_GETCYCLES(cycles); -+ -+ for (i = 0; i < pktp->dbg_qlen; i++) { -+ ASSERT(pktp->dbg_q[i].p != NULL); -+ -+ if (pktp->dbg_q[i].p == p) { -+ if (pktp->dbg_q[i].cycles == 0) -+ break; -+ -+ if (cycles >= pktp->dbg_q[i].cycles) -+ pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles; -+ else -+ pktp->dbg_q[i].dur = -+ (((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1; -+ -+ pktp->dbg_q[i].cycles = 0; -+ break; -+ } -+ } -+ -+ return 0; -+} -+#endif /* BCMDBG_POOL */ -+ -+int -+pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp) -+{ -+ ASSERT(pktp); -+ pktp->availcb_excl = NULL; -+ return 0; -+} -+ -+int -+pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb) -+{ -+ int i; -+ -+ ASSERT(pktp); -+ ASSERT(pktp->availcb_excl == NULL); -+ for (i = 0; i < pktp->cbcnt; i++) { -+ if (cb == pktp->cbs[i].cb) { -+ pktp->availcb_excl = &pktp->cbs[i]; -+ break; -+ } -+ } -+ -+ if (pktp->availcb_excl == NULL) { -+ return BCME_ERROR; -+ } else { -+ return 0; -+ } -+} -+ -+static int -+pktpool_avail_notify(pktpool_t *pktp) -+{ -+ int i, k, idx; -+ int avail; -+ -+ ASSERT(pktp); -+ if (pktp->availcb_excl != NULL) { -+ pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg); -+ return 0; -+ } -+ -+ k = pktp->cbcnt - 1; -+ for (i = 0; i < pktp->cbcnt; i++) { -+ avail = pktpool_avail(pktp); -+ -+ if (avail) { -+ if (pktp->cbtoggle) { -+ idx = i; -+ } else { -+ idx = k--; -+ } -+ -+ ASSERT(pktp->cbs[idx].cb != NULL); -+ pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg); -+ } -+ } -+ -+ /* Alternate between filling from head or tail -+ */ -+ pktp->cbtoggle ^= 1; -+ -+ return 0; -+} -+ -+void * -+pktpool_get(pktpool_t *pktp) -+{ -+ void *p; -+ -+ p = pktpool_deq(pktp); -+ -+ if (p == NULL) { -+ /* Notify and try to reclaim tx pkts */ -+ if (pktp->ecbcnt) { -+ pktpool_empty_notify(pktp); -+ } -+ -+ p = pktpool_deq(pktp); -+ } -+ -+ return p; -+} -+ -+void -+pktpool_free(pktpool_t *pktp, void *p) -+{ -+ ASSERT(p != NULL); -+ -+#ifdef BCMDBG_POOL -+ /* pktpool_stop_trigger(pktp, p); */ -+#endif -+ -+ pktpool_enq(pktp, p); -+ -+ if (pktp->emptycb_disable) { -+ return; -+ } -+ -+ if (pktp->cbcnt) { -+ if (pktp->empty == FALSE) { -+ pktpool_avail_notify(pktp); -+ } -+ } -+} -+ -+int -+pktpool_add(pktpool_t *pktp, void *p) -+{ -+ ASSERT(p != NULL); -+ -+ if (pktpool_len(pktp) == pktp->maxlen) { -+ return BCME_RANGE; -+ } -+ -+ ASSERT(pktpool_plen(pktp) == PKTLEN(NULL, p)); /* pkts in pool have same length */ -+ PKTSETPOOL(NULL, p, TRUE, pktp); -+ -+ pktp->len++; -+ if (pktp->r > pktp->w) { -+ /* Add to tail */ -+ ASSERT(pktp->q[pktp->len - 1] == NULL); -+ pktp->q[pktp->len - 1] = p; -+ } else { -+ pktpool_enq(pktp, p); -+ } -+ -+#ifdef BCMDBG_POOL -+ pktp->dbg_q[pktp->dbg_qlen++].p = p; -+#endif -+ -+ return 0; -+} -+ -+int -+pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen) -+{ -+ if (maxlen > PKTPOOL_LEN_MAX) -+ maxlen = PKTPOOL_LEN_MAX; -+ -+ /* if pool is already beyond maxlen, then just cap it -+ * since we currently do not reduce the pool len -+ * already allocated -+ */ -+ pktp->maxlen = (pktpool_len(pktp) > maxlen) ? pktpool_len(pktp) : maxlen; -+ -+ return pktp->maxlen; -+} -+ -+void -+pktpool_emptycb_disable(pktpool_t *pktp, bool disable) -+{ -+ ASSERT(pktp); -+ -+ pktp->emptycb_disable = disable; -+} -+ -+bool -+pktpool_emptycb_disabled(pktpool_t *pktp) -+{ -+ ASSERT(pktp); -+ return pktp->emptycb_disable; -+} -+ -+/* copy a pkt buffer chain into a buffer */ -+uint -+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) -+{ -+ uint n, ret = 0; -+ -+ if (len < 0) { -+ len = 4096; /* "infinite" */ -+ } -+ -+ /* skip 'offset' bytes */ -+ for (; p && offset; p = PKTNEXT(osh, p)) { -+ if (offset < (uint)PKTLEN(osh, p)) { -+ break; -+ } -+ offset -= PKTLEN(osh, p); -+ } -+ -+ if (!p) { -+ return 0; -+ } -+ -+ /* copy the data */ -+ for (; p && len; p = PKTNEXT(osh, p)) { -+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); -+ bcopy(PKTDATA(osh, p) + offset, buf, n); -+ buf += n; -+ len -= n; -+ ret += n; -+ offset = 0; -+ } -+ -+ return ret; -+} -+ -+/* copy a buffer into a pkt buffer chain */ -+uint -+pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) -+{ -+ uint n, ret = 0; -+ -+ /* skip 'offset' bytes */ -+ for (; p && offset; p = PKTNEXT(osh, p)) { -+ if (offset < (uint)PKTLEN(osh, p)) { -+ break; -+ } -+ offset -= PKTLEN(osh, p); -+ } -+ -+ if (!p) { -+ return 0; -+ } -+ -+ /* copy the data */ -+ for (; p && len; p = PKTNEXT(osh, p)) { -+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); -+ bcopy(buf, PKTDATA(osh, p) + offset, n); -+ buf += n; -+ len -= n; -+ ret += n; -+ offset = 0; -+ } -+ -+ return ret; -+} -+ -+#ifdef NOTYET -+/* copy data from one pkt buffer (chain) to another */ -+uint -+pkt2pktcopy(osl_t *osh, void *p1, uint offs1, void *p2, uint offs2, int maxlen) -+{ -+ uint8 *dp1, *dp2; -+ uint len1, len2, copylen, totallen; -+ -+ for (; p1 && offs; p1 = PKTNEXT(osh, p1)) { -+ if (offs1 < (uint)PKTLEN(osh, p1)) { -+ break; -+ } -+ offs1 -= PKTLEN(osh, p1); -+ } -+ for (; p2 && offs; p2 = PKTNEXT(osh, p2)) { -+ if (offs2 < (uint)PKTLEN(osh, p2)) { -+ break; -+ } -+ offs2 -= PKTLEN(osh, p2); -+ } -+ -+ /* Heck w/it, only need the above for now */ -+} -+#endif /* NOTYET */ -+ -+ -+/* return total length of buffer chain */ -+uint BCMFASTPATH -+pkttotlen(osl_t *osh, void *p) -+{ -+ uint total; -+ int len; -+ -+ total = 0; -+ for (; p; p = PKTNEXT(osh, p)) { -+ len = PKTLEN(osh, p); -+#ifdef MACOSX -+ if (len < 0) { -+ /* Bad packet length, just drop and exit */ -+ printf("wl: pkttotlen bad (%p,%d)\n", p, len); -+ break; -+ } -+#endif /* MACOSX */ -+ total += len; -+ } -+ -+ return (total); -+} -+ -+/* return the last buffer of chained pkt */ -+void * -+pktlast(osl_t *osh, void *p) -+{ -+ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) { -+ ; -+ } -+ -+ return (p); -+} -+ -+/* count segments of a chained packet */ -+uint BCMFASTPATH -+pktsegcnt(osl_t *osh, void *p) -+{ -+ uint cnt; -+ -+ for (cnt = 0; p; p = PKTNEXT(osh, p)) { -+ cnt++; -+ } -+ -+ return cnt; -+} -+ -+ -+/* count segments of a chained packet */ -+uint BCMFASTPATH -+pktsegcnt_war(osl_t *osh, void *p) -+{ -+ uint cnt; -+ uint8 *pktdata; -+ uint len, remain, align64; -+ -+ for (cnt = 0; p; p = PKTNEXT(osh, p)) { -+ cnt++; -+ len = PKTLEN(osh, p); -+ if (len > 128) { -+ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ -+ /* Check for page boundary straddle (2048B) */ -+ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) { -+ cnt++; -+ } -+ -+ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ -+ align64 = (64 - align64) & 0x3f; -+ len -= align64; /* bytes from aligned 64B to end */ -+ /* if aligned to 128B, check for MOD 128 between 1 to 4B */ -+ remain = len % 128; -+ if (remain > 0 && remain <= 4) { -+ cnt++; /* add extra seg */ -+ } -+ } -+ } -+ -+ return cnt; -+} -+ -+uint8 * BCMFASTPATH -+pktdataoffset(osl_t *osh, void *p, uint offset) -+{ -+ uint total = pkttotlen(osh, p); -+ uint pkt_off = 0, len = 0; -+ uint8 *pdata = (uint8 *) PKTDATA(osh, p); -+ -+ if (offset > total) { -+ return NULL; -+ } -+ -+ for (; p; p = PKTNEXT(osh, p)) { -+ pdata = (uint8 *) PKTDATA(osh, p); -+ pkt_off = offset - len; -+ len += PKTLEN(osh, p); -+ if (len > offset) { -+ break; -+ } -+ } -+ return (uint8*) (pdata+pkt_off); -+} -+ -+ -+/* given a offset in pdata, find the pkt seg hdr */ -+void * -+pktoffset(osl_t *osh, void *p, uint offset) -+{ -+ uint total = pkttotlen(osh, p); -+ uint len = 0; -+ -+ if (offset > total) { -+ return NULL; -+ } -+ -+ for (; p; p = PKTNEXT(osh, p)) { -+ len += PKTLEN(osh, p); -+ if (len > offset) { -+ break; -+ } -+ } -+ return p; -+} -+ -+/* -+ * osl multiple-precedence packet queue -+ * hi_prec is always >= the number of the highest non-empty precedence -+ */ -+void * BCMFASTPATH -+pktq_penq(struct pktq *pq, int prec, void *p) -+{ -+ struct pktq_prec *q; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ -+ -+ ASSERT(!pktq_full(pq)); -+ ASSERT(!pktq_pfull(pq, prec)); -+ -+ q = &pq->q[prec]; -+ -+ if (q->head) { -+ PKTSETLINK(q->tail, p); -+ } else { -+ q->head = p; -+ } -+ -+ q->tail = p; -+ q->len++; -+ -+ pq->len++; -+ -+ if (pq->hi_prec < prec) { -+ pq->hi_prec = (uint8)prec; -+ } -+ -+ return p; -+} -+ -+void * BCMFASTPATH -+pktq_penq_head(struct pktq *pq, int prec, void *p) -+{ -+ struct pktq_prec *q; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ -+ -+ ASSERT(!pktq_full(pq)); -+ ASSERT(!pktq_pfull(pq, prec)); -+ -+ q = &pq->q[prec]; -+ -+ if (q->head == NULL) { -+ q->tail = p; -+ } -+ -+ PKTSETLINK(p, q->head); -+ q->head = p; -+ q->len++; -+ -+ pq->len++; -+ -+ if (pq->hi_prec < prec) { -+ pq->hi_prec = (uint8)prec; -+ } -+ -+ return p; -+} -+ -+void * BCMFASTPATH -+pktq_pdeq(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ void *p; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ if ((q->head = PKTLINK(p)) == NULL) { -+ q->tail = NULL; -+ } -+ -+ q->len--; -+ -+ pq->len--; -+ -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} -+ -+void * BCMFASTPATH -+pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) -+{ -+ struct pktq_prec *q; -+ void *p; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ q = &pq->q[prec]; -+ -+ if (prev_p == NULL) { -+ return NULL; -+ } -+ -+ if ((p = PKTLINK(prev_p)) == NULL) { -+ return NULL; -+ } -+ -+ q->len--; -+ -+ pq->len--; -+ -+ PKTSETLINK(prev_p, PKTLINK(p)); -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} -+ -+void * BCMFASTPATH -+pktq_pdeq_tail(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ void *p, *prev; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ for (prev = NULL; p != q->tail; p = PKTLINK(p)) { -+ prev = p; -+ } -+ -+ if (prev) { -+ PKTSETLINK(prev, NULL); -+ } else { -+ q->head = NULL; -+ } -+ -+ q->tail = prev; -+ q->len--; -+ -+ pq->len--; -+ -+ return p; -+} -+ -+void -+pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) -+{ -+ struct pktq_prec *q; -+ void *p, *prev = NULL; -+ -+ q = &pq->q[prec]; -+ p = q->head; -+ while (p) { -+ if (fn == NULL || (*fn)(p, arg)) { -+ bool head = (p == q->head); -+ if (head) { -+ q->head = PKTLINK(p); -+ } else { -+ PKTSETLINK(prev, PKTLINK(p)); -+ } -+ PKTSETLINK(p, NULL); -+ PKTFREE(osh, p, dir); -+ q->len--; -+ pq->len--; -+ p = (head ? q->head : PKTLINK(prev)); -+ } else { -+ prev = p; -+ p = PKTLINK(p); -+ } -+ } -+ -+ if (q->head == NULL) { -+ ASSERT(q->len == 0); -+ q->tail = NULL; -+ } -+} -+ -+bool BCMFASTPATH -+pktq_pdel(struct pktq *pq, void *pktbuf, int prec) -+{ -+ struct pktq_prec *q; -+ void *p; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ if (!pktbuf) { -+ return FALSE; -+ } -+ -+ q = &pq->q[prec]; -+ -+ if (q->head == pktbuf) { -+ if ((q->head = PKTLINK(pktbuf)) == NULL) { -+ q->tail = NULL; -+ } -+ } else { -+ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) { -+ ; -+ } -+ if (p == NULL) { -+ return FALSE; -+ } -+ -+ PKTSETLINK(p, PKTLINK(pktbuf)); -+ if (q->tail == pktbuf) { -+ q->tail = p; -+ } -+ } -+ -+ q->len--; -+ pq->len--; -+ PKTSETLINK(pktbuf, NULL); -+ return TRUE; -+} -+ -+void -+pktq_init(struct pktq *pq, int num_prec, int max_len) -+{ -+ int prec; -+ -+ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); -+ -+ /* pq is variable size; only zero out what's requested */ -+ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); -+ -+ pq->num_prec = (uint16)num_prec; -+ -+ pq->max = (uint16)max_len; -+ -+ for (prec = 0; prec < num_prec; prec++) { -+ pq->q[prec].max = pq->max; -+ } -+} -+ -+void -+pktq_set_max_plen(struct pktq *pq, int prec, int max_len) -+{ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ if (prec < pq->num_prec) { -+ pq->q[prec].max = (uint16)max_len; -+ } -+} -+ -+void * BCMFASTPATH -+pktq_deq(struct pktq *pq, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) { -+ pq->hi_prec--; -+ } -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ if ((q->head = PKTLINK(p)) == NULL) { -+ q->tail = NULL; -+ } -+ -+ q->len--; -+ -+ pq->len--; -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} -+ -+void * BCMFASTPATH -+pktq_deq_tail(struct pktq *pq, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p, *prev; -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ -+ for (prec = 0; prec < pq->hi_prec; prec++) { -+ if (pq->q[prec].head) { -+ break; -+ } -+ } -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ for (prev = NULL; p != q->tail; p = PKTLINK(p)) { -+ prev = p; -+ } -+ -+ if (prev) { -+ PKTSETLINK(prev, NULL); -+ } else { -+ q->head = NULL; -+ } -+ -+ q->tail = prev; -+ q->len--; -+ -+ pq->len--; -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} -+ -+void * -+pktq_peek(struct pktq *pq, int *prec_out) -+{ -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) { -+ pq->hi_prec--; -+ } -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ return (pq->q[prec].head); -+} -+ -+void * -+pktq_peek_tail(struct pktq *pq, int *prec_out) -+{ -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ -+ for (prec = 0; prec < pq->hi_prec; prec++) { -+ if (pq->q[prec].head) { -+ break; -+ } -+ } -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ return (pq->q[prec].tail); -+} -+ -+void -+pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) -+{ -+ int prec; -+ -+ /* Optimize flush, if pktq len = 0, just return. -+ * pktq len of 0 means pktq's prec q's are all empty. -+ */ -+ if (pq->len == 0) { -+ return; -+ } -+ -+ for (prec = 0; prec < pq->num_prec; prec++) { -+ pktq_pflush(osh, pq, prec, dir, fn, arg); -+ } -+ if (fn == NULL) { -+ ASSERT(pq->len == 0); -+ } -+} -+ -+/* Return sum of lengths of a specific set of precedences */ -+int -+pktq_mlen(struct pktq *pq, uint prec_bmp) -+{ -+ int prec, len; -+ -+ len = 0; -+ -+ for (prec = 0; prec <= pq->hi_prec; prec++) { -+ if (prec_bmp & (1 << prec)) { -+ len += pq->q[prec].len; -+ } -+ } -+ -+ return len; -+} -+ -+/* Priority peek from a specific set of precedences */ -+void * BCMFASTPATH -+pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) { -+ pq->hi_prec--; -+ } -+ -+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) { -+ if (prec-- == 0) { -+ return NULL; -+ } -+ } -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ return p; -+} -+/* Priority dequeue from a specific set of precedences */ -+void * BCMFASTPATH -+pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) { -+ return NULL; -+ } -+ -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) { -+ pq->hi_prec--; -+ } -+ -+ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) { -+ if (prec-- == 0) { -+ return NULL; -+ } -+ } -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) { -+ return NULL; -+ } -+ -+ if ((q->head = PKTLINK(p)) == NULL) { -+ q->tail = NULL; -+ } -+ -+ q->len--; -+ -+ if (prec_out) { -+ *prec_out = prec; -+ } -+ -+ pq->len--; -+ -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} -+ -+#endif /* BCMDRIVER */ -+ -+#if defined(BCMROMBUILD) -+const unsigned char BCMROMDATA(bcm_ctype)[] = { -+#else -+const unsigned char bcm_ctype[] = { -+#endif -+ -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ -+ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, -+ _BCM_C, /* 8-15 */ -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ -+ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ -+ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ -+ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ -+ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ -+ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, -+ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ -+ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, -+ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ -+ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, -+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ -+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, -+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ -+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, -+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ -+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, -+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ -+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, -+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ -+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, -+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ -+}; -+ -+ulong -+BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base) -+{ -+ ulong result, last_result = 0, value; -+ bool minus; -+ -+ minus = FALSE; -+ -+ while (bcm_isspace(*cp)) { -+ cp++; -+ } -+ -+ if (cp[0] == '+') { -+ cp++; -+ } else if (cp[0] == '-') { -+ minus = TRUE; -+ cp++; -+ } -+ -+ if (base == 0) { -+ if (cp[0] == '0') { -+ if ((cp[1] == 'x') || (cp[1] == 'X')) { -+ base = 16; -+ cp = &cp[2]; -+ } else { -+ base = 8; -+ cp = &cp[1]; -+ } -+ } else { -+ base = 10; -+ } -+ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { -+ cp = &cp[2]; -+ } -+ -+ result = 0; -+ -+ while (bcm_isxdigit(*cp) && -+ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { -+ result = result*base + value; -+ /* Detected overflow */ -+ if (result < last_result && !minus) { -+ return (ulong)-1; -+ } -+ last_result = result; -+ cp++; -+ } -+ -+ if (minus) { -+ result = (ulong)(-(long)result); -+ } -+ -+ if (endp) { -+ *endp = DISCARD_QUAL(cp, char); -+ } -+ -+ return (result); -+} -+ -+int -+BCMROMFN(bcm_atoi)(const char *s) -+{ -+ return (int)bcm_strtoul(s, NULL, 10); -+} -+ -+/* return pointer to location of substring 'needle' in 'haystack' */ -+char * -+BCMROMFN(bcmstrstr)(const char *haystack, const char *needle) -+{ -+ int len, nlen; -+ int i; -+ -+ if ((haystack == NULL) || (needle == NULL)) { -+ return DISCARD_QUAL(haystack, char); -+ } -+ -+ nlen = strlen(needle); -+ len = strlen(haystack) - nlen + 1; -+ -+ for (i = 0; i < len; i++) { -+ if (memcmp(needle, &haystack[i], nlen) == 0) { -+ return DISCARD_QUAL(&haystack[i], char); -+ } -+ } -+ return (NULL); -+} -+ -+char * -+BCMROMFN(bcmstrcat)(char *dest, const char *src) -+{ -+ char *p; -+ -+ p = dest + strlen(dest); -+ -+ while ((*p++ = *src++) != '\0') { -+ ; -+ } -+ -+ return (dest); -+} -+ -+char * -+BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size) -+{ -+ char *endp; -+ char *p; -+ -+ p = dest + strlen(dest); -+ endp = p + size; -+ -+ while (p != endp && (*p++ = *src++) != '\0') { -+ ; -+ } -+ -+ return (dest); -+} -+ -+ -+/**************************************************************************** -+* Function: bcmstrtok -+* -+* Purpose: -+* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), -+* but allows strToken() to be used by different strings or callers at the same -+* time. Each call modifies '*string' by substituting a NULL character for the -+* first delimiter that is encountered, and updates 'string' to point to the char -+* after the delimiter. Leading delimiters are skipped. -+* -+* Parameters: -+* string (mod) Ptr to string ptr, updated by token. -+* delimiters (in) Set of delimiter characters. -+* tokdelim (out) Character that delimits the returned token. (May -+* be set to NULL if token delimiter is not required). -+* -+* Returns: Pointer to the next token found. NULL when no more tokens are found. -+***************************************************************************** -+*/ -+char * -+bcmstrtok(char **string, const char *delimiters, char *tokdelim) -+{ -+ unsigned char *str; -+ unsigned long map[8]; -+ int count; -+ char *nextoken; -+ -+ if (tokdelim != NULL) { -+ /* Prime the token delimiter */ -+ *tokdelim = '\0'; -+ } -+ -+ /* Clear control map */ -+ for (count = 0; count < 8; count++) { -+ map[count] = 0; -+ } -+ -+ /* Set bits in delimiter table */ -+ do { -+ map[*delimiters >> 5] |= (1 << (*delimiters & 31)); -+ } -+ while (*delimiters++); -+ -+ str = (unsigned char*)*string; -+ -+ /* Find beginning of token (skip over leading delimiters). Note that -+ * there is no token iff this loop sets str to point to the terminal -+ * null (*str == '\0') -+ */ -+ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { -+ str++; -+ } -+ -+ nextoken = (char*)str; -+ -+ /* Find the end of the token. If it is not the end of the string, -+ * put a null there. -+ */ -+ for (; *str; str++) { -+ if (map[*str >> 5] & (1 << (*str & 31))) { -+ if (tokdelim != NULL) { -+ *tokdelim = *str; -+ } -+ -+ *str++ = '\0'; -+ break; -+ } -+ } -+ -+ *string = (char*)str; -+ -+ /* Determine if a token has been found. */ -+ if (nextoken == (char *) str) { -+ return NULL; -+ } -+ else { -+ return nextoken; -+ } -+} -+ -+ -+#define xToLower(C) \ -+ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) -+ -+ -+/**************************************************************************** -+* Function: bcmstricmp -+* -+* Purpose: Compare to strings case insensitively. -+* -+* Parameters: s1 (in) First string to compare. -+* s2 (in) Second string to compare. -+* -+* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -+* t1 > t2, when ignoring case sensitivity. -+***************************************************************************** -+*/ -+int -+bcmstricmp(const char *s1, const char *s2) -+{ -+ char dc, sc; -+ -+ while (*s2 && *s1) { -+ dc = xToLower(*s1); -+ sc = xToLower(*s2); -+ if (dc < sc) return -1; -+ if (dc > sc) return 1; -+ s1++; -+ s2++; -+ } -+ -+ if (*s1 && !*s2) return 1; -+ if (!*s1 && *s2) return -1; -+ return 0; -+} -+ -+ -+/**************************************************************************** -+* Function: bcmstrnicmp -+* -+* Purpose: Compare to strings case insensitively, upto a max of 'cnt' -+* characters. -+* -+* Parameters: s1 (in) First string to compare. -+* s2 (in) Second string to compare. -+* cnt (in) Max characters to compare. -+* -+* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -+* t1 > t2, when ignoring case sensitivity. -+***************************************************************************** -+*/ -+int -+bcmstrnicmp(const char* s1, const char* s2, int cnt) -+{ -+ char dc, sc; -+ -+ while (*s2 && *s1 && cnt) { -+ dc = xToLower(*s1); -+ sc = xToLower(*s2); -+ if (dc < sc) return -1; -+ if (dc > sc) return 1; -+ s1++; -+ s2++; -+ cnt--; -+ } -+ -+ if (!cnt) return 0; -+ if (*s1 && !*s2) return 1; -+ if (!*s1 && *s2) return -1; -+ return 0; -+} -+ -+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ -+int -+BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea) -+{ -+ int i = 0; -+ char *ep; -+ -+ for (;;) { -+ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); -+ p = ep; -+ if (!*p++ || i == 6) -+ break; -+ } -+ -+ return (i == 6); -+} -+ -+ -+#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) -+/* registry routine buffer preparation utility functions: -+ * parameter order is like strncpy, but returns count -+ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) -+ */ -+ulong -+wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) -+{ -+ ulong copyct = 1; -+ ushort i; -+ -+ if (abuflen == 0) -+ return 0; -+ -+ /* wbuflen is in bytes */ -+ wbuflen /= sizeof(ushort); -+ -+ for (i = 0; i < wbuflen; ++i) { -+ if (--abuflen == 0) { -+ break; -+ } -+ *abuf++ = (char) *wbuf++; -+ ++copyct; -+ } -+ *abuf = '\0'; -+ -+ return copyct; -+} -+#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ -+ -+char * -+bcm_ether_ntoa(const struct ether_addr *ea, char *buf) -+{ -+ static const char hex[] = -+ { -+ '0', '1', '2', '3', '4', '5', '6', '7', -+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' -+ }; -+ const uint8 *octet = ea->octet; -+ char *p = buf; -+ int i; -+ -+ for (i = 0; i < 6; i++, octet++) { -+ *p++ = hex[(*octet >> 4) & 0xf]; -+ *p++ = hex[*octet & 0xf]; -+ *p++ = ':'; -+ } -+ -+ *(p-1) = '\0'; -+ -+ return (buf); -+} -+ -+char * -+bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) -+{ -+ snprintf(buf, 16, "%d.%d.%d.%d", -+ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); -+ return (buf); -+} -+ -+#ifdef BCMDRIVER -+ -+void -+bcm_mdelay(uint ms) -+{ -+ uint i; -+ -+ for (i = 0; i < ms; i++) { -+ OSL_DELAY(1000); -+ } -+} -+ -+/* -+ * Search the name=value vars for a specific one and return its value. -+ * Returns NULL if not found. -+ */ -+char * -+getvar(char *vars, const char *name) -+{ -+#ifdef _MINOSL_ -+ return NULL; -+#else -+ char *s; -+ int len; -+ -+ if (!name) { -+ return NULL; -+ } -+ -+ len = strlen(name); -+ if (len == 0) { -+ return NULL; -+ } -+ -+ /* first look in vars[] */ -+ for (s = vars; s && *s;) { -+ if ((bcmp(s, name, len) == 0) && (s[len] == '=') && (strlen(s)==len)) { -+ return (&s[len+1]); -+ } -+ -+ while (*s++) { -+ ; -+ } -+ } -+ -+ /* then query nvram */ -+ return (nvram_get(name)); -+#endif /* defined(_MINOSL_) */ -+} -+ -+/* -+ * Search the vars for a specific one and return its value as -+ * an integer. Returns 0 if not found. -+ */ -+int -+getintvar(char *vars, const char *name) -+{ -+#ifdef _MINOSL_ -+ return 0; -+#else -+ char *val; -+ -+ if ((val = getvar(vars, name)) == NULL) { -+ return (0); -+ } -+ -+ return (bcm_strtoul(val, NULL, 0)); -+#endif /* _MINOSL_ */ -+} -+ -+int -+getintvararray(char *vars, const char *name, int index) -+{ -+#ifdef _MINOSL_ -+ return 0; -+#else -+ char *buf, *endp; -+ int i = 0; -+ int val = 0; -+ -+ if ((buf = getvar(vars, name)) == NULL) { -+ return (0); -+ } -+ -+ /* table values are always separated by "," or " " */ -+ while (*buf != '\0') { -+ val = bcm_strtoul(buf, &endp, 0); -+ if (i == index) { -+ return val; -+ } -+ buf = endp; -+ /* delimiter is ',' */ -+ if (*buf == ',') { -+ buf++; -+ } -+ i++; -+ } -+ return 0; -+#endif /* _MINOSL_ */ -+} -+ -+int -+getintvararraysize(char *vars, const char *name) -+{ -+#ifdef _MINOSL_ -+ return 0; -+#else -+ char *buf, *endp; -+ int count = 0; -+ int val = 0; -+ -+ if ((buf = getvar(vars, name)) == NULL) { -+ return (0); -+ } -+ -+ /* table values are always separated by "," or " " */ -+ while (*buf != '\0') { -+ val = bcm_strtoul(buf, &endp, 0); -+ buf = endp; -+ /* delimiter is ',' */ -+ if (*buf == ',') { -+ buf++; -+ } -+ count++; -+ } -+ BCM_REFERENCE(val); -+ return count; -+#endif /* _MINOSL_ */ -+} -+ -+/* Search for token in comma separated token-string */ -+static int -+findmatch(const char *string, const char *name) -+{ -+ uint len; -+ char *c; -+ -+ len = strlen(name); -+ while ((c = strchr(string, ',')) != NULL) { -+ if (len == (uint)(c - string) && !strncmp(string, name, len)) { -+ return 1; -+ } -+ string = c + 1; -+ } -+ -+ return (!strcmp(string, name)); -+} -+ -+/* Return gpio pin number assigned to the named pin -+ * -+ * Variable should be in format: -+ * -+ * gpio=pin_name,pin_name -+ * -+ * This format allows multiple features to share the gpio with mutual -+ * understanding. -+ * -+ * 'def_pin' is returned if a specific gpio is not defined for the requested functionality -+ * and if def_pin is not used by others. -+ */ -+uint -+getgpiopin(char *vars, char *pin_name, uint def_pin) -+{ -+ char name[] = "gpioXXXX"; -+ char *val; -+ uint pin; -+ -+ /* Go thru all possibilities till a match in pin name */ -+ for (pin = 0; pin < GPIO_NUMPINS; pin ++) { -+ snprintf(name, sizeof(name), "gpio%d", pin); -+ val = getvar(vars, name); -+ if (val && findmatch(val, pin_name)) { -+ return pin; -+ } -+ } -+ -+ if (def_pin != GPIO_PIN_NOTDEFINED) { -+ /* make sure the default pin is not used by someone else */ -+ snprintf(name, sizeof(name), "gpio%d", def_pin); -+ if (getvar(vars, name)) { -+ def_pin = GPIO_PIN_NOTDEFINED; -+ } -+ } -+ return def_pin; -+} -+ -+ -+/* Return the WAN port number -+ * -+ * 0 is returned if no wanport is configured. -+ */ -+int -+getwanport(void) -+{ -+ char name[] = "wanport"; -+ int retval; -+ -+ retval = getintvar(NULL, name); -+ return retval; -+} -+ -+ -+/* Return the brcmtag variable -+ * -+ * 0 is returned if no wanport is configured. -+ */ -+int -+getbrcmtag(void) -+{ -+ char name[] = "brcmtag"; -+ int retval; -+ -+ retval = getintvar(NULL, name); -+ return retval; -+} -+ -+#if defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) -+#define LOGSIZE 256 /* should be power of 2 to avoid div below */ -+static struct { -+ uint cycles; -+ char *fmt; -+ uint a1; -+ uint a2; -+} logtab[LOGSIZE]; -+ -+/* last entry logged */ -+static uint logi = 0; -+/* next entry to read */ -+static uint readi = 0; -+#endif /* defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) */ -+ -+#ifdef BCMPERFSTATS -+void -+bcm_perf_enable() -+{ -+ BCMPERF_ENABLE_INSTRCOUNT(); -+ BCMPERF_ENABLE_ICACHE_MISS(); -+ BCMPERF_ENABLE_ICACHE_HIT(); -+} -+ -+/* WARNING: This routine uses OSL_GETCYCLES(), which can give unexpected results on -+ * modern speed stepping CPUs. Use bcmtslog() instead in combination with TSF counter. -+ */ -+void -+bcmlog(char *fmt, uint a1, uint a2) -+{ -+ static uint last = 0; -+ uint cycles, i; -+ OSL_GETCYCLES(cycles); -+ -+ i = logi; -+ -+ logtab[i].cycles = cycles - last; -+ logtab[i].fmt = fmt; -+ logtab[i].a1 = a1; -+ logtab[i].a2 = a2; -+ -+ logi = (i + 1) % LOGSIZE; -+ last = cycles; -+} -+ -+ -+void -+bcmstats(char *fmt) -+{ -+ static uint last = 0; -+ static uint32 ic_miss = 0; -+ static uint32 instr_count = 0; -+ uint32 ic_miss_cur; -+ uint32 instr_count_cur; -+ uint cycles, i; -+ -+ OSL_GETCYCLES(cycles); -+ BCMPERF_GETICACHE_MISS(ic_miss_cur); -+ BCMPERF_GETINSTRCOUNT(instr_count_cur); -+ -+ i = logi; -+ -+ logtab[i].cycles = cycles - last; -+ logtab[i].a1 = ic_miss_cur - ic_miss; -+ logtab[i].a2 = instr_count_cur - instr_count; -+ logtab[i].fmt = fmt; -+ -+ logi = (i + 1) % LOGSIZE; -+ -+ last = cycles; -+ instr_count = instr_count_cur; -+ ic_miss = ic_miss_cur; -+} -+ -+ -+void -+bcmdumplog(char *buf, int size) -+{ -+ char *limit; -+ int j = 0; -+ int num; -+ -+ limit = buf + size - 80; -+ *buf = '\0'; -+ -+ num = logi - readi; -+ -+ if (num < 0) { -+ num += LOGSIZE; -+ } -+ -+ /* print in chronological order */ -+ -+ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { -+ if (logtab[readi].fmt == NULL) { -+ continue; -+ } -+ buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); -+ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, -+ logtab[readi].a2); -+ buf += snprintf(buf, (limit - buf), "\n"); -+ } -+ -+} -+ -+ -+/* -+ * Dump one log entry at a time. -+ * Return index of next entry or -1 when no more . -+ */ -+int -+bcmdumplogent(char *buf, uint i) -+{ -+ bool hit; -+ -+ /* -+ * If buf is NULL, return the starting index, -+ * interpreting i as the indicator of last 'i' entries to dump. -+ */ -+ if (buf == NULL) { -+ i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1); -+ return ((logi - i) % LOGSIZE); -+ } -+ -+ *buf = '\0'; -+ -+ ASSERT(i < LOGSIZE); -+ -+ if (i == logi) { -+ return (-1); -+ } -+ -+ hit = FALSE; -+ for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) { -+ if (logtab[i].fmt == NULL) { -+ continue; -+ } -+ buf += sprintf(buf, "%d: %d\t", i, logtab[i].cycles); -+ buf += sprintf(buf, logtab[i].fmt, logtab[i].a1, logtab[i].a2); -+ buf += sprintf(buf, "\n"); -+ hit = TRUE; -+ } -+ -+ return (i); -+} -+ -+#endif /* BCMPERFSTATS */ -+ -+#if defined(BCMTSTAMPEDLOGS) -+/* Store a TSF timestamp and a log line in the log buffer */ -+void -+bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2) -+{ -+ uint i = logi; -+ bool use_delta = FALSE; -+ static uint32 last = 0; /* used only when use_delta is true */ -+ -+ logtab[i].cycles = tstamp; -+ if (use_delta) { -+ logtab[i].cycles -= last; -+ } -+ -+ logtab[i].fmt = fmt; -+ logtab[i].a1 = a1; -+ logtab[i].a2 = a2; -+ -+ if (use_delta) { -+ last = tstamp; -+ } -+ logi = (i + 1) % LOGSIZE; -+} -+ -+/* Print out a microsecond timestamp as "sec.ms.us " */ -+void -+bcmprinttstamp(uint32 ticks) -+{ -+ uint us, ms, sec; -+ -+ us = (ticks % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; -+ ms = ticks / TSF_TICKS_PER_MS; -+ sec = ms / 1000; -+ ms -= sec * 1000; -+ printf("%04u.%03u.%03u ", sec, ms, us); -+} -+ -+/* Print out the log buffer with timestamps */ -+void -+bcmprinttslogs(void) -+{ -+ int j = 0; -+ int num; -+ -+ num = logi - readi; -+ if (num < 0) { -+ num += LOGSIZE; -+ } -+ -+ /* Format and print the log entries directly in chronological order */ -+ for (j = 0; j < num; readi = (readi + 1) % LOGSIZE, j++) { -+ if (logtab[readi].fmt == NULL) { -+ continue; -+ } -+ bcmprinttstamp(logtab[readi].cycles); -+ printf(logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2); -+ printf("\n"); -+ } -+} -+ -+void -+bcmdumptslog(char *buf, int size) -+{ -+ char *limit; -+ int j = 0; -+ int num; -+ uint us, ms, sec; -+ -+ limit = buf + size - 80; -+ *buf = '\0'; -+ -+ num = logi - readi; -+ -+ if (num < 0) { -+ num += LOGSIZE; -+ } -+ -+ /* print in chronological order */ -+ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { -+ if (logtab[readi].fmt == NULL) { -+ continue; -+ } -+ us = (logtab[readi].cycles % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; -+ ms = logtab[readi].cycles / TSF_TICKS_PER_MS; -+ sec = ms / 1000; -+ ms -= sec * 1000; -+ -+ buf += snprintf(buf, (limit - buf), "%04u.%03u.%03u ", sec, ms, us); -+ /* buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); */ -+ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, -+ logtab[readi].a2); -+ buf += snprintf(buf, (limit - buf), "\n"); -+ } -+} -+#endif /* BCMTSTAMPEDLOGS */ -+ -+#if defined(BCMDBG) || defined(DHD_DEBUG) -+/* pretty hex print a pkt buffer chain */ -+void -+prpkt(const char *msg, osl_t *osh, void *p0) -+{ -+ void *p; -+ -+ if (msg && (msg[0] != '\0')) { -+ printf("%s:\n", msg); -+ } -+ -+ for (p = p0; p; p = PKTNEXT(osh, p)) { -+ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); -+ } -+} -+#endif /* BCMDBG || DHD_DEBUG */ -+ -+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. -+ * Also updates the inplace vlan tag if requested. -+ * For debugging, it returns an indication of what it did. -+ */ -+uint BCMFASTPATH -+pktsetprio(void *pkt, bool update_vtag) -+{ -+ struct ether_header *eh; -+ struct ethervlan_header *evh; -+ uint8 *pktdata; -+ int priority = 0; -+ int rc = 0; -+ -+ pktdata = (uint8 *)PKTDATA(NULL, pkt); -+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); -+ -+ eh = (struct ether_header *) pktdata; -+ -+ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { -+ uint16 vlan_tag; -+ int vlan_prio, dscp_prio = 0; -+ -+ evh = (struct ethervlan_header *)eh; -+ -+ vlan_tag = ntoh16(evh->vlan_tag); -+ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; -+ -+ if (evh->ether_type == hton16(ETHER_TYPE_IP)) { -+ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); -+ uint8 tos_tc = IP_TOS46(ip_body); -+ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); -+ } -+ -+ /* DSCP priority gets precedence over 802.1P (vlan tag) */ -+ if (dscp_prio != 0) { -+ priority = dscp_prio; -+ rc |= PKTPRIO_VDSCP; -+ } else { -+ priority = vlan_prio; -+ rc |= PKTPRIO_VLAN; -+ } -+ /* -+ * If the DSCP priority is not the same as the VLAN priority, -+ * then overwrite the priority field in the vlan tag, with the -+ * DSCP priority value. This is required for Linux APs because -+ * the VLAN driver on Linux, overwrites the skb->priority field -+ * with the priority value in the vlan tag -+ */ -+ if (update_vtag && (priority != vlan_prio)) { -+ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); -+ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; -+ evh->vlan_tag = hton16(vlan_tag); -+ rc |= PKTPRIO_UPD; -+ } -+ } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { -+ uint8 *ip_body = pktdata + sizeof(struct ether_header); -+ uint8 tos_tc = IP_TOS46(ip_body); -+ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); -+ rc |= PKTPRIO_DSCP; -+ } -+ -+ ASSERT(priority >= 0 && priority <= MAXPRIO); -+ PKTSETPRIO(pkt, priority); -+ return (rc | priority); -+} -+ -+#ifndef BCM_BOOTLOADER -+ -+static char bcm_undeferrstr[32]; -+static const char *const bcmerrorstrtable[] = BCMERRSTRINGTABLE; -+ -+/* Convert the error codes into related error strings */ -+const char * -+bcmerrorstr(int bcmerror) -+{ -+ /* check if someone added a bcmerror code but forgot to add errorstring */ -+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); -+ -+ if (bcmerror > 0 || bcmerror < BCME_LAST) { -+ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); -+ return bcm_undeferrstr; -+ } -+ -+ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); -+ -+ return bcmerrorstrtable[-bcmerror]; -+} -+ -+#endif /* !BCM_BOOTLOADER */ -+ -+#ifdef WLC_LOW -+static void -+BCMINITFN(bcm_nvram_refresh)(char *flash) -+{ -+ int i; -+ int ret = 0; -+ -+ ASSERT(flash != NULL); -+ -+ /* default "empty" vars cache */ -+ bzero(flash, 2); -+ -+ if ((ret = nvram_getall(flash, NVRAM_SPACE))) { -+ return; -+ } -+ -+ /* determine nvram length */ -+ for (i = 0; i < NVRAM_SPACE; i++) { -+ if (flash[i] == '\0' && flash[i+1] == '\0') { -+ break; -+ } -+ } -+ -+ if (i > 1) { -+ vars_len = i + 2; -+ } else { -+ vars_len = 0; -+ } -+} -+ -+char * -+bcm_nvram_vars(uint *length) -+{ -+ /* cache may be stale if nvram is read/write */ -+ if (nvram_vars) { -+ ASSERT(!bcmreclaimed); -+ bcm_nvram_refresh(nvram_vars); -+ } -+ if (length) { -+ *length = vars_len; -+ } -+ return nvram_vars; -+} -+ -+/* copy nvram vars into locally-allocated multi-string array */ -+int -+BCMINITFN(bcm_nvram_cache)(void *sih) -+{ -+ int ret = 0; -+ void *osh; -+ char *flash = NULL; -+ -+ if (vars_len >= 0) { -+ bcm_nvram_refresh(nvram_vars); -+ return 0; -+ } -+ -+ osh = si_osh((si_t *)sih); -+ -+ /* allocate memory and read in flash */ -+ if (!(flash = MALLOC(osh, NVRAM_SPACE))) { -+ ret = BCME_NOMEM; -+ goto exit; -+ } -+ -+ bcm_nvram_refresh(flash); -+ -+ /* cache must be full size of nvram if read/write */ -+ nvram_vars = flash; -+ -+exit: -+ return ret; -+} -+#endif /* WLC_LOW */ -+ -+ -+int32 -+exthdr_validate(char *ptr, uint size) -+{ -+ char *exthdr, *trx_offset; -+ uint hdrsz; -+ int trxof = 0; -+ -+ if ((exthdr = nvram_get("ext_imghdr"))) { -+ char s[] = "XXX"; -+ uint i, j; -+ -+ hdrsz = strlen(exthdr); -+ -+ if (hdrsz > size) { -+ printf("Exthdr_size(%d) > Image_size(%d)\n", hdrsz, size); -+ trxof = -1; -+ goto done; -+ } -+ -+ if (hdrsz == 0) { -+ goto match; -+ } -+ -+ for (i = 0, j = 0; i < (hdrsz >> 1); i++) { -+ sprintf(s, "%02x", (ptr[i] & 0xff)); -+ if ((exthdr[j++] != s[0]) || (exthdr[j++] != s[1])) { -+ printf("Header mismatch\n"); -+ goto done; -+ } -+ } -+ } -+ -+match: -+ if ((trx_offset = nvram_get("trx_offset"))) -+ trxof = bcm_strtoul(trx_offset, NULL, 0); -+ -+done: -+ return trxof; -+} -+ -+/* iovar table lookup */ -+const bcm_iovar_t* -+bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) -+{ -+ const bcm_iovar_t *vi; -+ const char *lookup_name; -+ -+ /* skip any ':' delimited option prefixes */ -+ lookup_name = strrchr(name, ':'); -+ if (lookup_name != NULL) { -+ lookup_name++; -+ } else { -+ lookup_name = name; -+ } -+ -+ ASSERT(table != NULL); -+ -+ for (vi = table; vi->name; vi++) { -+ if (!strcmp(vi->name, lookup_name)) { -+ return vi; -+ } -+ } -+ /* ran to end of table */ -+ -+ return NULL; /* var name not found */ -+} -+ -+int -+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) -+{ -+ int bcmerror = 0; -+ -+ /* length check on io buf */ -+ switch (vi->type) { -+ case IOVT_BOOL: -+ case IOVT_INT8: -+ case IOVT_INT16: -+ case IOVT_INT32: -+ case IOVT_UINT8: -+ case IOVT_UINT16: -+ case IOVT_UINT32: -+ /* all integers are int32 sized args at the ioctl interface */ -+ if (len < (int)sizeof(int)) { -+ bcmerror = BCME_BUFTOOSHORT; -+ } -+ break; -+ -+ case IOVT_BUFFER: -+ /* buffer must meet minimum length requirement */ -+ if (len < vi->minlen) { -+ bcmerror = BCME_BUFTOOSHORT; -+ } -+ break; -+ -+ case IOVT_VOID: -+ if (!set) { -+ /* Cannot return nil... */ -+ bcmerror = BCME_UNSUPPORTED; -+ } else if (len) { -+ /* Set is an action w/o parameters */ -+ bcmerror = BCME_BUFTOOLONG; -+ } -+ break; -+ -+ default: -+ /* unknown type for length check in iovar info */ -+ ASSERT(0); -+ bcmerror = BCME_UNSUPPORTED; -+ } -+ -+ return bcmerror; -+} -+#endif /* BCMDRIVER */ -+ -+ -+/******************************************************************************* -+ * crc8 -+ * -+ * Computes a crc8 over the input data using the polynomial: -+ * -+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 -+ * -+ * The caller provides the initial value (either CRC8_INIT_VALUE -+ * or the previous returned value) to allow for processing of -+ * discontiguous blocks of data. When generating the CRC the -+ * caller is responsible for complementing the final return value -+ * and inserting it into the byte stream. When checking, a final -+ * return value of CRC8_GOOD_VALUE indicates a valid CRC. -+ * -+ * Reference: Dallas Semiconductor Application Note 27 -+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", -+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., -+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt -+ * -+ * **************************************************************************** -+ */ -+ -+static const uint8 crc8_table[256] = { -+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, -+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, -+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, -+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, -+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, -+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, -+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, -+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, -+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, -+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, -+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, -+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, -+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, -+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, -+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, -+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, -+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, -+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, -+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, -+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, -+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, -+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, -+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, -+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, -+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, -+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, -+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, -+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, -+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, -+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, -+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, -+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F -+}; -+ -+#define CRC_INNER_LOOP(n, c, x) \ -+ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] -+ -+uint8 -+BCMROMFN(hndcrc8)( -+ uint8 *pdata, /* pointer to array of data to process */ -+ uint nbytes, /* number of input data bytes to process */ -+ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ -+) -+{ -+ /* hard code the crc loop instead of using CRC_INNER_LOOP macro -+ * to avoid the undefined and unnecessary (uint8 >> 8) operation. -+ */ -+ while (nbytes-- > 0) { -+ crc = crc8_table[(crc ^ *pdata++) & 0xff]; -+ } -+ -+ return crc; -+} -+ -+/******************************************************************************* -+ * crc16 -+ * -+ * Computes a crc16 over the input data using the polynomial: -+ * -+ * x^16 + x^12 +x^5 + 1 -+ * -+ * The caller provides the initial value (either CRC16_INIT_VALUE -+ * or the previous returned value) to allow for processing of -+ * discontiguous blocks of data. When generating the CRC the -+ * caller is responsible for complementing the final return value -+ * and inserting it into the byte stream. When checking, a final -+ * return value of CRC16_GOOD_VALUE indicates a valid CRC. -+ * -+ * Reference: Dallas Semiconductor Application Note 27 -+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", -+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., -+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt -+ * -+ * **************************************************************************** -+ */ -+ -+static const uint16 crc16_table[256] = { -+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, -+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, -+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, -+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, -+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, -+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, -+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, -+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, -+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, -+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, -+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, -+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, -+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, -+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, -+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, -+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, -+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, -+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, -+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, -+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, -+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, -+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, -+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, -+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, -+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, -+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, -+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, -+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, -+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, -+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, -+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, -+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 -+}; -+ -+uint16 -+BCMROMFN(hndcrc16)( -+ uint8 *pdata, /* pointer to array of data to process */ -+ uint nbytes, /* number of input data bytes to process */ -+ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ -+) -+{ -+ while (nbytes-- > 0) { -+ CRC_INNER_LOOP(16, crc, *pdata++); -+ } -+ return crc; -+} -+ -+static const uint32 crc32_table[256] = { -+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, -+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, -+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, -+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, -+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, -+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, -+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, -+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, -+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, -+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, -+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, -+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, -+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, -+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, -+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, -+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, -+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, -+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, -+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, -+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, -+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, -+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, -+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, -+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, -+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, -+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, -+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, -+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, -+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, -+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, -+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, -+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, -+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, -+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, -+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, -+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, -+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, -+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, -+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, -+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, -+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, -+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, -+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, -+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, -+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, -+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, -+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, -+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, -+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, -+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, -+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, -+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, -+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, -+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, -+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, -+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, -+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, -+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, -+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, -+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, -+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, -+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, -+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, -+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -+}; -+ -+/* -+ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if -+ * accumulating over multiple pieces. -+ */ -+uint32 -+BCMROMFN(hndcrc32)(uint8 *pdata, uint nbytes, uint32 crc) -+{ -+ uint8 *pend; -+#ifdef __mips__ -+ uint8 tmp[4]; -+ ulong *tptr = (ulong *)tmp; -+ -+ if (nbytes > 3) { -+ /* in case the beginning of the buffer isn't aligned */ -+ pend = (uint8 *)((uint)(pdata + 3) & ~0x3); -+ nbytes -= (pend - pdata); -+ while (pdata < pend) { -+ CRC_INNER_LOOP(32, crc, *pdata++); -+ } -+ } -+ -+ if (nbytes > 3) { -+ /* handle bulk of data as 32-bit words */ -+ pend = pdata + (nbytes & ~0x3); -+ while (pdata < pend) { -+ *tptr = *(ulong *)pdata; -+ pdata += sizeof(ulong *); -+ CRC_INNER_LOOP(32, crc, tmp[0]); -+ CRC_INNER_LOOP(32, crc, tmp[1]); -+ CRC_INNER_LOOP(32, crc, tmp[2]); -+ CRC_INNER_LOOP(32, crc, tmp[3]); -+ } -+ } -+ -+ /* 1-3 bytes at end of buffer */ -+ pend = pdata + (nbytes & 0x03); -+ while (pdata < pend) { -+ CRC_INNER_LOOP(32, crc, *pdata++); -+ } -+#else -+ pend = pdata + nbytes; -+ while (pdata < pend) { -+ CRC_INNER_LOOP(32, crc, *pdata++); -+ } -+#endif /* __mips__ */ -+ -+ return crc; -+} -+ -+#ifdef notdef -+#define CLEN 1499 /* CRC Length */ -+#define CBUFSIZ (CLEN+4) -+#define CNBUFS 5 /* # of bufs */ -+ -+void -+testcrc32(void) -+{ -+ uint j, k, l; -+ uint8 *buf; -+ uint len[CNBUFS]; -+ uint32 crcr; -+ uint32 crc32tv[CNBUFS] = -+ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; -+ -+ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); -+ -+ /* step through all possible alignments */ -+ for (l = 0; l <= 4; l++) { -+ for (j = 0; j < CNBUFS; j++) { -+ len[j] = CLEN; -+ for (k = 0; k < len[j]; k++) { -+ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; -+ } -+ } -+ -+ for (j = 0; j < CNBUFS; j++) { -+ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); -+ ASSERT(crcr == crc32tv[j]); -+ } -+ } -+ -+ MFREE(buf, CBUFSIZ*CNBUFS); -+ return; -+} -+#endif /* notdef */ -+ -+/* -+ * Advance from the current 1-byte tag/1-byte length/variable-length value -+ * triple, to the next, returning a pointer to the next. -+ * If the current or next TLV is invalid (does not fit in given buffer length), -+ * NULL is returned. -+ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented -+ * by the TLV parameter's length if it is valid. -+ */ -+bcm_tlv_t * -+BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen) -+{ -+ int len; -+ -+ /* validate current elt */ -+ if (!bcm_valid_tlv(elt, *buflen)) { -+ return NULL; -+ } -+ -+ /* advance to next elt */ -+ len = elt->len; -+ elt = (bcm_tlv_t*)(elt->data + len); -+ *buflen -= (TLV_HDR_LEN + len); -+ -+ /* validate next elt */ -+ if (!bcm_valid_tlv(elt, *buflen)) { -+ return NULL; -+ } -+ -+ return elt; -+} -+ -+/* -+ * Traverse a string of 1-byte tag/1-byte length/variable-length value -+ * triples, returning a pointer to the substring whose first element -+ * matches tag -+ */ -+bcm_tlv_t * -+BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key) -+{ -+ bcm_tlv_t *elt; -+ int totlen; -+ -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; -+ -+ /* find tagged parameter */ -+ while (totlen >= TLV_HDR_LEN) { -+ int len = elt->len; -+ -+ /* validate remaining totlen */ -+ if ((elt->id == key) && -+ (totlen >= (len + TLV_HDR_LEN))) { -+ return (elt); -+ } -+ -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); -+ totlen -= (len + TLV_HDR_LEN); -+ } -+ -+ return NULL; -+} -+ -+/* -+ * Traverse a string of 1-byte tag/1-byte length/variable-length value -+ * triples, returning a pointer to the substring whose first element -+ * matches tag. Stop parsing when we see an element whose ID is greater -+ * than the target key. -+ */ -+bcm_tlv_t * -+BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key) -+{ -+ bcm_tlv_t *elt; -+ int totlen; -+ -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; -+ -+ /* find tagged parameter */ -+ while (totlen >= TLV_HDR_LEN) { -+ uint id = elt->id; -+ int len = elt->len; -+ -+ /* Punt if we start seeing IDs > than target key */ -+ if (id > key) { -+ return (NULL); -+ } -+ -+ /* validate remaining totlen */ -+ if ((id == key) && -+ (totlen >= (len + TLV_HDR_LEN))) { -+ return (elt); -+ } -+ -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); -+ totlen -= (len + TLV_HDR_LEN); -+ } -+ return NULL; -+} -+ -+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(WLMSG_PRHDRS) || \ -+ defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || defined(DHD_DEBUG) -+int -+bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) -+{ -+ int i; -+ char* p = buf; -+ char hexstr[16]; -+ int slen = 0, nlen = 0; -+ uint32 bit; -+ const char* name; -+ -+ if (len < 2 || !buf) { -+ return 0; -+ } -+ -+ buf[0] = '\0'; -+ -+ for (i = 0; flags != 0; i++) { -+ bit = bd[i].bit; -+ name = bd[i].name; -+ if (bit == 0 && flags != 0) { -+ /* print any unnamed bits */ -+ snprintf(hexstr, 16, "0x%X", flags); -+ name = hexstr; -+ flags = 0; /* exit loop */ -+ } else if ((flags & bit) == 0) { -+ continue; -+ } -+ flags &= ~bit; -+ nlen = strlen(name); -+ slen += nlen; -+ /* count btwn flag space */ -+ if (flags != 0) { -+ slen += 1; -+ } -+ /* need NULL char as well */ -+ if (len <= slen) { -+ break; -+ } -+ /* copy NULL char but don't count it */ -+ strncpy(p, name, nlen + 1); -+ p += nlen; -+ /* copy btwn flag space and NULL char */ -+ if (flags != 0) { -+ p += snprintf(p, 2, " "); -+ } -+ } -+ -+ /* indicate the str was too short */ -+ if (flags != 0) { -+ if (len < 2) { -+ p -= 2 - len; /* overwrite last char */ -+ } -+ p += snprintf(p, 2, ">"); -+ } -+ -+ return (int)(p - buf); -+} -+ -+/* print bytes formatted as hex to a string. return the resulting string length */ -+int -+bcm_format_hex(char *str, const void *bytes, int len) -+{ -+ int i; -+ char *p = str; -+ const uint8 *src = (const uint8*)bytes; -+ -+ for (i = 0; i < len; i++) { -+ p += snprintf(p, 3, "%02X", *src); -+ src++; -+ } -+ return (int)(p - str); -+} -+#endif -+ -+/* pretty hex print a contiguous buffer */ -+void -+prhex(const char *msg, uchar *buf, uint nbytes) -+{ -+ char line[128], *p; -+ int len = sizeof(line); -+ int nchar; -+ uint i; -+ -+ if (msg && (msg[0] != '\0')) { -+ printf("%s:\n", msg); -+ } -+ -+ p = line; -+ for (i = 0; i < nbytes; i++) { -+ if (i % 16 == 0) { -+ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ -+ p += nchar; -+ len -= nchar; -+ } -+ if (len > 0) { -+ nchar = snprintf(p, len, "%02x ", buf[i]); -+ p += nchar; -+ len -= nchar; -+ } -+ -+ if (i % 16 == 15) { -+ printf("%s\n", line); /* flush line */ -+ p = line; -+ len = sizeof(line); -+ } -+ } -+ -+ /* flush last partial line */ -+ if (p != line) { -+ printf("%s\n", line); -+ } -+} -+ -+static const char *crypto_algo_names[] = { -+ "NONE", -+ "WEP1", -+ "TKIP", -+ "WEP128", -+ "AES_CCM", -+ "AES_OCB_MSDU", -+ "AES_OCB_MPDU", -+ "NALG" -+ "UNDEF", -+ "UNDEF", -+ "UNDEF", -+ "UNDEF" -+}; -+ -+const char * -+bcm_crypto_algo_name(uint algo) -+{ -+ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; -+} -+ -+#ifdef BCMDBG -+void -+deadbeef(void *p, size_t len) -+{ -+ static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef }; -+ -+ while (len-- > 0) { -+ *(uint8*)p = meat[((uintptr)p) & 3]; -+ p = (uint8*)p + 1; -+ } -+} -+#endif /* BCMDBG */ -+ -+char * -+bcm_chipname(uint chipid, char *buf, uint len) -+{ -+ const char *fmt; -+ -+ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; -+ snprintf(buf, len, fmt, chipid); -+ return buf; -+} -+ -+/* Produce a human-readable string for boardrev */ -+char * -+bcm_brev_str(uint32 brev, char *buf) -+{ -+ if (brev < 0x100) { -+ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); -+ } else { -+ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); -+ } -+ return (buf); -+} -+ -+#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ -+ -+/* dump large strings to console */ -+void -+printbig(char *buf) -+{ -+ uint len, max_len; -+ char c; -+ -+ len = strlen(buf); -+ -+ max_len = BUFSIZE_TODUMP_ATONCE; -+ -+ while (len > max_len) { -+ c = buf[max_len]; -+ buf[max_len] = '\0'; -+ printf("%s", buf); -+ buf[max_len] = c; -+ -+ buf += max_len; -+ len -= max_len; -+ } -+ /* print the remaining string */ -+ printf("%s\n", buf); -+ return; -+} -+ -+/* routine to dump fields in a fileddesc structure */ -+uint -+bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, -+ char *buf, uint32 bufsize) -+{ -+ uint filled_len; -+ int len; -+ struct fielddesc *cur_ptr; -+ -+ filled_len = 0; -+ cur_ptr = fielddesc_array; -+ -+ while (bufsize > 1) { -+ if (cur_ptr->nameandfmt == NULL) { -+ break; -+ } -+ len = snprintf(buf, bufsize, cur_ptr->nameandfmt, -+ read_rtn(arg0, arg1, cur_ptr->offset)); -+ /* check for snprintf overflow or error */ -+ if (len < 0 || (uint32)len >= bufsize) { -+ len = bufsize - 1; -+ } -+ buf += len; -+ bufsize -= len; -+ filled_len += len; -+ cur_ptr++; -+ } -+ return filled_len; -+} -+ -+uint -+bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) -+{ -+ uint len; -+ -+ len = strlen(name) + 1; -+ -+ if ((len + datalen) > buflen) { -+ return 0; -+ } -+ -+ strncpy(buf, name, buflen); -+ -+ /* append data onto the end of the name string */ -+ memcpy(&buf[len], data, datalen); -+ len += datalen; -+ -+ return len; -+} -+ -+/* Quarter dBm units to mW -+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 -+ * Table is offset so the last entry is largest mW value that fits in -+ * a uint16. -+ */ -+ -+#define QDBM_OFFSET 153 /* Offset for first entry */ -+#define QDBM_TABLE_LEN 40 /* Table size */ -+ -+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. -+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 -+ */ -+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ -+ -+/* Largest mW value that will round down to the last table entry, -+ * QDBM_OFFSET + QDBM_TABLE_LEN-1. -+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. -+ */ -+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ -+ -+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -+}; -+ -+uint16 -+BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm) -+{ -+ uint factor = 1; -+ int idx = qdbm - QDBM_OFFSET; -+ -+ if (idx >= QDBM_TABLE_LEN) { -+ /* clamp to max uint16 mW value */ -+ return 0xFFFF; -+ } -+ -+ /* scale the qdBm index up to the range of the table 0-40 -+ * where an offset of 40 qdBm equals a factor of 10 mW. -+ */ -+ while (idx < 0) { -+ idx += 40; -+ factor *= 10; -+ } -+ -+ /* return the mW value scaled down to the correct factor of 10, -+ * adding in factor/2 to get proper rounding. -+ */ -+ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); -+} -+ -+uint8 -+BCMROMFN(bcm_mw_to_qdbm)(uint16 mw) -+{ -+ uint8 qdbm; -+ int offset; -+ uint mw_uint = mw; -+ uint boundary; -+ -+ /* handle boundary case */ -+ if (mw_uint <= 1) { -+ return 0; -+ } -+ -+ offset = QDBM_OFFSET; -+ -+ /* move mw into the range of the table */ -+ while (mw_uint < QDBM_TABLE_LOW_BOUND) { -+ mw_uint *= 10; -+ offset -= 40; -+ } -+ -+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { -+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - -+ nqdBm_to_mW_map[qdbm])/2; -+ if (mw_uint < boundary) break; -+ } -+ -+ qdbm += (uint8)offset; -+ -+ return (qdbm); -+} -+ -+ -+uint -+BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint length) -+{ -+ uint bitcount = 0, i; -+ uint8 tmp; -+ for (i = 0; i < length; i++) { -+ tmp = bitmap[i]; -+ while (tmp) { -+ bitcount++; -+ tmp &= (tmp - 1); -+ } -+ } -+ return bitcount; -+} -+ -+#ifdef BCMDRIVER -+ -+/* Initialization of bcmstrbuf structure */ -+void -+bcm_binit(struct bcmstrbuf *b, char *buf, uint size) -+{ -+ b->origsize = b->size = size; -+ b->origbuf = b->buf = buf; -+} -+ -+/* Buffer sprintf wrapper to guard against buffer overflow */ -+int -+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) -+{ -+ va_list ap; -+ int r; -+ -+ va_start(ap, fmt); -+ -+ r = vsnprintf(b->buf, b->size, fmt, ap); -+ -+ /* Non Ansi C99 compliant returns -1, -+ * Ansi compliant return r >= b->size, -+ * bcmstdlib returns 0, handle all -+ */ -+ /* r == 0 is also the case when strlen(fmt) is zero. -+ * typically the case when "" is passed as argument. -+ */ -+ if ((r == -1) || (r >= (int)b->size)) { -+ b->size = 0; -+ } else { -+ b->size -= r; -+ b->buf += r; -+ } -+ -+ va_end(ap); -+ -+ return r; -+} -+ -+void -+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len) -+{ -+ int i; -+ -+ if (msg != NULL && msg[0] != '\0') { -+ bcm_bprintf(b, "%s", msg); -+ } -+ for (i = 0; i < len; i ++) { -+ bcm_bprintf(b, "%02X", buf[i]); -+ } -+ if (newline) { -+ bcm_bprintf(b, "\n"); -+ } -+} -+ -+void -+bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) -+{ -+ int i; -+ -+ for (i = 0; i < num_bytes; i++) { -+ num[i] += amount; -+ if (num[i] >= amount) { -+ break; -+ } -+ amount = 1; -+ } -+} -+ -+int -+bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) -+{ -+ int i; -+ -+ for (i = nbytes - 1; i >= 0; i--) { -+ if (arg1[i] != arg2[i]) { -+ return (arg1[i] - arg2[i]); -+ } -+ } -+ return 0; -+} -+ -+void -+bcm_print_bytes(const char *name, const uchar *data, int len) -+{ -+ int i; -+ int per_line = 0; -+ -+ printf("%s: %d \n", name ? name : "", len); -+ for (i = 0; i < len; i++) { -+ printf("%02x ", *data++); -+ per_line++; -+ if (per_line == 16) { -+ per_line = 0; -+ printf("\n"); -+ } -+ } -+ printf("\n"); -+} -+#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ -+ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) -+#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) -+ -+int -+bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) -+{ -+ uint i, c; -+ char *p = buf; -+ char *endp = buf + SSID_FMT_BUF_LEN; -+ -+ if (ssid_len > DOT11_MAX_SSID_LEN) { -+ ssid_len = DOT11_MAX_SSID_LEN; -+ } -+ -+ for (i = 0; i < ssid_len; i++) { -+ c = (uint)ssid[i]; -+ if (c == '\\') { -+ *p++ = '\\'; -+ *p++ = '\\'; -+ } else if (bcm_isprint((uchar)c)) { -+ *p++ = (char)c; -+ } else { -+ p += snprintf(p, (endp - p), "\\x%02X", c); -+ } -+ } -+ *p = '\0'; -+ ASSERT(p < endp); -+ -+ return (int)(p - buf); -+} -+#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ -+ -+#endif /* BCMDRIVER */ -+ -+/* -+ * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. -+ * also accepts nvram files which are already in the format of =\0\=\0 -+ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. -+ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. -+*/ -+ -+unsigned int -+process_nvram_vars(char *varbuf, unsigned int len) -+{ -+ char *dp; -+ bool findNewline; -+ int column; -+ unsigned int buf_len, n; -+ unsigned int pad = 0; -+ -+ dp = varbuf; -+ -+ findNewline = FALSE; -+ column = 0; -+ -+ for (n = 0; n < len; n++) { -+ if (varbuf[n] == '\r') { -+ continue; -+ } -+ if (findNewline && varbuf[n] != '\n') { -+ continue; -+ } -+ findNewline = FALSE; -+ if (varbuf[n] == '#') { -+ findNewline = TRUE; -+ continue; -+ } -+ if (varbuf[n] == '\n') { -+ if (column == 0) { -+ continue; -+ } -+ *dp++ = 0; -+ column = 0; -+ continue; -+ } -+ *dp++ = varbuf[n]; -+ column++; -+ } -+ buf_len = (unsigned int)(dp - varbuf); -+ if (buf_len % 4) { -+ pad = 4 - buf_len % 4; -+ if (pad && (buf_len + pad <= len)) { -+ buf_len += pad; -+ } -+ } -+ -+ while (dp < varbuf + n) { -+ *dp++ = 0; -+ } -+ -+ return buf_len; -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.c 2017-11-09 17:53:44.032304000 +0800 -@@ -0,0 +1,18 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Greyhound2 sudo EROM -+ * -+ */ -+#include -+ -+uint32 gh2_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18042005, 0x181100c5, -+ 0x4bf82d01, 0x04004211, 0x00000203, 0x1804a005, 0x181110c5, -+ 0x0000000f -+}; -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/gh2_erom.h 2017-11-09 17:53:44.033296000 +0800 -@@ -0,0 +1,14 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Greyhound2 sudo EROM -+ * -+ */ -+ -+#ifndef _gh2_erom_h_ -+#define _gh2_erom_h_ -+ -+extern uint32 gh2_erom[]; -+ -+#endif /* _gh2_erom_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.c 2017-11-09 17:53:44.034292000 +0800 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Greyhound sudo EROM -+ * -+ */ -+#include -+ -+uint32 gh_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18042005, 0x181100c5, -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/gh_erom.h 2017-11-09 17:53:44.035289000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Greyhound sudo EROM -+ * -+ */ -+ -+#ifndef _gh_erom_h_ -+#define _gh_erom_h_ -+ -+extern uint32 gh_erom[]; -+ -+#endif /* _gh_erom_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hnddma.c b/drivers/net/ethernet/broadcom/gmac/src/shared/hnddma.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hnddma.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hnddma.c 2017-11-09 17:53:44.045302000 +0800 -@@ -0,0 +1,3701 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Generic Broadcom Home Networking Division (HND) DMA module. -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * $Id: hnddma.c 328477 2012-04-19 10:57:54Z $ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+#include -+#endif -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_RWREG_OPT -+#ifdef R_REG -+#undef R_REG -+#define R_REG(osh, r) (\ -+ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r)) : \ -+ (*(volatile unsigned int __force *)(r)) \ -+) -+#endif /* R_REG */ -+ -+#ifdef W_REG -+#undef W_REG -+#define W_REG(osh, r, v) (\ -+ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r) = (v)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r) = (v)) : \ -+ (*(volatile unsigned int __force *)(r) = (v)) \ -+) -+#endif /* W_REG */ -+#endif /* CONFIG_BCM_IPROC_GMAC_RWREG_OPT */ -+ -+/* debug/trace */ -+#ifdef BCMDBG -+#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args -+#define DMA_TRACE(args) if (!(*di->msg_level & 2)); else printf args -+#elif defined(BCMDBG_ERR) -+#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args -+#define DMA_TRACE(args) -+#else -+#define DMA_ERROR(args) -+#define DMA_TRACE(args) -+#endif /* BCMDBG */ -+ -+#define DMA_NONE(args) -+ -+ -+#define d32txregs dregs.d32_u.txregs_32 -+#define d32rxregs dregs.d32_u.rxregs_32 -+#define txd32 dregs.d32_u.txd_32 -+#define rxd32 dregs.d32_u.rxd_32 -+ -+#define d64txregs dregs.d64_u.txregs_64 -+#define d64rxregs dregs.d64_u.rxregs_64 -+#define txd64 dregs.d64_u.txd_64 -+#define rxd64 dregs.d64_u.rxd_64 -+ -+#define DBG(x...) printk(KERN_ERR x) -+ -+/* default dma message level (if input msg_level pointer is null in dma_attach()) */ -+#ifdef BCMDBG_ERR -+static uint dma_msg_level = 1; -+#else -+static uint dma_msg_level = 0; -+#endif /* BCMDBG_ERR */ -+ -+#define MAXNAMEL 8 /* 8 char names */ -+ -+#define DI_INFO(dmah) ((dma_info_t *)dmah) -+ -+/* dma engine software state */ -+typedef struct dma_info { -+ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, -+ * which could be const -+ */ -+ uint *msg_level; /* message level pointer */ -+ char name[MAXNAMEL]; /* callers name for diag msgs */ -+ -+ void *osh; /* os handle */ -+ si_t *sih; /* sb handle */ -+ -+ bool dma64; /* this dma engine is operating in 64-bit mode */ -+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ -+ -+ union { -+ struct { -+ dma32regs_t *txregs_32; /* 32-bit dma tx engine registers */ -+ dma32regs_t *rxregs_32; /* 32-bit dma rx engine registers */ -+ dma32dd_t *txd_32; /* pointer to dma32 tx descriptor ring */ -+ dma32dd_t *rxd_32; /* pointer to dma32 rx descriptor ring */ -+ } d32_u; -+ struct { -+ dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */ -+ dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */ -+ dma64dd_t *txd_64; /* pointer to dma64 tx descriptor ring */ -+ dma64dd_t *rxd_64; /* pointer to dma64 rx descriptor ring */ -+ } d64_u; -+ } dregs; -+ -+ uint16 dmadesc_align; /* alignment requirement for dma descriptors */ -+ -+ uint16 ntxd; /* # tx descriptors tunable */ -+ uint16 txin; /* index of next descriptor to reclaim */ -+ uint16 txout; /* index of next descriptor to post */ -+ void **txp; /* pointer to parallel array of pointers to packets */ -+ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ -+ hnddma_seg_map_t *txp_dmah; /* DMA MAP meta-data handle */ -+ dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */ -+ dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */ -+ uint16 txdalign; /* #bytes added to alloc'd mem to align txd */ -+ uint32 txdalloc; /* #bytes allocated for the ring */ -+ uint32 xmtptrbase; /* When using unaligned descriptors, the ptr register -+ * is not just an index, it needs all 13 bits to be -+ * an offset from the addr register. -+ */ -+ -+ uint16 nrxd; /* # rx descriptors tunable */ -+ uint16 rxin; /* index of next descriptor to reclaim */ -+ uint16 rxout; /* index of next descriptor to post */ -+ void **rxp; /* pointer to parallel array of pointers to packets */ -+ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ -+ hnddma_seg_map_t *rxp_dmah; /* DMA MAP meta-data handle */ -+ dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */ -+ dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */ -+ uint16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ -+ uint32 rxdalloc; /* #bytes allocated for the ring */ -+ uint32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ -+ -+ /* tunables */ -+ uint16 rxbufsize; /* rx buffer size in bytes, -+ * not including the extra headroom -+ */ -+ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack -+ * e.g. some rx pkt buffers will be bridged to tx side -+ * without byte copying. The extra headroom needs to be -+ * large enough to fit txheader needs. -+ * Some dongle driver may not need it. -+ */ -+ uint nrxpost; /* # rx buffers to keep posted */ -+ uint rxoffset; /* rxcontrol offset */ -+ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ -+ uint ddoffsethigh; /* high 32 bits */ -+ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ -+ uint dataoffsethigh; /* high 32 bits */ -+ bool aligndesc_4k; /* descriptor base need to be aligned or not */ -+ uint8 rxburstlen; /* burstlen field for rx (for cores supporting burstlen) */ -+ uint8 txburstlen; /* burstlen field for tx (for cores supporting burstlen) */ -+ uint8 txmultioutstdrd; /* tx multiple outstanding reads */ -+ uint8 txprefetchctl; /* prefetch control for tx */ -+ uint8 txprefetchthresh; /* prefetch threshold for tx */ -+ uint8 rxprefetchctl; /* prefetch control for rx */ -+ uint8 rxprefetchthresh; /* prefetch threshold for rx */ -+ pktpool_t *pktpool; /* pktpool */ -+ uint dma_avoidance_cnt; -+ -+ uint32 d64_xs0_cd_mask; /* tx current descriptor pointer mask */ -+ uint32 d64_xs1_ad_mask; /* tx active descriptor mask */ -+ uint32 d64_rs0_cd_mask; /* rx current descriptor pointer mask */ -+ uint16 rs0cd; /* cached value of rcvstatus0 currdescr */ -+ uint16 xs0cd; /* cached value of xmtstatus0 currdescr */ -+ uint16 xs0cd_snapshot; /* snapshot of xmtstatus0 currdescr */ -+ spinlock_t des_lock; -+} dma_info_t; -+ -+/* -+ * If BCMDMA32 is defined, hnddma will support both 32-bit and 64-bit DMA engines. -+ * Otherwise it will support only 64-bit. -+ * -+ * DMA32_ENAB indicates whether hnddma is compiled with support for 32-bit DMA engines. -+ * DMA64_ENAB indicates whether hnddma is compiled with support for 64-bit DMA engines. -+ * -+ * DMA64_MODE indicates whether the current DMA engine is running as 64-bit. -+ */ -+#ifdef BCMDMA32 -+#define DMA32_ENAB(di) 1 -+#define DMA64_ENAB(di) 1 -+#define DMA64_MODE(di) ((di)->dma64) -+#else /* !BCMDMA32 */ -+#define DMA32_ENAB(di) 0 -+#define DMA64_ENAB(di) 1 -+#define DMA64_MODE(di) 1 -+#endif /* !BCMDMA32 */ -+ -+/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */ -+#ifdef BCMDMASGLISTOSL -+#define DMASGLIST_ENAB TRUE -+#else -+#define DMASGLIST_ENAB FALSE -+#endif /* BCMDMASGLISTOSL */ -+ -+/* descriptor bumping macros */ -+#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ -+#define TXD(x) XXD((x), di->ntxd) -+#define RXD(x) XXD((x), di->nrxd) -+#define NEXTTXD(i) TXD((i) + 1) -+#define PREVTXD(i) TXD((i) - 1) -+#define NEXTRXD(i) RXD((i) + 1) -+#define PREVRXD(i) RXD((i) - 1) -+ -+#define NTXDACTIVE(h, t) TXD((t) - (h)) -+#define NRXDACTIVE(h, t) RXD((t) - (h)) -+ -+/* macros to convert between byte offsets and indexes */ -+#define B2I(bytes, type) ((uint16)((bytes) / sizeof(type))) -+#define I2B(index, type) ((index) * sizeof(type)) -+ -+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -+#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ -+ -+#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ -+#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ -+ -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+#define SKB_PREFETCH_LEN (128) -+#endif -+ -+/* Common prototypes */ -+static bool _dma_isaddrext(dma_info_t *di); -+static bool _dma_descriptor_align(dma_info_t *di); -+static bool _dma_alloc(dma_info_t *di, uint direction); -+static void _dma_detach(dma_info_t *di); -+static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa); -+static void _dma_rxinit(dma_info_t *di); -+static void *_dma_rx(dma_info_t *di); -+static bool _dma_rxfill(dma_info_t *di); -+static void _dma_rxreclaim(dma_info_t *di); -+static void _dma_rxenable(dma_info_t *di); -+static void *_dma_getnextrxp(dma_info_t *di, bool forceall); -+static void _dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize); -+ -+static void _dma_txblock(dma_info_t *di); -+static void _dma_txunblock(dma_info_t *di); -+static uint _dma_txactive(dma_info_t *di); -+static uint _dma_rxactive(dma_info_t *di); -+static uint _dma_activerxbuf(dma_info_t *di); -+static uint _dma_txpending(dma_info_t *di); -+static uint _dma_txcommitted(dma_info_t *di); -+ -+static void *_dma_peeknexttxp(dma_info_t *di); -+static int _dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range); -+static void *_dma_peeknextrxp(dma_info_t *di); -+static uintptr _dma_getvar(dma_info_t *di, const char *name); -+static void _dma_counterreset(dma_info_t *di); -+static void _dma_fifoloopbackenable(dma_info_t *di); -+static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags); -+static uint8 dma_align_sizetobits(uint size); -+static void *dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, -+ dmaaddr_t *descpa, osldma_t **dmah); -+static int _dma_pktpool_set(dma_info_t *di, pktpool_t *pool); -+static bool _dma_rxtx_error(dma_info_t *di, bool istx); -+static void _dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen); -+static uint _dma_avoidancecnt(dma_info_t *di); -+static void _dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval); -+static bool _dma_glom_enable(dma_info_t *di, uint32 val); -+ -+ -+/* Prototypes for 32-bit routines */ -+static bool dma32_alloc(dma_info_t *di, uint direction); -+static bool dma32_txreset(dma_info_t *di); -+static bool dma32_rxreset(dma_info_t *di); -+static bool dma32_txsuspendedidle(dma_info_t *di); -+static int dma32_txfast(dma_info_t *di, void *p0, bool commit); -+static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range); -+static void *dma32_getnextrxp(dma_info_t *di, bool forceall); -+static void dma32_txrotate(dma_info_t *di); -+static bool dma32_rxidle(dma_info_t *di); -+static void dma32_txinit(dma_info_t *di); -+static bool dma32_txenabled(dma_info_t *di); -+static void dma32_txsuspend(dma_info_t *di); -+static void dma32_txresume(dma_info_t *di); -+static bool dma32_txsuspended(dma_info_t *di); -+#ifdef WL_MULTIQUEUE -+static void dma32_txflush(dma_info_t *di); -+static void dma32_txflush_clear(dma_info_t *di); -+#endif /* WL_MULTIQUEUE */ -+static void dma32_txreclaim(dma_info_t *di, txd_range_t range); -+static bool dma32_txstopped(dma_info_t *di); -+static bool dma32_rxstopped(dma_info_t *di); -+static bool dma32_rxenabled(dma_info_t *di); -+#if defined(BCMDBG) -+static void dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, -+ uint end, uint max_num); -+static void dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+static void dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+static void dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+#endif -+ -+static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); -+ -+/* Prototypes for 64-bit routines */ -+static bool dma64_alloc(dma_info_t *di, uint direction); -+static bool dma64_txreset(dma_info_t *di); -+static bool dma64_rxreset(dma_info_t *di); -+static bool dma64_txsuspendedidle(dma_info_t *di); -+static int dma64_txfast(dma_info_t *di, void *p0, bool commit); -+static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit); -+static void *dma64_getpos(dma_info_t *di, bool direction); -+static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range); -+static void *dma64_getnextrxp(dma_info_t *di, bool forceall); -+static void dma64_txrotate(dma_info_t *di); -+ -+static bool dma64_rxidle(dma_info_t *di); -+static void dma64_txinit(dma_info_t *di); -+static bool dma64_txenabled(dma_info_t *di); -+static void dma64_txsuspend(dma_info_t *di); -+static void dma64_txresume(dma_info_t *di); -+static bool dma64_txsuspended(dma_info_t *di); -+#ifdef WL_MULTIQUEUE -+static void dma64_txflush(dma_info_t *di); -+static void dma64_txflush_clear(dma_info_t *di); -+#endif /* WL_MULTIQUEUE */ -+static void dma64_txreclaim(dma_info_t *di, txd_range_t range); -+static bool dma64_txstopped(dma_info_t *di); -+static bool dma64_rxstopped(dma_info_t *di); -+static bool dma64_rxenabled(dma_info_t *di); -+static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs); -+static int dma64_rxunframed(dma_info_t *di, void *p0, uint len, bool commit); -+ -+STATIC INLINE uint32 parity32(uint32 data); -+ -+#if defined(BCMDBG) -+static void dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, -+ uint end, uint max_num); -+static void dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+static void dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+static void dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); -+#endif -+ -+ -+const di_fcn_t dma64proc = { -+ (di_detach_t)_dma_detach, -+ (di_txinit_t)dma64_txinit, -+ (di_txreset_t)dma64_txreset, -+ (di_txenabled_t)dma64_txenabled, -+ (di_txsuspend_t)dma64_txsuspend, -+ (di_txresume_t)dma64_txresume, -+ (di_txsuspended_t)dma64_txsuspended, -+ (di_txsuspendedidle_t)dma64_txsuspendedidle, -+#ifdef WL_MULTIQUEUE -+ (di_txflush_t)dma64_txflush, -+ (di_txflush_clear_t)dma64_txflush_clear, -+#endif /* WL_MULTIQUEUE */ -+ (di_txfast_t)dma64_txfast, -+ (di_txunframed_t)dma64_txunframed, -+ (di_getpos_t)dma64_getpos, -+ (di_txstopped_t)dma64_txstopped, -+ (di_txreclaim_t)dma64_txreclaim, -+ (di_getnexttxp_t)dma64_getnexttxp, -+ (di_peeknexttxp_t)_dma_peeknexttxp, -+ (di_peekntxp_t)_dma_peekntxp, -+ (di_txblock_t)_dma_txblock, -+ (di_txunblock_t)_dma_txunblock, -+ (di_txactive_t)_dma_txactive, -+ (di_txrotate_t)dma64_txrotate, -+ -+ (di_rxinit_t)_dma_rxinit, -+ (di_rxreset_t)dma64_rxreset, -+ (di_rxidle_t)dma64_rxidle, -+ (di_rxstopped_t)dma64_rxstopped, -+ (di_rxenable_t)_dma_rxenable, -+ (di_rxenabled_t)dma64_rxenabled, -+ (di_rx_t)_dma_rx, -+ (di_rxfill_t)_dma_rxfill, -+ (di_rxreclaim_t)_dma_rxreclaim, -+ (di_getnextrxp_t)_dma_getnextrxp, -+ (di_peeknextrxp_t)_dma_peeknextrxp, -+ (di_rxparam_get_t)_dma_rx_param_get, -+ -+ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, -+ (di_getvar_t)_dma_getvar, -+ (di_counterreset_t)_dma_counterreset, -+ (di_ctrlflags_t)_dma_ctrlflags, -+ -+#if defined(BCMDBG) -+ (di_dump_t)dma64_dump, -+ (di_dumptx_t)dma64_dumptx, -+ (di_dumprx_t)dma64_dumprx, -+#else -+ NULL, -+ NULL, -+ NULL, -+#endif -+ (di_rxactive_t)_dma_rxactive, -+ (di_txpending_t)_dma_txpending, -+ (di_txcommitted_t)_dma_txcommitted, -+ (di_pktpool_set_t)_dma_pktpool_set, -+ (di_rxtxerror_t)_dma_rxtx_error, -+ (di_burstlen_set_t)_dma_burstlen_set, -+ (di_avoidancecnt_t)_dma_avoidancecnt, -+ (di_param_set_t)_dma_param_set, -+ (dma_glom_enable_t)_dma_glom_enable, -+ (di_rxunframed_t)dma64_rxunframed, -+ (dma_active_rxbuf_t)_dma_activerxbuf, -+ 40 -+}; -+ -+static const di_fcn_t dma32proc = { -+ (di_detach_t)_dma_detach, -+ (di_txinit_t)dma32_txinit, -+ (di_txreset_t)dma32_txreset, -+ (di_txenabled_t)dma32_txenabled, -+ (di_txsuspend_t)dma32_txsuspend, -+ (di_txresume_t)dma32_txresume, -+ (di_txsuspended_t)dma32_txsuspended, -+ (di_txsuspendedidle_t)dma32_txsuspendedidle, -+#ifdef WL_MULTIQUEUE -+ (di_txflush_t)dma32_txflush, -+ (di_txflush_clear_t)dma32_txflush_clear, -+#endif /* WL_MULTIQUEUE */ -+ (di_txfast_t)dma32_txfast, -+ NULL, -+ NULL, -+ (di_txstopped_t)dma32_txstopped, -+ (di_txreclaim_t)dma32_txreclaim, -+ (di_getnexttxp_t)dma32_getnexttxp, -+ (di_peeknexttxp_t)_dma_peeknexttxp, -+ (di_peekntxp_t)_dma_peekntxp, -+ (di_txblock_t)_dma_txblock, -+ (di_txunblock_t)_dma_txunblock, -+ (di_txactive_t)_dma_txactive, -+ (di_txrotate_t)dma32_txrotate, -+ -+ (di_rxinit_t)_dma_rxinit, -+ (di_rxreset_t)dma32_rxreset, -+ (di_rxidle_t)dma32_rxidle, -+ (di_rxstopped_t)dma32_rxstopped, -+ (di_rxenable_t)_dma_rxenable, -+ (di_rxenabled_t)dma32_rxenabled, -+ (di_rx_t)_dma_rx, -+ (di_rxfill_t)_dma_rxfill, -+ (di_rxreclaim_t)_dma_rxreclaim, -+ (di_getnextrxp_t)_dma_getnextrxp, -+ (di_peeknextrxp_t)_dma_peeknextrxp, -+ (di_rxparam_get_t)_dma_rx_param_get, -+ -+ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, -+ (di_getvar_t)_dma_getvar, -+ (di_counterreset_t)_dma_counterreset, -+ (di_ctrlflags_t)_dma_ctrlflags, -+ -+#if defined(BCMDBG) -+ (di_dump_t)dma32_dump, -+ (di_dumptx_t)dma32_dumptx, -+ (di_dumprx_t)dma32_dumprx, -+#else -+ NULL, -+ NULL, -+ NULL, -+#endif -+ (di_rxactive_t)_dma_rxactive, -+ (di_txpending_t)_dma_txpending, -+ (di_txcommitted_t)_dma_txcommitted, -+ (di_pktpool_set_t)_dma_pktpool_set, -+ (di_rxtxerror_t)_dma_rxtx_error, -+ (di_burstlen_set_t)_dma_burstlen_set, -+ (di_avoidancecnt_t)_dma_avoidancecnt, -+ (di_param_set_t)_dma_param_set, -+ NULL, -+ NULL, -+ NULL, -+ 40 -+}; -+ -+EXPORT_SYMBOL(dma_attach); -+EXPORT_SYMBOL(dma64proc); -+ -+hnddma_t * -+dma_attach(osl_t *osh, const char *name, si_t *sih, -+ volatile void *dmaregstx, volatile void *dmaregsrx, -+ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, uint rxoffset, -+ uint *msg_level) -+{ -+ dma_info_t *di; -+ uint size; -+ uint32 mask; -+ -+ /* allocate private info structure */ -+ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { -+#ifdef BCMDBG -+ DMA_ERROR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); -+#endif -+ return (NULL); -+ } -+ -+ bzero(di, sizeof(dma_info_t)); -+ -+ di->msg_level = msg_level ? msg_level : &dma_msg_level; -+ spin_lock_init(&di->des_lock); -+ -+ /* old chips w/o sb is no longer supported */ -+ ASSERT(sih != NULL); -+ -+ if (DMA64_ENAB(di)) { -+ di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); -+ } else { -+ di->dma64 = 0; -+ } -+ -+ /* check arguments */ -+ ASSERT(ISPOWEROF2(ntxd)); -+ ASSERT(ISPOWEROF2(nrxd)); -+ -+ if (nrxd == 0) { -+ ASSERT(dmaregsrx == NULL); -+ } -+ if (ntxd == 0) { -+ ASSERT(dmaregstx == NULL); -+ } -+ -+ /* init dma reg pointer */ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ di->d64txregs = (dma64regs_t *)dmaregstx; -+ di->d64rxregs = (dma64regs_t *)dmaregsrx; -+ di->hnddma.di_fn = (const di_fcn_t *)&dma64proc; -+ } else if (DMA32_ENAB(di)) { -+ ASSERT(ntxd <= D32MAXDD); -+ ASSERT(nrxd <= D32MAXDD); -+ di->d32txregs = (dma32regs_t *)dmaregstx; -+ di->d32rxregs = (dma32regs_t *)dmaregsrx; -+ di->hnddma.di_fn = (const di_fcn_t *)&dma32proc; -+ } else { -+ DMA_ERROR(("%s: driver doesn't support 32-bit DMA\n", __FUNCTION__)); -+ ASSERT(0); -+ goto fail; -+ } -+ -+ /* Default flags (which can be changed by the driver calling dma_ctrlflags -+ * before enable): For backwards compatibility both Rx Overflow Continue -+ * and Parity are DISABLED. -+ * supports it. -+ */ -+ di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); -+ -+ DMA_TRACE(("%s: %s: %s osh %p flags 0x%x ntxd %d nrxd %d rxbufsize %d " -+ "rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", -+ name, __FUNCTION__, (DMA64_MODE(di) ? "DMA64" : "DMA32"), -+ osh, di->hnddma.dmactrlflags, ntxd, nrxd, -+ rxbufsize, rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); -+ -+ /* make a private copy of our callers name */ -+ strncpy(di->name, name, MAXNAMEL); -+ di->name[MAXNAMEL-1] = '\0'; -+ -+ di->osh = osh; -+ di->sih = sih; -+ -+ /* save tunables */ -+ di->ntxd = (uint16)ntxd; -+ di->nrxd = (uint16)nrxd; -+ -+ /* the actual dma size doesn't include the extra headroom */ -+ di->rxextrahdrroom = (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; -+ if (rxbufsize > BCMEXTRAHDROOM) { -+ di->rxbufsize = (uint16)(rxbufsize - di->rxextrahdrroom); -+ } else { -+ di->rxbufsize = (uint16)rxbufsize; -+ } -+ -+ di->nrxpost = (uint16)nrxpost; -+ di->rxoffset = (uint8)rxoffset; -+ -+ /* Get the default values (POR) of the burstlen. This can be overridden by the modules -+ * if this has to be different. Otherwise this value will be used to program the control -+ * register after the reset or during the init. -+ */ -+ if (dmaregsrx) { -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ /* detect the dma descriptor address mask, -+ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 -+ */ -+ W_REG(di->osh, &di->d64rxregs->addrlow, 0xffffffff); -+ mask = R_REG(di->osh, &di->d64rxregs->addrlow); -+ -+ if (mask & 0xfff) { -+ mask = R_REG(di->osh, &di->d64rxregs->ptr) | 0xf; -+ } else { -+ mask = 0x1fff; -+ } -+ -+ DMA_TRACE(("%s: dma_rx_mask: %08x\n", di->name, mask)); -+ di->d64_rs0_cd_mask = mask; -+ -+ if (mask == 0x1fff) { -+ ASSERT(nrxd <= D64MAXDD); -+ } else { -+ ASSERT(nrxd <= D64MAXDD_LARGE); -+ } -+ -+ di->rxburstlen = (R_REG(di->osh, -+ &di->d64rxregs->control) & D64_RC_BL_MASK) >> D64_RC_BL_SHIFT; -+ di->rxprefetchctl = (R_REG(di->osh, -+ &di->d64rxregs->control) & D64_RC_PC_MASK) >> D64_RC_PC_SHIFT; -+ di->rxprefetchthresh = (R_REG(di->osh, -+ &di->d64rxregs->control) & D64_RC_PT_MASK) >> D64_RC_PT_SHIFT; -+ } else if (DMA32_ENAB(di)) { -+ di->rxburstlen = (R_REG(di->osh, -+ &di->d32rxregs->control) & RC_BL_MASK) >> RC_BL_SHIFT; -+ di->rxprefetchctl = (R_REG(di->osh, -+ &di->d32rxregs->control) & RC_PC_MASK) >> RC_PC_SHIFT; -+ di->rxprefetchthresh = (R_REG(di->osh, -+ &di->d32rxregs->control) & RC_PT_MASK) >> RC_PT_SHIFT; -+ } -+ } -+ if (dmaregstx) { -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ -+ /* detect the dma descriptor address mask, -+ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 -+ */ -+ W_REG(di->osh, &di->d64txregs->addrlow, 0xffffffff); -+ mask = R_REG(di->osh, &di->d64txregs->addrlow); -+ -+ if (mask & 0xfff) { -+ mask = R_REG(di->osh, &di->d64txregs->ptr) | 0xf; -+ } else { -+ mask = 0x1fff; -+ } -+ -+ DMA_TRACE(("%s: dma_tx_mask: %08x\n", di->name, mask)); -+ di->d64_xs0_cd_mask = mask; -+ di->d64_xs1_ad_mask = mask; -+ -+ if (mask == 0x1fff) { -+ ASSERT(ntxd <= D64MAXDD); -+ } else { -+ ASSERT(ntxd <= D64MAXDD_LARGE); -+ } -+ -+ di->txburstlen = (R_REG(di->osh, -+ &di->d64txregs->control) & D64_XC_BL_MASK) >> D64_XC_BL_SHIFT; -+ di->txmultioutstdrd = (R_REG(di->osh, -+ &di->d64txregs->control) & D64_XC_MR_MASK) >> D64_XC_MR_SHIFT; -+ di->txprefetchctl = (R_REG(di->osh, -+ &di->d64txregs->control) & D64_XC_PC_MASK) >> D64_XC_PC_SHIFT; -+ di->txprefetchthresh = (R_REG(di->osh, -+ &di->d64txregs->control) & D64_XC_PT_MASK) >> D64_XC_PT_SHIFT; -+ } else if (DMA32_ENAB(di)) { -+ di->txburstlen = (R_REG(di->osh, -+ &di->d32txregs->control) & XC_BL_MASK) >> XC_BL_SHIFT; -+ di->txmultioutstdrd = (R_REG(di->osh, -+ &di->d32txregs->control) & XC_MR_MASK) >> XC_MR_SHIFT; -+ di->txprefetchctl = (R_REG(di->osh, -+ &di->d32txregs->control) & XC_PC_MASK) >> XC_PC_SHIFT; -+ di->txprefetchthresh = (R_REG(di->osh, -+ &di->d32txregs->control) & XC_PT_MASK) >> XC_PT_SHIFT; -+ } -+ } -+ -+ /* force burstlen to 3 */ -+ di->rxburstlen = 3; -+ di->txburstlen = 3; -+ /* -+ * figure out the DMA physical address offset for dd and data -+ * Other bus: use zero -+ */ -+ di->ddoffsetlow = 0; -+ di->dataoffsetlow = 0; -+ -+ /* set addr ext fields */ -+ di->addrext = _dma_isaddrext(di); -+ -+ /* does the descriptors need to be aligned and if yes, on 4K/8K or not */ -+ di->aligndesc_4k = _dma_descriptor_align(di); -+ if (di->aligndesc_4k) { -+ if (DMA64_MODE(di)) { -+ di->dmadesc_align = D64RINGALIGN_BITS; -+ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { -+ /* for smaller dd table, HW relax the alignment requirement */ -+ di->dmadesc_align = D64RINGALIGN_BITS - 1; -+ } -+ } else { -+ di->dmadesc_align = D32RINGALIGN_BITS; -+ } -+ } else { -+ /* The start address of descriptor table should be algined to cache line size, -+ * or other structure may share a cache line with it, which can lead to memory -+ * overlapping due to cache write-back operation. In the case of MIPS 74k, the -+ * cache line size is 32 bytes. -+ */ -+#ifdef __mips__ -+ di->dmadesc_align = 5; /* 32 byte alignment */ -+#else -+ di->dmadesc_align = 4; /* 16 byte alignment */ -+#endif -+ } -+ -+ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", -+ di->aligndesc_4k, di->dmadesc_align)); -+ -+ /* allocate tx packet pointer vector */ -+ if (ntxd) { -+ size = ntxd * sizeof(void *); -+ if ((di->txp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: %s: out of tx memory, malloced %d bytes\n", -+ di->name, __FUNCTION__, MALLOCED(osh))); -+ goto fail; -+ } -+ bzero(di->txp, size); -+ } -+ -+ /* allocate rx packet pointer vector */ -+ if (nrxd) { -+ size = nrxd * sizeof(void *); -+ if ((di->rxp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: %s: out of rx memory, malloced %d bytes\n", -+ di->name, __FUNCTION__, MALLOCED(osh))); -+ goto fail; -+ } -+ bzero(di->rxp, size); -+ } -+ -+ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ -+ if (ntxd) { -+ if (!_dma_alloc(di, DMA_TX)) { -+ goto fail; -+ } -+ } -+ -+ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ -+ if (nrxd) { -+ if (!_dma_alloc(di, DMA_RX)) { -+ goto fail; -+ } -+ } -+ -+ if ((di->ddoffsetlow != 0) && !di->addrext) { -+ if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) { -+ DMA_ERROR(("%s: %s: txdpa 0x%x: addrext not supported\n", -+ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->txdpa))); -+ goto fail; -+ } -+ if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) { -+ DMA_ERROR(("%s: %s: rxdpa 0x%x: addrext not supported\n", -+ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->rxdpa))); -+ goto fail; -+ } -+ } -+ -+ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " -+ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, -+ di->dataoffsethigh, di->addrext)); -+ -+ /* allocate DMA mapping vectors */ -+ if (DMASGLIST_ENAB) { -+ if (ntxd) { -+ size = ntxd * sizeof(hnddma_seg_map_t); -+ if ((di->txp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) { -+ goto fail; -+ } -+ bzero(di->txp_dmah, size); -+ } -+ -+ if (nrxd) { -+ size = nrxd * sizeof(hnddma_seg_map_t); -+ if ((di->rxp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) { -+ goto fail; -+ } -+ bzero(di->rxp_dmah, size); -+ } -+ } -+ -+ return ((hnddma_t *)di); -+ -+fail: -+ _dma_detach(di); -+ return (NULL); -+} -+ -+/* init the tx or rx descriptor */ -+static INLINE void -+dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, -+ uint32 bufcount) -+{ -+ /* dma32 uses 32-bit control to fit both flags and bufcounter */ -+ *flags = *flags | (bufcount & CTRL_BC_MASK); -+ -+ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { -+ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); -+ } else { -+ /* address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; -+ -+ *flags |= (ae << CTRL_AE_SHIFT); -+ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); -+ } -+} -+ -+/* Check for odd number of 1's */ -+STATIC INLINE uint32 parity32(uint32 data) -+{ -+ data ^= data >> 16; -+ data ^= data >> 8; -+ data ^= data >> 4; -+ data ^= data >> 2; -+ data ^= data >> 1; -+ -+ return (data & 1); -+} -+ -+#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) -+ -+static INLINE void -+dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, -+ uint32 bufcount) -+{ -+ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; -+ -+ /* PCI bus with big(>1G) physical address, use address extension */ -+#if defined(__mips__) && defined(IL_BIGENDIAN) -+ if ((di->dataoffsetlow == SI_SDRAM_SWAPPED) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { -+#else -+ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { -+#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ -+ ASSERT((PHYSADDRHI(pa) & PCI64ADDR_HIGH) == 0); -+ -+ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); -+ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh)); -+ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); -+ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); -+ } else { -+ /* address extension for 32-bit PCI */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ -+ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; -+ ASSERT(PHYSADDRHI(pa) == 0); -+ -+ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; -+ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); -+ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); -+ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); -+ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); -+ } -+ if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) { -+ if (DMA64_DD_PARITY(&ddring[outidx])) { -+ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY)); -+ } -+ } -+ -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+/* Test */ -+#if defined(__arm__) -+ OSL_CACHE_FLUSH((uint)OSL_CACHED(&ddring[outidx]), sizeof(dma64dd_t)); -+#endif -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+} -+ -+static bool -+_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) -+{ -+ uint32 w; -+ -+ OR_REG(osh, &dma32regs->control, XC_AE); -+ w = R_REG(osh, &dma32regs->control); -+ AND_REG(osh, &dma32regs->control, ~XC_AE); -+ return ((w & XC_AE) == XC_AE); -+} -+ -+static bool -+_dma_alloc(dma_info_t *di, uint direction) -+{ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ return dma64_alloc(di, direction); -+ } else if (DMA32_ENAB(di)) { -+ return dma32_alloc(di, direction); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+/* !! may be called with core in reset */ -+static void -+_dma_detach(dma_info_t *di) -+{ -+ -+ DMA_TRACE(("%s: dma_detach\n", di->name)); -+ -+ /* shouldn't be here if descriptors are unreclaimed */ -+ ASSERT(di->txin == di->txout); -+ ASSERT(di->rxin == di->rxout); -+ -+ /* free dma descriptor rings */ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ if (di->txd64) { -+ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd64 - di->txdalign), -+ di->txdalloc, (di->txdpaorig), &di->tx_dmah); -+ } -+ if (di->rxd64) { -+ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd64 - di->rxdalign), -+ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); -+ } -+ } else if (DMA32_ENAB(di)) { -+ if (di->txd32) { -+ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd32 - di->txdalign), -+ di->txdalloc, (di->txdpaorig), &di->tx_dmah); -+ } -+ if (di->rxd32) { -+ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd32 - di->rxdalign), -+ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); -+ } -+ } else -+ ASSERT(0); -+ -+ /* free packet pointer vectors */ -+ if (di->txp) { -+ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); -+ } -+ if (di->rxp) { -+ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); -+ } -+ -+ /* free tx packet DMA handles */ -+ if (di->txp_dmah) { -+ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(hnddma_seg_map_t)); -+ } -+ -+ /* free rx packet DMA handles */ -+ if (di->rxp_dmah) { -+ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(hnddma_seg_map_t)); -+ } -+ -+ /* free our private info structure */ -+ MFREE(di->osh, (void *)di, sizeof(dma_info_t)); -+ -+} -+ -+static bool -+_dma_descriptor_align(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ uint32 addrl; -+ -+ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ -+ if (di->d64txregs != NULL) { -+ W_REG(di->osh, &di->d64txregs->addrlow, 0xff0); -+ addrl = R_REG(di->osh, &di->d64txregs->addrlow); -+ if (addrl != 0) { -+ return FALSE; -+ } -+ } else if (di->d64rxregs != NULL) { -+ W_REG(di->osh, &di->d64rxregs->addrlow, 0xff0); -+ addrl = R_REG(di->osh, &di->d64rxregs->addrlow); -+ if (addrl != 0) { -+ return FALSE; -+ } -+ } -+ } -+ return TRUE; -+} -+ -+/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ -+static bool -+_dma_isaddrext(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ -+ -+ /* not all tx or rx channel are available */ -+ if (di->d64txregs != NULL) { -+ if (!_dma64_addrext(di->osh, di->d64txregs)) { -+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", -+ di->name)); -+ ASSERT(0); -+ } -+ return TRUE; -+ } else if (di->d64rxregs != NULL) { -+ if (!_dma64_addrext(di->osh, di->d64rxregs)) { -+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", -+ di->name)); -+ ASSERT(0); -+ } -+ return TRUE; -+ } -+ return FALSE; -+ } else if (DMA32_ENAB(di)) { -+ if (di->d32txregs) { -+ return (_dma32_addrext(di->osh, di->d32txregs)); -+ } else if (di->d32rxregs) { -+ return (_dma32_addrext(di->osh, di->d32rxregs)); -+ } -+ } else { -+ ASSERT(0); -+ } -+ -+ return FALSE; -+} -+ -+/* initialize descriptor table base address */ -+static void -+_dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa) -+{ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ if (!di->aligndesc_4k) { -+ if (direction == DMA_TX) { -+ di->xmtptrbase = PHYSADDRLO(pa); -+ } else { -+ di->rcvptrbase = PHYSADDRLO(pa); -+ } -+ } -+ -+ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { -+ if (direction == DMA_TX) { -+ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ W_REG(di->osh, &di->d64txregs->addrhigh, (PHYSADDRHI(pa) + -+ di->ddoffsethigh)); -+ } else { -+ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ W_REG(di->osh, &di->d64rxregs->addrhigh, (PHYSADDRHI(pa) + -+ di->ddoffsethigh)); -+ } -+ } else { -+ /* DMA64 32bits address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ASSERT(PHYSADDRHI(pa) == 0); -+ -+ /* shift the high bit(s) from pa to ae */ -+ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; -+ -+ if (direction == DMA_TX) { -+ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); -+ SET_REG(di->osh, &di->d64txregs->control, D64_XC_AE, -+ (ae << D64_XC_AE_SHIFT)); -+ } else { -+ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); -+ SET_REG(di->osh, &di->d64rxregs->control, D64_RC_AE, -+ (ae << D64_RC_AE_SHIFT)); -+ } -+ } -+ -+ } else if (DMA32_ENAB(di)) { -+ ASSERT(PHYSADDRHI(pa) == 0); -+ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { -+ if (direction == DMA_TX) { -+ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ } else { -+ W_REG(di->osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ } -+ } else { -+ /* dma32 address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ -+ /* shift the high bit(s) from pa to ae */ -+ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; -+ -+ if (direction == DMA_TX) { -+ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + -+ di->ddoffsetlow)); -+ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE); -+ } else if (DMA32_ENAB(di)) { -+ OR_REG(di->osh, &di->d32txregs->control, XC_LE); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+static void -+_dma_rxinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxinit\n", di->name)); -+ -+ if (di->nrxd == 0) { -+ return; -+ } -+ -+ /* During the reset procedure, the active rxd may not be zero if pktpool is -+ * enabled, we need to reclaim active rxd to avoid rxd being leaked. -+ */ -+ if ((POOL_ENAB(di->pktpool)) && (NRXDACTIVE(di->rxin, di->rxout))) { -+ _dma_rxreclaim(di); -+ } -+ -+ ASSERT(di->rxin == di->rxout); -+ di->rxin = di->rxout = di->rs0cd = 0; -+ -+ /* clear rx descriptor ring */ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ BZERO_SM((void *)(uintptr)di->rxd64, (di->nrxd * sizeof(dma64dd_t))); -+ -+ /* DMA engine with out alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (!di->aligndesc_4k) { -+ _dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } -+ -+ _dma_rxenable(di); -+ -+ if (di->aligndesc_4k) { -+ _dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } -+ } else if (DMA32_ENAB(di)) { -+ BZERO_SM((void *)(uintptr)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); -+ _dma_rxenable(di); -+ _dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+static void -+_dma_rxenable(dma_info_t *di) -+{ -+ uint dmactrlflags = di->hnddma.dmactrlflags; -+ -+ DMA_TRACE(("%s: dma_rxenable\n", di->name)); -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ uint32 control = (R_REG(di->osh, &di->d64rxregs->control) & D64_RC_AE) | D64_RC_RE; -+ -+ if ((dmactrlflags & DMA_CTRL_PEN) == 0) { -+ control |= D64_RC_PD; -+ } -+ -+ if (dmactrlflags & DMA_CTRL_ROC) { -+ control |= D64_RC_OC; -+ } -+ -+ /* These bits 20:18 (burstLen) of control register can be written but will take -+ * effect only if these bits are valid. So this will not affect previous versions -+ * of the DMA. They will continue to have those bits set to 0. -+ */ -+ control &= ~D64_RC_BL_MASK; -+ control |= (di->rxburstlen << D64_RC_BL_SHIFT); -+ -+ control &= ~D64_RC_PC_MASK; -+ control |= (di->rxprefetchctl << D64_RC_PC_SHIFT); -+ -+ control &= ~D64_RC_PT_MASK; -+ control |= (di->rxprefetchthresh << D64_RC_PT_SHIFT); -+ -+ W_REG(di->osh, &di->d64rxregs->control, -+ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); -+ } else if (DMA32_ENAB(di)) { -+ uint32 control = (R_REG(di->osh, &di->d32rxregs->control) & RC_AE) | RC_RE; -+ -+ if ((dmactrlflags & DMA_CTRL_PEN) == 0) { -+ control |= RC_PD; -+ } -+ -+ if (dmactrlflags & DMA_CTRL_ROC) { -+ control |= RC_OC; -+ } -+ -+ /* These bits 20:18 (burstLen) of control register can be written but will take -+ * effect only if these bits are valid. So this will not affect previous versions -+ * of the DMA. They will continue to have those bits set to 0. -+ */ -+ control &= ~RC_BL_MASK; -+ control |= (di->rxburstlen << RC_BL_SHIFT); -+ -+ control &= ~RC_PC_MASK; -+ control |= (di->rxprefetchctl << RC_PC_SHIFT); -+ -+ control &= ~RC_PT_MASK; -+ control |= (di->rxprefetchthresh << RC_PT_SHIFT); -+ -+ W_REG(di->osh, &di->d32rxregs->control, -+ ((di->rxoffset << RC_RO_SHIFT) | control)); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+static void -+_dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize) -+{ -+ /* the normal values fit into 16 bits */ -+ *rxoffset = (uint16)di->rxoffset; -+ *rxbufsize = (uint16)di->rxbufsize; -+} -+ -+/* !! rx entry routine -+ * returns a pointer to the next frame received, or NULL if there are no more -+ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported -+ * with pkts chain -+ * otherwise, it's treated as giant pkt and will be tossed. -+ * The DMA scattering starts with normal DMA header, followed by first buffer data. -+ * After it reaches the max size of buffer, the data continues in next DMA descriptor -+ * buffer WITHOUT DMA header -+ */ -+static void * BCMFASTPATH -+_dma_rx(dma_info_t *di) -+{ -+ void *p, *head, *tail; -+ uint len; -+ uint pkt_len; -+ int resid = 0; -+#ifdef BCM4335 -+ dma64regs_t *dregs = di->d64rxregs; -+#endif -+ -+next_frame: -+ head = _dma_getnextrxp(di, FALSE); -+ if (head == NULL) { -+ return (NULL); -+ } -+ -+ len = ltoh16(*(uint16 *)(PKTDATA(di->osh, head))); -+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); -+ -+ /* set actual length */ -+ pkt_len = MIN((di->rxoffset + len), di->rxbufsize); -+ PKTSETLEN(di->osh, head, pkt_len); -+ resid = len - (di->rxbufsize - di->rxoffset); -+ -+ /* check for single or multi-buffer rx */ -+ if (resid <= 0) { -+ /* Single frame, all good */ -+ } else if (di->hnddma.dmactrlflags & DMA_CTRL_RXSINGLE) { -+ DMA_TRACE(("%s: dma_rx: corrupted length (%d)\n", di->name, len)); -+ PKTFREE(di->osh, head, FALSE); -+ di->hnddma.rxgiants++; -+ goto next_frame; -+ } else { -+ /* multi-buffer rx */ -+#ifdef BCMDBG -+ p = NULL; /* get rid of compiler warning */ -+#endif /* BCMDBG */ -+ tail = head; -+ while ((resid > 0) && (p = _dma_getnextrxp(di, FALSE))) { -+ PKTSETNEXT(di->osh, tail, p); -+ pkt_len = MIN(resid, (int)di->rxbufsize); -+ PKTSETLEN(di->osh, p, pkt_len); -+ -+ tail = p; -+ resid -= di->rxbufsize; -+ } -+ -+#ifdef BCMDBG -+ if (resid > 0) { -+ uint16 cur; -+ ASSERT(p == NULL); -+ cur = (DMA64_ENAB(di) && DMA64_MODE(di)) ? -+ B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t) : -+ B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, -+ dma32dd_t); -+ DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n", -+ di->rxin, di->rxout, cur)); -+ } -+#endif /* BCMDBG */ -+ -+ if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { -+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); -+ PKTFREE(di->osh, head, FALSE); -+ di->hnddma.rxgiants++; -+ goto next_frame; -+ } -+ } -+ -+ return (head); -+} -+ -+/* post receive buffers -+ * return FALSE is refill failed completely and ring is empty -+ * this will stall the rx dma and user might want to call rxfill again asap -+ * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle -+ */ -+static bool BCMFASTPATH -+_dma_rxfill(dma_info_t *di) -+{ -+ void *p; -+ uint16 rxin, rxout; -+ uint32 flags = 0; -+ uint n; -+ uint i; -+ dmaaddr_t pa; -+ uint extra_offset = 0, extra_pad; -+ bool ring_empty; -+ uint alignment_req = (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) ? -+ 16 : 1; /* MUST BE POWER of 2 */ -+ -+ ring_empty = FALSE; -+ -+ /* -+ * Determine how many receive buffers we're lacking -+ * from the full complement, allocate, initialize, -+ * and post them, then update the chip rx lastdscr. -+ */ -+ -+ rxin = di->rxin; -+ rxout = di->rxout; -+ -+ n = di->nrxpost - NRXDACTIVE(rxin, rxout); -+ -+ if (di->rxbufsize > BCMEXTRAHDROOM) { -+ extra_offset = di->rxextrahdrroom; -+ } -+ -+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); -+ -+ for (i = 0; i < n; i++) { -+ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the -+ size to be allocated -+ */ -+ if (POOL_ENAB(di->pktpool)) { -+ ASSERT(di->pktpool); -+ p = pktpool_get(di->pktpool); -+#ifdef BCMDBG_POOL -+ if (p) { -+ PKTPOOLSETSTATE(p, POOL_RXFILL); -+ } -+#endif /* BCMDBG_POOL */ -+ } -+ else { -+ p = PKTGET(di->osh, (di->rxbufsize + extra_offset + alignment_req - 1), FALSE); -+ } -+ if (p == NULL) { -+ DMA_TRACE(("%s: dma_rxfill: out of rxbufs\n", di->name)); -+ if (i == 0) { -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ if (dma64_rxidle(di)) { -+ DMA_TRACE(("%s: rxfill64: ring is empty !\n", di->name)); -+ ring_empty = TRUE; -+ } -+ } else if (DMA32_ENAB(di)) { -+ if (dma32_rxidle(di)) { -+ DMA_TRACE(("%s: rxfill32: ring is empty !\n", di->name)); -+ ring_empty = TRUE; -+ } -+ } else { -+ ASSERT(0); -+ } -+ } -+ di->hnddma.rxnobuf++; -+ break; -+ } -+ /* reserve an extra headroom, if applicable */ -+ if (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) { -+ extra_pad = ((alignment_req - (uint)(((unsigned long)PKTDATA(di->osh, p) - -+ (unsigned long)(uchar *)0))) & (alignment_req - 1)); -+ } else { -+ extra_pad = 0; -+ } -+ -+ if (extra_offset + extra_pad) { -+ PKTPULL(di->osh, p, extra_offset + extra_pad); -+ } -+ -+ /* Do a cached write instead of uncached write since DMA_MAP -+ * will flush the cache. -+ */ -+ *(uint16 *)(PKTDATA(di->osh, p)) = 0; -+ -+ if (DMASGLIST_ENAB) { -+ bzero(&di->rxp_dmah[rxout], sizeof(hnddma_seg_map_t)); -+ } -+ -+#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) -+ pa = virt_to_phys(PKTDATA(di->osh, p)); -+#else -+ pa = DMA_MAP(di->osh, PKTDATA(di->osh, p), -+ di->rxbufsize, DMA_RX, p, -+ &di->rxp_dmah[rxout]); -+#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ -+ -+ ASSERT(ISALIGNED(PHYSADDRLO(pa), 4)); -+ -+ /* save the free packet pointer */ -+ ASSERT(di->rxp[rxout] == NULL); -+ di->rxp[rxout] = p; -+ -+ /* reset flags for each descriptor */ -+ flags = 0; -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ if (rxout == (di->nrxd - 1)) { -+ flags = D64_CTRL1_EOT; -+ } -+ -+ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, di->rxbufsize); -+ } else if (DMA32_ENAB(di)) { -+ if (rxout == (di->nrxd - 1)) { -+ flags = CTRL_EOT; -+ } -+ -+ ASSERT(PHYSADDRHI(pa) == 0); -+ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); -+ } else { -+ ASSERT(0); -+ } -+ rxout = NEXTRXD(rxout); -+ } -+ -+ di->rxout = rxout; -+ -+ /* update the chip lastdscr pointer */ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); -+ } else if (DMA32_ENAB(di)) { -+ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); -+ } else { -+ ASSERT(0); -+ } -+ -+ return ring_empty; -+} -+ -+/* like getnexttxp but no reclaim */ -+static void * -+_dma_peeknexttxp(dma_info_t *di) -+{ -+ uint16 end, i; -+ -+ if (di->ntxd == 0) { -+ return (NULL); -+ } -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ end = (uint16)B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); -+ di->xs0cd = end; -+ } else if (DMA32_ENAB(di)) { -+ end = (uint16)B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); -+ di->xs0cd = end; -+ } else { -+ ASSERT(0); -+ } -+ -+ for (i = di->txin; i != end; i = NEXTTXD(i)) { -+ if (di->txp[i]) { -+ return (di->txp[i]); -+ } -+ } -+ -+ return (NULL); -+} -+ -+int -+_dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range) -+{ -+ uint16 start, end, i; -+ uint act; -+ void *txp = NULL; -+ int k, len_max; -+ -+ DMA_TRACE(("%s: dma_peekntxp\n", di->name)); -+ -+ ASSERT(len); -+ ASSERT(txps); -+ ASSERT(di); -+ if (di->ntxd == 0) { -+ *len = 0; -+ return BCME_ERROR; -+ } -+ -+ len_max = *len; -+ *len = 0; -+ -+ start = di->txin; -+ -+ if (range == HNDDMA_RANGE_ALL) { -+ end = di->txout; -+ } else { -+ if (DMA64_ENAB(di)) { -+ end = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); -+ -+ act = (uint)(R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK); -+ act = (act - di->xmtptrbase) & D64_XS0_CD_MASK; -+ act = (uint)B2I(act, dma64dd_t); -+ } else { -+ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); -+ -+ act = (uint)((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> -+ XS_AD_SHIFT); -+ act = (uint)B2I(act, dma32dd_t); -+ } -+ -+ di->xs0cd = end; -+ if (end != act) { -+ end = PREVTXD(act); -+ } -+ } -+ -+ if ((start == 0) && (end > di->txout)) { -+ return BCME_ERROR; -+ } -+ -+ k = 0; -+ for (i = start; i != end; i = NEXTTXD(i)) { -+ txp = di->txp[i]; -+ if (txp != NULL) { -+ if (k < len_max) { -+ txps[k++] = txp; -+ } else { -+ break; -+ } -+ } -+ } -+ *len = k; -+ -+ return BCME_OK; -+} -+ -+/* like getnextrxp but not take off the ring */ -+static void * -+_dma_peeknextrxp(dma_info_t *di) -+{ -+ uint16 end, i; -+ -+ if (di->nrxd == 0) { -+ return (NULL); -+ } -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ end = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); -+ di->rs0cd = end; -+ } else if (DMA32_ENAB(di)) { -+ end = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); -+ di->rs0cd = end; -+ } else { -+ ASSERT(0); -+ } -+ -+ for (i = di->rxin; i != end; i = NEXTRXD(i)) { -+ if (di->rxp[i]) { -+ return (di->rxp[i]); -+ } -+ } -+ -+ return (NULL); -+} -+ -+static void -+_dma_rxreclaim(dma_info_t *di) -+{ -+ void *p; -+ bool origcb = TRUE; -+ -+#ifndef EFI -+ /* "unused local" warning suppression for OSLs that -+ * define PKTFREE() without using the di->osh arg -+ */ -+ di = di; -+#endif /* EFI */ -+ -+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); -+ -+ if (POOL_ENAB(di->pktpool) && -+ ((origcb = pktpool_emptycb_disabled(di->pktpool)) == FALSE)) { -+ pktpool_emptycb_disable(di->pktpool, TRUE); -+ } -+ -+ while ((p = _dma_getnextrxp(di, TRUE))) { -+ PKTFREE(di->osh, p, FALSE); -+ } -+ -+ if (origcb == FALSE) { -+ pktpool_emptycb_disable(di->pktpool, FALSE); -+ } -+} -+ -+static void * BCMFASTPATH -+_dma_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ if (di->nrxd == 0) { -+ return (NULL); -+ } -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ return dma64_getnextrxp(di, forceall); -+ } else if (DMA32_ENAB(di)) { -+ return dma32_getnextrxp(di, forceall); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+static void -+_dma_txblock(dma_info_t *di) -+{ -+ di->hnddma.txavail = 0; -+} -+ -+static void -+_dma_txunblock(dma_info_t *di) -+{ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+} -+ -+static uint -+_dma_txactive(dma_info_t *di) -+{ -+ return NTXDACTIVE(di->txin, di->txout); -+} -+ -+static uint -+_dma_txpending(dma_info_t *di) -+{ -+ uint16 curr; -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ curr = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); -+ di->xs0cd = curr; -+ } else if (DMA32_ENAB(di)) { -+ curr = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); -+ di->xs0cd = curr; -+ } else { -+ ASSERT(0); -+ } -+ -+ return NTXDACTIVE(curr, di->txout); -+} -+ -+static uint -+_dma_txcommitted(dma_info_t *di) -+{ -+ uint16 ptr; -+ uint txin = di->txin; -+ -+ if (txin == di->txout) { -+ return 0; -+ } -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ ptr = B2I(R_REG(di->osh, &di->d64txregs->ptr), dma64dd_t); -+ } else if (DMA32_ENAB(di)) { -+ ptr = B2I(R_REG(di->osh, &di->d32txregs->ptr), dma32dd_t); -+ } else { -+ ASSERT(0); -+ } -+ -+ return NTXDACTIVE(di->txin, ptr); -+} -+ -+static uint -+_dma_rxactive(dma_info_t *di) -+{ -+ return NRXDACTIVE(di->rxin, di->rxout); -+} -+ -+static uint -+_dma_activerxbuf(dma_info_t *di) -+{ -+ uint16 curr, ptr; -+ curr = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); -+ ptr = B2I(((R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); -+ return NRXDACTIVE(curr, ptr); -+} -+ -+ -+static void -+_dma_counterreset(dma_info_t *di) -+{ -+ /* reset all software counter */ -+ di->hnddma.rxgiants = 0; -+ di->hnddma.rxnobuf = 0; -+ di->hnddma.txnobuf = 0; -+} -+ -+static uint -+_dma_ctrlflags(dma_info_t *di, uint mask, uint flags) -+{ -+ uint dmactrlflags; -+ -+ if (!di) { -+ DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n")); -+ return (0); -+ } -+ -+ dmactrlflags = di->hnddma.dmactrlflags; -+ ASSERT((flags & ~mask) == 0); -+ -+ dmactrlflags &= ~mask; -+ dmactrlflags |= flags; -+ -+ /* If trying to enable parity, check if parity is actually supported */ -+ if (dmactrlflags & DMA_CTRL_PEN) { -+ uint32 control; -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ control = R_REG(di->osh, &di->d64txregs->control); -+ W_REG(di->osh, &di->d64txregs->control, control | D64_XC_PD); -+ if (R_REG(di->osh, &di->d64txregs->control) & D64_XC_PD) { -+ /* We *can* disable it so it is supported, -+ * restore control register -+ */ -+ W_REG(di->osh, &di->d64txregs->control, control); -+ } else { -+ /* Not supported, don't allow it to be enabled */ -+ dmactrlflags &= ~DMA_CTRL_PEN; -+ } -+ } else if (DMA32_ENAB(di)) { -+ control = R_REG(di->osh, &di->d32txregs->control); -+ W_REG(di->osh, &di->d32txregs->control, control | XC_PD); -+ if (R_REG(di->osh, &di->d32txregs->control) & XC_PD) { -+ W_REG(di->osh, &di->d32txregs->control, control); -+ } else { -+ /* Not supported, don't allow it to be enabled */ -+ dmactrlflags &= ~DMA_CTRL_PEN; -+ } -+ } else { -+ ASSERT(0); -+ } -+ } -+ -+ di->hnddma.dmactrlflags = dmactrlflags; -+ -+ return (dmactrlflags); -+} -+ -+/* get the address of the var in order to change later */ -+static uintptr -+_dma_getvar(dma_info_t *di, const char *name) -+{ -+ if (!strcmp(name, "&txavail")) { -+ return ((uintptr) &(di->hnddma.txavail)); -+ } else { -+ ASSERT(0); -+ } -+ return (0); -+} -+ -+static uint -+_dma_avoidancecnt(dma_info_t *di) -+{ -+ return (di->dma_avoidance_cnt); -+} -+ -+void -+dma_txpioloopback(osl_t *osh, dma32regs_t *regs) -+{ -+ OR_REG(osh, ®s->control, XC_LE); -+} -+ -+static -+uint8 dma_align_sizetobits(uint size) -+{ -+ uint8 bitpos = 0; -+ ASSERT(size); -+ ASSERT(!(size & (size-1))); -+ while (size >>= 1) { -+ bitpos ++; -+ } -+ return (bitpos); -+} -+ -+/* This function ensures that the DMA descriptor ring will not get allocated -+ * across Page boundary. If the allocation is done across the page boundary -+ * at the first time, then it is freed and the allocation is done at -+ * descriptor ring size aligned location. This will ensure that the ring will -+ * not cross page boundary -+ */ -+static void * -+dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, -+ dmaaddr_t *descpa, osldma_t **dmah) -+{ -+ void * va; -+ uint32 desc_strtaddr; -+ uint32 alignbytes = 1 << *alignbits; -+ -+ if ((va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah)) == NULL) { -+ return NULL; -+ } -+ -+ /* printk("%s va(0x%x)\n", __FUNCTION__, va); */ -+ desc_strtaddr = (uint32)ROUNDUP((uint)PHYSADDRLO(*descpa), alignbytes); -+ if (((desc_strtaddr + size - 1) & boundary) != -+ (desc_strtaddr & boundary)) { -+ *alignbits = dma_align_sizetobits(size); -+ DMA_FREE_CONSISTENT(osh, va, -+ size, *descpa, dmah); -+ va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah); -+ } -+ return va; -+} -+ -+#if defined(BCMDBG) -+static void -+dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, uint end, -+ uint max_num) -+{ -+ uint i; -+ -+ for (i = start; i != end; i = XXD((i + 1), max_num)) { -+ /* in the format of high->low 8 bytes */ -+ bcm_bprintf(b, "ring index %d: 0x%x %x\n", -+ i, R_SM(&ring[i].addr), R_SM(&ring[i].ctrl)); -+ } -+} -+ -+static void -+dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ bcm_bprintf(b, "DMA32: txd32 %p txdpa 0x%lx txp %p txin %d txout %d " -+ "txavail %d txnodesc %d\n", di->txd32, PHYSADDRLO(di->txdpa), di->txp, di->txin, -+ di->txout, di->hnddma.txavail, di->hnddma.txnodesc); -+ -+ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n", -+ R_REG(di->osh, &di->d32txregs->control), -+ R_REG(di->osh, &di->d32txregs->addr), -+ R_REG(di->osh, &di->d32txregs->ptr), -+ R_REG(di->osh, &di->d32txregs->status)); -+ -+ if (dumpring && di->txd32) { -+ dma32_dumpring(di, b, di->txd32, di->txin, di->txout, di->ntxd); -+ } -+} -+ -+static void -+dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ if (di->nrxd == 0) { -+ return; -+ } -+ -+ bcm_bprintf(b, "DMA32: rxd32 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", -+ di->rxd32, PHYSADDRLO(di->rxdpa), di->rxp, di->rxin, di->rxout); -+ -+ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n", -+ R_REG(di->osh, &di->d32rxregs->control), -+ R_REG(di->osh, &di->d32rxregs->addr), -+ R_REG(di->osh, &di->d32rxregs->ptr), -+ R_REG(di->osh, &di->d32rxregs->status)); -+ if (di->rxd32 && dumpring) { -+ dma32_dumpring(di, b, di->rxd32, di->rxin, di->rxout, di->nrxd); -+ } -+} -+ -+static void -+dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ dma32_dumptx(di, b, dumpring); -+ dma32_dumprx(di, b, dumpring); -+} -+ -+static void -+dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, uint end, -+ uint max_num) -+{ -+ uint i; -+ -+ for (i = start; i != end; i = XXD((i + 1), max_num)) { -+ /* in the format of high->low 16 bytes */ -+ bcm_bprintf(b, "ring index %d: 0x%x %x %x %x\n", -+ i, R_SM(&ring[i].addrhigh), R_SM(&ring[i].addrlow), -+ R_SM(&ring[i].ctrl2), R_SM(&ring[i].ctrl1)); -+ } -+} -+ -+static void -+dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ bcm_bprintf(b, "DMA64: txd64 %p txdpa 0x%lx txdpahi 0x%lx txp %p txin %d txout %d " -+ "txavail %d txnodesc %d\n", di->txd64, PHYSADDRLO(di->txdpa), -+ PHYSADDRHI(di->txdpaorig), di->txp, di->txin, di->txout, di->hnddma.txavail, -+ di->hnddma.txnodesc); -+ -+ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddrlow 0x%x xmtaddrhigh 0x%x " -+ "xmtptr 0x%x xmtstatus0 0x%x xmtstatus1 0x%x\n", -+ R_REG(di->osh, &di->d64txregs->control), -+ R_REG(di->osh, &di->d64txregs->addrlow), -+ R_REG(di->osh, &di->d64txregs->addrhigh), -+ R_REG(di->osh, &di->d64txregs->ptr), -+ R_REG(di->osh, &di->d64txregs->status0), -+ R_REG(di->osh, &di->d64txregs->status1)); -+ -+ bcm_bprintf(b, "DMA64: DMA avoidance applied %d\n", di->dma_avoidance_cnt); -+ -+ if (dumpring && di->txd64) { -+ dma64_dumpring(di, b, di->txd64, di->txin, di->txout, di->ntxd); -+ } -+} -+ -+static void -+dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ if (di->nrxd == 0) { -+ return; -+ } -+ -+ bcm_bprintf(b, "DMA64: rxd64 %p rxdpa 0x%lx rxdpahi 0x%lx rxp %p rxin %d rxout %d\n", -+ di->rxd64, PHYSADDRLO(di->rxdpa), PHYSADDRHI(di->rxdpaorig), di->rxp, -+ di->rxin, di->rxout); -+ -+ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddrlow 0x%x rcvaddrhigh 0x%x rcvptr " -+ "0x%x rcvstatus0 0x%x rcvstatus1 0x%x\n", -+ R_REG(di->osh, &di->d64rxregs->control), -+ R_REG(di->osh, &di->d64rxregs->addrlow), -+ R_REG(di->osh, &di->d64rxregs->addrhigh), -+ R_REG(di->osh, &di->d64rxregs->ptr), -+ R_REG(di->osh, &di->d64rxregs->status0), -+ R_REG(di->osh, &di->d64rxregs->status1)); -+ if (di->rxd64 && dumpring) { -+ dma64_dumpring(di, b, di->rxd64, di->rxin, di->rxout, di->nrxd); -+ } -+} -+ -+static void -+dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) -+{ -+ dma64_dumptx(di, b, dumpring); -+ dma64_dumprx(di, b, dumpring); -+} -+#endif -+ -+ -+/* 32-bit DMA functions */ -+ -+static void -+dma32_txinit(dma_info_t *di) -+{ -+ uint32 control = XC_XE; -+ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ di->txin = di->txout = di->xs0cd = 0; -+ di->hnddma.txavail = di->ntxd - 1; -+ -+ /* clear tx descriptor ring */ -+ BZERO_SM(DISCARD_QUAL(di->txd32, void), (di->ntxd * sizeof(dma32dd_t))); -+ -+ /* These bits 20:18 (burstLen) of control register can be written but will take -+ * effect only if these bits are valid. So this will not affect previous versions -+ * of the DMA. They will continue to have those bits set to 0. -+ */ -+ control |= (di->txburstlen << XC_BL_SHIFT); -+ control |= (di->txmultioutstdrd << XC_MR_SHIFT); -+ control |= (di->txprefetchctl << XC_PC_SHIFT); -+ control |= (di->txprefetchthresh << XC_PT_SHIFT); -+ -+ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) { -+ control |= XC_PD; -+ } -+ W_REG(di->osh, &di->d32txregs->control, control); -+ _dma_ddtable_init(di, DMA_TX, di->txdpa); -+} -+ -+static bool -+dma32_txenabled(dma_info_t *di) -+{ -+ uint32 xc; -+ -+ /* If the chip is dead, it is not enabled :-) */ -+ xc = R_REG(di->osh, &di->d32txregs->control); -+ return ((xc != 0xffffffff) && (xc & XC_XE)); -+} -+ -+static void -+dma32_txsuspend(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ OR_REG(di->osh, &di->d32txregs->control, XC_SE); -+} -+ -+static void -+dma32_txresume(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txresume\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); -+} -+ -+static bool -+dma32_txsuspended(dma_info_t *di) -+{ -+ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); -+} -+ -+#ifdef WL_MULTIQUEUE -+static void -+dma32_txflush(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txflush\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ OR_REG(di->osh, &di->d32txregs->control, XC_SE | XC_FL); -+} -+ -+static void -+dma32_txflush_clear(dma_info_t *di) -+{ -+ uint32 status; -+ -+ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) -+ != XS_XS_DISABLED) && -+ (status != XS_XS_IDLE) && -+ (status != XS_XS_STOPPED), -+ (10000)); -+ AND_REG(di->osh, &di->d32txregs->control, ~XC_FL); -+} -+#endif /* WL_MULTIQUEUE */ -+ -+static void -+dma32_txreclaim(dma_info_t *di, txd_range_t range) -+{ -+ void *p; -+ -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, -+ (range == HNDDMA_RANGE_ALL) ? "all" : -+ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); -+ -+ if (di->txin == di->txout) { -+ return; -+ } -+ -+ while ((p = dma32_getnexttxp(di, range))) { -+ PKTFREE(di->osh, p, TRUE); -+ } -+} -+ -+static bool -+dma32_txstopped(dma_info_t *di) -+{ -+ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); -+} -+ -+static bool -+dma32_rxstopped(dma_info_t *di) -+{ -+ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); -+} -+ -+static bool -+dma32_alloc(dma_info_t *di, uint direction) -+{ -+ uint size; -+ uint ddlen; -+ void *va; -+ uint alloced; -+ uint16 align; -+ uint16 align_bits; -+ -+ ddlen = sizeof(dma32dd_t); -+ -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); -+ -+ alloced = 0; -+ align_bits = di->dmadesc_align; -+ align = (1 << align_bits); -+ -+ if (direction == DMA_TX) { -+ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, -+ &di->txdpaorig, &di->tx_dmah)) == NULL) { -+ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", -+ di->name)); -+ return FALSE; -+ } -+ -+ PHYSADDRHISET(di->txdpa, 0); -+ ASSERT(PHYSADDRHI(di->txdpaorig) == 0); -+ di->txd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); -+ di->txdalign = (uint)((int8 *)(uintptr)di->txd32 - (int8 *)va); -+ -+ PHYSADDRLOSET(di->txdpa, PHYSADDRLO(di->txdpaorig) + di->txdalign); -+ /* Make sure that alignment didn't overflow */ -+ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); -+ -+ di->txdalloc = alloced; -+ ASSERT(ISALIGNED(di->txd32, align)); -+ } else { -+ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, -+ &di->rxdpaorig, &di->rx_dmah)) == NULL) { -+ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", -+ di->name)); -+ return FALSE; -+ } -+ -+ PHYSADDRHISET(di->rxdpa, 0); -+ ASSERT(PHYSADDRHI(di->rxdpaorig) == 0); -+ di->rxd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); -+ di->rxdalign = (uint)((int8 *)(uintptr)di->rxd32 - (int8 *)va); -+ -+ PHYSADDRLOSET(di->rxdpa, PHYSADDRLO(di->rxdpaorig) + di->rxdalign); -+ /* Make sure that alignment didn't overflow */ -+ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); -+ di->rxdalloc = alloced; -+ ASSERT(ISALIGNED(di->rxd32, align)); -+ } -+ -+ return TRUE; -+} -+ -+static bool -+dma32_txreset(dma_info_t *di) -+{ -+ uint32 status; -+ -+ if (di->ntxd == 0) { -+ return TRUE; -+ } -+ -+ /* suspend tx DMA first */ -+ W_REG(di->osh, &di->d32txregs->control, XC_SE); -+ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) -+ != XS_XS_DISABLED) && -+ (status != XS_XS_IDLE) && -+ (status != XS_XS_STOPPED), -+ (10000)); -+ -+ W_REG(di->osh, &di->d32txregs->control, 0); -+ SPINWAIT(((status = (R_REG(di->osh, -+ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), -+ 10000); -+ -+ /* We should be disabled at this point */ -+ if (status != XS_XS_DISABLED) { -+ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); -+ ASSERT(status == XS_XS_DISABLED); -+ OSL_DELAY(300); -+ } -+ -+ return (status == XS_XS_DISABLED); -+} -+ -+static bool -+dma32_rxidle(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxidle\n", di->name)); -+ -+ if (di->nrxd == 0) { -+ return TRUE; -+ } -+ -+ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == -+ R_REG(di->osh, &di->d32rxregs->ptr)); -+} -+ -+static bool -+dma32_rxreset(dma_info_t *di) -+{ -+ uint32 status; -+ -+ if (di->nrxd == 0) { -+ return TRUE; -+ } -+ -+ W_REG(di->osh, &di->d32rxregs->control, 0); -+ SPINWAIT(((status = (R_REG(di->osh, -+ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), -+ 10000); -+ -+ return (status == RS_RS_DISABLED); -+} -+ -+static bool -+dma32_rxenabled(dma_info_t *di) -+{ -+ uint32 rc; -+ -+ rc = R_REG(di->osh, &di->d32rxregs->control); -+ return ((rc != 0xffffffff) && (rc & RC_RE)); -+} -+ -+static bool -+dma32_txsuspendedidle(dma_info_t *di) -+{ -+ if (di->ntxd == 0) { -+ return TRUE; -+ } -+ -+ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) { -+ return 0; -+ } -+ -+ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) { -+ return 0; -+ } -+ -+ OSL_DELAY(2); -+ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); -+} -+ -+/* !! tx entry routine -+ * supports full 32bit dma engine buffer addressing so -+ * dma buffers can cross 4 Kbyte page boundaries. -+ * -+ * WARNING: call must check the return value for error. -+ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems -+ */ -+static int -+dma32_txfast(dma_info_t *di, void *p0, bool commit) -+{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint16 txout; -+ uint32 flags = 0; -+ dmaaddr_t pa; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); -+ -+ txout = di->txout; -+ -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ uint nsegs, j; -+ hnddma_seg_map_t *map; -+ -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+#ifdef BCM_DMAPAD -+ len += PKTDMAPAD(di->osh, p); -+#endif -+ next = PKTNEXT(di->osh, p); -+ -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) { -+ goto outoftxd; -+ } -+ -+ if (len == 0) { -+ continue; -+ } -+ -+ if (DMASGLIST_ENAB) { -+ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); -+ } -+ -+ /* get physical address of buffer start */ -+ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); -+ -+ if (DMASGLIST_ENAB) { -+ map = &di->txp_dmah[txout]; -+ -+ /* See if all the segments can be accounted for */ -+ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) { -+ goto outoftxd; -+ } -+ -+ nsegs = map->nsegs; -+ } else { -+ nsegs = 1; -+ } -+ -+ for (j = 1; j <= nsegs; j++) { -+ flags = 0; -+ if (p == p0 && j == 1) { -+ flags |= CTRL_SOF; -+ } -+ -+ /* With a DMA segment list, Descriptor table is filled -+ * using the segment list instead of looping over -+ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when -+ * end of segment list is reached. -+ */ -+ if ((!DMASGLIST_ENAB && next == NULL) || -+ (DMASGLIST_ENAB && j == nsegs)) { -+ flags |= (CTRL_IOC | CTRL_EOF); -+ } -+ if (txout == (di->ntxd - 1)) { -+ flags |= CTRL_EOT; -+ } -+ -+ if (DMASGLIST_ENAB) { -+ len = map->segs[j - 1].length; -+ pa = map->segs[j - 1].addr; -+ } -+ ASSERT(PHYSADDRHI(pa) == 0); -+ -+ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); -+ ASSERT(di->txp[txout] == NULL); -+ -+ txout = NEXTTXD(txout); -+ } -+ -+ /* See above. No need to loop over individual buffers */ -+ if (DMASGLIST_ENAB) { -+ break; -+ } -+ } -+ -+ /* if last txd eof not set, fix it */ -+ if (!(flags & CTRL_EOF)) { -+ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); -+ } -+ -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; -+ -+ /* bump the tx descriptor index */ -+ di->txout = txout; -+ -+ /* kick the chip */ -+ if (commit) { -+ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); -+ } -+ -+ /* tx flow control */ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (0); -+ -+outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->hnddma.txavail = 0; -+ di->hnddma.txnobuf++; -+ di->hnddma.txnodesc++; -+ return (-1); -+} -+ -+/* -+ * Reclaim next completed txd (txds if using chained buffers) in the range -+ * specified and return associated packet. -+ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be -+ * transmitted as noted by the hardware "CurrDescr" pointer. -+ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be -+ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. -+ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and -+ * return associated packet regardless of the value of hardware pointers. -+ */ -+static void * -+dma32_getnexttxp(dma_info_t *di, txd_range_t range) -+{ -+ uint16 start, end, i; -+ uint16 active_desc; -+ void *txp; -+ -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, -+ (range == HNDDMA_RANGE_ALL) ? "all" : -+ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); -+ -+ if (di->ntxd == 0) { -+ return (NULL); -+ } -+ -+ txp = NULL; -+ -+ start = di->txin; -+ if (range == HNDDMA_RANGE_ALL) { -+ end = di->txout; -+ } else { -+ dma32regs_t *dregs = di->d32txregs; -+ -+ if (di->txin == di->xs0cd) { -+ end = (uint16)B2I(R_REG(di->osh, &dregs->status) & XS_CD_MASK, dma32dd_t); -+ di->xs0cd = end; -+ } else { -+ end = di->xs0cd; -+ } -+ -+ if (range == HNDDMA_RANGE_TRANSFERED) { -+ active_desc = (uint16)((R_REG(di->osh, &dregs->status) & XS_AD_MASK) >> -+ XS_AD_SHIFT); -+ active_desc = (uint16)B2I(active_desc, dma32dd_t); -+ if (end != active_desc) { -+ end = PREVTXD(active_desc); -+ } -+ } -+ } -+ -+ if ((start == 0) && (end > di->txout)) { -+ goto bogus; -+ } -+ -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ dmaaddr_t pa; -+ hnddma_seg_map_t *map = NULL; -+ uint size, j, nsegs; -+ -+ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow)); -+ PHYSADDRHISET(pa, 0); -+ -+ if (DMASGLIST_ENAB) { -+ map = &di->txp_dmah[i]; -+ size = map->origsize; -+ nsegs = map->nsegs; -+ } else { -+ size = (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK); -+ nsegs = 1; -+ } -+ -+ for (j = nsegs; j > 0; j--) { -+ W_SM(&di->txd32[i].addr, 0xdeadbeef); -+ -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ if (j > 1) { -+ i = NEXTTXD(i); -+ } -+ } -+ -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+ } -+ -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (txp); -+ -+bogus: -+ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+ return (NULL); -+} -+ -+static void * -+dma32_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ uint16 i, curr; -+ void *rxp; -+ dmaaddr_t pa; -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma32_rxenabled(di)); -+ -+ i = di->rxin; -+ -+ /* return if no packets posted */ -+ if (i == di->rxout) { -+ return (NULL); -+ } -+ -+ if (di->rxin == di->rs0cd) { -+ curr = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); -+ di->rs0cd = curr; -+ } else { -+ curr = di->rs0cd; -+ } -+ -+ /* ignore curr if forceall */ -+ if (!forceall && (i == curr)) { -+ return (NULL); -+ } -+ -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; -+ -+ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow)); -+ PHYSADDRHISET(pa, 0); -+ -+ /* clear this packet from the descriptor ring */ -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ DMA_UNMAP(di->osh, pa, -+ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+ -+ W_SM(&di->rxd32[i].addr, 0xdeadbeef); -+ -+ di->rxin = NEXTRXD(i); -+ -+ return (rxp); -+} -+ -+/* -+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). -+ */ -+static void -+dma32_txrotate(dma_info_t *di) -+{ -+ uint16 ad; -+ uint nactive; -+ uint rot; -+ uint16 old, new; -+ uint32 w; -+ uint16 first, last; -+ -+ ASSERT(dma32_txsuspendedidle(di)); -+ -+ nactive = _dma_txactive(di); -+ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); -+ rot = TXD(ad - di->txin); -+ -+ ASSERT(rot < di->ntxd); -+ -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; -+ } -+ -+ first = di->txin; -+ last = PREVTXD(di->txout); -+ -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); -+ -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; -+ if (new == (di->ntxd - 1)) { -+ w |= CTRL_EOT; -+ } -+ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); -+ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); -+ -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); -+ -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ -+ /* Move the segment map as well */ -+ if (DMASGLIST_ENAB) { -+ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); -+ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); -+ } -+ -+ di->txp[old] = NULL; -+ } -+ -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ /* kick the chip */ -+ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); -+} -+ -+/* 64-bit DMA functions */ -+ -+static void -+dma64_txinit(dma_info_t *di) -+{ -+ uint32 control; -+ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ di->txin = di->txout = di->xs0cd = di->xs0cd_snapshot = 0; -+ di->hnddma.txavail = di->ntxd - 1; -+ -+ /* clear tx descriptor ring */ -+ BZERO_SM((void *)(uintptr)di->txd64, (di->ntxd * sizeof(dma64dd_t))); -+ -+ /* These bits 20:18 (burstLen) of control register can be written but will take -+ * effect only if these bits are valid. So this will not affect previous versions -+ * of the DMA. They will continue to have those bits set to 0. -+ */ -+ control = R_REG(di->osh, &di->d64txregs->control); -+ control = (control & ~D64_XC_BL_MASK) | (di->txburstlen << D64_XC_BL_SHIFT); -+ control = (control & ~D64_XC_MR_MASK) | (di->txmultioutstdrd << D64_XC_MR_SHIFT); -+ control = (control & ~D64_XC_PC_MASK) | (di->txprefetchctl << D64_XC_PC_SHIFT); -+ control = (control & ~D64_XC_PT_MASK) | (di->txprefetchthresh << D64_XC_PT_SHIFT); -+ W_REG(di->osh, &di->d64txregs->control, control); -+ -+ control = D64_XC_XE; -+ /* DMA engine with out alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (!di->aligndesc_4k) { -+ _dma_ddtable_init(di, DMA_TX, di->txdpa); -+ } -+ -+ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) { -+ control |= D64_XC_PD; -+ } -+ OR_REG(di->osh, &di->d64txregs->control, control); -+ -+ /* DMA engine with alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (di->aligndesc_4k) { -+ _dma_ddtable_init(di, DMA_TX, di->txdpa); -+ } -+} -+ -+static bool -+dma64_txenabled(dma_info_t *di) -+{ -+ uint32 xc; -+ -+ /* If the chip is dead, it is not enabled :-) */ -+ xc = R_REG(di->osh, &di->d64txregs->control); -+ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); -+} -+ -+static void -+dma64_txsuspend(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE); -+} -+ -+static void -+dma64_txresume(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txresume\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE); -+} -+ -+static bool -+dma64_txsuspended(dma_info_t *di) -+{ -+ return (di->ntxd == 0) || -+ ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); -+} -+ -+#ifdef WL_MULTIQUEUE -+static void -+dma64_txflush(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txflush\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE | D64_XC_FL); -+} -+ -+static void -+dma64_txflush_clear(dma_info_t *di) -+{ -+ uint32 status; -+ -+ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); -+ -+ if (di->ntxd == 0) { -+ return; -+ } -+ -+ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != -+ D64_XS0_XS_DISABLED) && -+ (status != D64_XS0_XS_IDLE) && -+ (status != D64_XS0_XS_STOPPED), -+ 10000); -+ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_FL); -+} -+#endif /* WL_MULTIQUEUE */ -+ -+static void BCMFASTPATH -+dma64_txreclaim(dma_info_t *di, txd_range_t range) -+{ -+ void *p; -+ -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, -+ (range == HNDDMA_RANGE_ALL) ? "all" : -+ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); -+ -+ if (di->txin == di->txout) { -+ return; -+ } -+ -+ while ((p = dma64_getnexttxp(di, range))) { -+ /* For unframed data, we don't have any packets to free */ -+ if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED)) { -+ PKTFREE(di->osh, p, TRUE); -+ } -+ } -+} -+ -+static bool -+dma64_txstopped(dma_info_t *di) -+{ -+ return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); -+} -+ -+static bool -+dma64_rxstopped(dma_info_t *di) -+{ -+ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); -+} -+ -+static bool -+dma64_alloc(dma_info_t *di, uint direction) -+{ -+ uint32 size; -+ uint ddlen; -+ void *va; -+ uint alloced = 0; -+ uint32 align; -+ uint16 align_bits; -+ -+ ddlen = sizeof(dma64dd_t); -+ -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); -+ align_bits = di->dmadesc_align; -+ align = (1 << align_bits); -+ -+ if (direction == DMA_TX) { -+ if ((va = dma_ringalloc(di->osh, -+ (di->d64_xs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, -+ size, &align_bits, &alloced, -+ &di->txdpaorig, &di->tx_dmah)) == NULL) { -+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", -+ di->name)); -+ return FALSE; -+ } -+ align = (1 << align_bits); -+ -+ /* adjust the pa by rounding up to the alignment */ -+ PHYSADDRLOSET(di->txdpa, ROUNDUP(PHYSADDRLO(di->txdpaorig), align)); -+ PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig)); -+ -+ /* Make sure that alignment didn't overflow */ -+ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); -+ -+ /* find the alignment offset that was used */ -+ di->txdalign = (uint)(PHYSADDRLO(di->txdpa) - PHYSADDRLO(di->txdpaorig)); -+ -+ /* adjust the va by the same offset */ -+ di->txd64 = (dma64dd_t *)((uintptr)va + di->txdalign); -+ -+ /* printk("%s di->txd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txd64), PHYSADDRLO(di->txd64)); */ -+ /* printk("%s di->txdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txdpa), PHYSADDRLO(di->txdpa)); */ -+ di->txdalloc = alloced; -+ ASSERT(ISALIGNED(PHYSADDRLO(di->txdpa), align)); -+ } else { -+ if ((va = dma_ringalloc(di->osh, -+ (di->d64_rs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, -+ size, &align_bits, &alloced, -+ &di->rxdpaorig, &di->rx_dmah)) == NULL) { -+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", -+ di->name)); -+ return FALSE; -+ } -+ align = (1 << align_bits); -+ -+ /* adjust the pa by rounding up to the alignment */ -+ PHYSADDRLOSET(di->rxdpa, ROUNDUP(PHYSADDRLO(di->rxdpaorig), align)); -+ PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig)); -+ -+ /* Make sure that alignment didn't overflow */ -+ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); -+ -+ /* find the alignment offset that was used */ -+ di->rxdalign = (uint)(PHYSADDRLO(di->rxdpa) - PHYSADDRLO(di->rxdpaorig)); -+ -+ /* adjust the va by the same offset */ -+ di->rxd64 = (dma64dd_t *)((uintptr)va + di->rxdalign); -+ -+ /* printk("%s di->rxd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxd64), PHYSADDRLO(di->rxd64)); */ -+ /* printk("%s di->rxdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxdpa), PHYSADDRLO(di->rxdpa)); */ -+ di->rxdalloc = alloced; -+ ASSERT(ISALIGNED(PHYSADDRLO(di->rxdpa), align)); -+ } -+ -+ return TRUE; -+} -+ -+static bool -+dma64_txreset(dma_info_t *di) -+{ -+ uint32 status; -+ -+ if (di->ntxd == 0) { -+ return TRUE; -+ } -+ -+ /* suspend tx DMA first */ -+ W_REG(di->osh, &di->d64txregs->control, D64_XC_SE); -+ -+ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != -+ D64_XS0_XS_DISABLED) && -+ (status != D64_XS0_XS_IDLE) && -+ (status != D64_XS0_XS_STOPPED), -+ 10000); -+ -+ W_REG(di->osh, &di->d64txregs->control, 0); -+ -+ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != -+ D64_XS0_XS_DISABLED), -+ 10000); -+ -+ /* We should be disabled at this point */ -+ if (status != D64_XS0_XS_DISABLED) { -+ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); -+ ASSERT(status == D64_XS0_XS_DISABLED); -+ OSL_DELAY(300); -+ } -+ -+ return (status == D64_XS0_XS_DISABLED); -+} -+ -+static bool -+dma64_rxidle(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxidle\n", di->name)); -+ -+ if (di->nrxd == 0) { -+ return TRUE; -+ } -+ -+ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == -+ (R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK)); -+} -+ -+static bool -+dma64_rxreset(dma_info_t *di) -+{ -+ uint32 status; -+ -+ if (di->nrxd == 0) { -+ return TRUE; -+ } -+ -+ W_REG(di->osh, &di->d64rxregs->control, 0); -+ -+ SPINWAIT(((status = (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != -+ D64_RS0_RS_DISABLED), 10000); -+ -+ return (status == D64_RS0_RS_DISABLED); -+} -+ -+static bool -+dma64_rxenabled(dma_info_t *di) -+{ -+ uint32 rc; -+ -+ rc = R_REG(di->osh, &di->d64rxregs->control); -+ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); -+} -+ -+static bool -+dma64_txsuspendedidle(dma_info_t *di) -+{ -+ -+ if (di->ntxd == 0) { -+ return TRUE; -+ } -+ -+ if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE)) { -+ return 0; -+ } -+ -+ if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) { -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* Useful when sending unframed data. This allows us to get a progress report from the DMA. -+ * We return a pointer to the beginning of the data buffer of the current descriptor. -+ * If DMA is idle, we return NULL. -+ */ -+static void* -+dma64_getpos(dma_info_t *di, bool direction) -+{ -+ void *va; -+ bool idle; -+ uint16 cur_idx; -+ -+ if (direction == DMA_TX) { -+ cur_idx = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); -+ idle = !NTXDACTIVE(di->txin, di->txout); -+ va = di->txp[cur_idx]; -+ } else { -+ cur_idx = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); -+ idle = !NRXDACTIVE(di->rxin, di->rxout); -+ va = di->rxp[cur_idx]; -+ } -+ -+ /* If DMA is IDLE, return NULL */ -+ if (idle) { -+ DMA_TRACE(("%s: DMA idle, return NULL\n", __FUNCTION__)); -+ va = NULL; -+ } -+ -+ return va; -+} -+ -+/* TX of unframed data -+ * -+ * Adds a DMA ring descriptor for the data pointed to by "buf". -+ * This is for DMA of a buffer of data and is unlike other hnddma TX functions -+ * that take a pointer to a "packet" -+ * Each call to this is results in a single descriptor being added for "len" bytes of -+ * data starting at "buf", it doesn't handle chained buffers. -+ */ -+static int -+dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit) -+{ -+ uint16 txout; -+ uint32 flags = 0; -+ dmaaddr_t pa; /* phys addr */ -+ -+ txout = di->txout; -+ -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) { -+ goto outoftxd; -+ } -+ -+ if (len == 0) { -+ return 0; -+ } -+ -+#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) -+ pa = virt_to_phys(buf); -+#else -+ pa = DMA_MAP(di->osh, buf, len, DMA_TX, NULL, &di->txp_dmah[txout]); -+#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ -+ -+ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); -+ -+ if (txout == (di->ntxd - 1)) { -+ flags |= D64_CTRL1_EOT; -+ } -+ -+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); -+ ASSERT(di->txp[txout] == NULL); -+ -+ /* save the buffer pointer - used by dma_getpos */ -+ di->txp[txout] = buf; -+ -+ txout = NEXTTXD(txout); -+ /* bump the tx descriptor index */ -+ di->txout = txout; -+ -+ /* kick the chip */ -+ if (commit) { -+ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); -+ } -+ -+ /* tx flow control */ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (0); -+ -+outoftxd: -+ DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __FUNCTION__)); -+ di->hnddma.txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); -+} -+ -+/* RX of unframed data -+ * -+ * Adds a DMA ring descriptor for the data pointed to by "buf". -+ * This is for DMA of a buffer of data and is unlike other hnddma TX functions -+ * that take a pointer to a "packet" -+ * Each call to this is results in a single descriptor being added for "len" bytes of -+ * data starting at "buf", it doesn't handle chained buffers. -+ */ -+static int -+dma64_rxunframed(dma_info_t *di, void *buf, uint len, bool commit) -+{ -+ uint16 rxout; -+ uint32 flags = 0; -+ dmaaddr_t pa; /* phys addr */ -+ -+ rxout = di->rxout; -+ -+ /* return nonzero if out of rx descriptors */ -+ if (NEXTRXD(rxout) == di->rxin) { -+ goto outofrxd; -+ } -+ -+ if (len == 0) { -+ return 0; -+ } -+ -+#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) -+ pa = virt_to_phys(buf); -+#else -+ pa = DMA_MAP(di->osh, buf, len, DMA_RX, NULL, &di->rxp_dmah[rxout]); -+#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ -+ -+ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); -+ -+ if (rxout == (di->nrxd - 1)) { -+ flags |= D64_CTRL1_EOT; -+ } -+ -+ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, len); -+ ASSERT(di->rxp[rxout] == NULL); -+ -+ /* save the buffer pointer - used by dma_getpos */ -+ di->rxp[rxout] = buf; -+ -+ rxout = NEXTRXD(rxout); -+ /* bump the tx descriptor index */ -+ di->rxout = rxout; -+ -+ /* kick the chip */ -+ if (commit) { -+ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); -+ //DBG("%s (Control Reg)W_REG: 0x%x Value: 0x%x\n", __FUNCTION__, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); -+ } -+ -+ /* tx flow control */ -+ //di->hnddma.rxavail = di->nrxd - NRXDACTIVE(di->rxin, di->rxout) - 1; -+ -+ return (0); -+ -+outofrxd: -+ DMA_ERROR(("%s: %s: out of rxds !!!\n", di->name, __FUNCTION__)); -+ //di->hnddma.rxavail = 0; -+ di->hnddma.rxnobuf++; -+ return (-1); -+} -+ -+/* !! tx entry routine -+ * WARNING: call must check the return value for error. -+ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems -+ */ -+static int BCMFASTPATH -+dma64_txfast(dma_info_t *di, void *p0, bool commit) -+{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint16 txout; -+ uint32 flags = 0; -+ dmaaddr_t pa; -+ bool war; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); -+ -+ txout = di->txout; -+ war = (di->hnddma.dmactrlflags & DMA_CTRL_DMA_AVOIDANCE_WAR) ? TRUE : FALSE; -+ -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ uint nsegs, j, segsadd; -+ hnddma_seg_map_t *map = NULL; -+ -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+#ifdef BCM_DMAPAD -+ len += PKTDMAPAD(di->osh, p); -+#endif /* BCM_DMAPAD */ -+ next = PKTNEXT(di->osh, p); -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ prefetch_range(next, SKB_PREFETCH_LEN); -+#endif -+ -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) { -+ goto outoftxd; -+ } -+ -+ if (len == 0) { -+ continue; -+ } -+ -+ /* get physical address of buffer start */ -+ if (DMASGLIST_ENAB) { -+ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); -+ } -+ -+#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) -+ pa = virt_to_phys(data); -+#else -+ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); -+#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ -+ -+ -+ if (DMASGLIST_ENAB) { -+ map = &di->txp_dmah[txout]; -+ -+ /* See if all the segments can be accounted for */ -+ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) { -+ goto outoftxd; -+ } -+ -+ nsegs = map->nsegs; -+ } else { -+ nsegs = 1; -+ } -+ -+ segsadd = 0; -+ for (j = 1; j <= nsegs; j++) { -+ flags = 0; -+ if (p == p0 && j == 1) { -+ flags |= D64_CTRL1_SOF; -+ } -+ -+ /* With a DMA segment list, Descriptor table is filled -+ * using the segment list instead of looping over -+ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when -+ * end of segment list is reached. -+ */ -+ if ((!DMASGLIST_ENAB && next == NULL) || -+ (DMASGLIST_ENAB && j == nsegs)) { -+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); -+ } -+ if (txout == (di->ntxd - 1)) { -+ flags |= D64_CTRL1_EOT; -+ } -+ -+ if (DMASGLIST_ENAB) { -+ len = map->segs[j - 1].length; -+ pa = map->segs[j - 1].addr; -+ if (len > 128 && war) { -+ uint remain, new_len, align64; -+ /* check for 64B aligned of pa */ -+ align64 = (uint)(PHYSADDRLO(pa) & 0x3f); -+ align64 = (64 - align64) & 0x3f; -+ new_len = len - align64; -+ remain = new_len % 128; -+ if (remain > 0 && remain <= 4) { -+ uint32 buf_addr_lo; -+ uint32 tmp_flags = -+ flags & (~(D64_CTRL1_EOF | D64_CTRL1_IOC)); -+ flags &= ~(D64_CTRL1_SOF | D64_CTRL1_EOT); -+ remain += 64; -+ dma64_dd_upd(di, di->txd64, pa, txout, -+ &tmp_flags, len-remain); -+ ASSERT(di->txp[txout] == NULL); -+ txout = NEXTTXD(txout); -+ /* return nonzero if out of tx descriptors */ -+ if (txout == di->txin) { -+ DMA_ERROR(("%s: dma_txfast: Out-of-DMA" -+ " descriptors (txin %d txout %d" -+ " nsegs %d)\n", __FUNCTION__, -+ di->txin, di->txout, nsegs)); -+ goto outoftxd; -+ } -+ if (txout == (di->ntxd - 1)) { -+ flags |= D64_CTRL1_EOT; -+ } -+ buf_addr_lo = PHYSADDRLO(pa); -+ PHYSADDRLOSET(pa, (PHYSADDRLO(pa) + (len-remain))); -+ if (PHYSADDRLO(pa) < buf_addr_lo) { -+ PHYSADDRHISET(pa, (PHYSADDRHI(pa) + 1)); -+ } -+ len = remain; -+ segsadd++; -+ di->dma_avoidance_cnt++; -+ } -+ } -+ } -+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); -+ ASSERT(di->txp[txout] == NULL); -+ -+ txout = NEXTTXD(txout); -+ /* return nonzero if out of tx descriptors */ -+ if (txout == di->txin) { -+ DMA_ERROR(("%s: dma_txfast: Out-of-DMA descriptors" -+ " (txin %d txout %d nsegs %d)\n", __FUNCTION__, -+ di->txin, di->txout, nsegs)); -+ goto outoftxd; -+ } -+ } -+ if (segsadd && DMASGLIST_ENAB) { -+ map->nsegs += segsadd; -+ } -+ -+ /* See above. No need to loop over individual buffers */ -+ if (DMASGLIST_ENAB) { -+ break; -+ } -+ } -+ -+ /* if last txd eof not set, fix it */ -+ if (!(flags & D64_CTRL1_EOF)) { -+ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, -+ BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); -+ } -+ -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; -+ -+ /* bump the tx descriptor index */ -+ di->txout = txout; -+ -+ /* Spin lock to prevent TX discriptor protocol errors when using SG lists */ -+ spin_lock(&di->des_lock); -+ spin_unlock(&di->des_lock); -+ -+ /* kick the chip */ -+ if (commit) { -+ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); -+ } -+ -+ /* tx flow control */ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (0); -+ -+outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->hnddma.txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); -+} -+ -+/* -+ * Reclaim next completed txd (txds if using chained buffers) in the range -+ * specified and return associated packet. -+ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be -+ * transmitted as noted by the hardware "CurrDescr" pointer. -+ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be -+ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. -+ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and -+ * return associated packet regardless of the value of hardware pointers. -+ */ -+static void * BCMFASTPATH -+dma64_getnexttxp(dma_info_t *di, txd_range_t range) -+{ -+ uint16 start, end, i; -+ uint16 active_desc; -+ void *txp; -+ -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, -+ (range == HNDDMA_RANGE_ALL) ? "all" : -+ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); -+ -+ if (di->ntxd == 0) { -+ return (NULL); -+ } -+ -+ txp = NULL; -+ -+ start = di->txin; -+ if (range == HNDDMA_RANGE_ALL) { -+ end = di->txout; -+ } else { -+ dma64regs_t *dregs = di->d64txregs; -+ -+ if (di->txin == di->xs0cd) { -+ end = (uint16)(B2I(((R_REG(di->osh, &dregs->status0) & D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t)); -+ di->xs0cd = end; -+ } else { -+ end = di->xs0cd; -+ } -+ -+ if (range == HNDDMA_RANGE_TRANSFERED) { -+ active_desc = (uint16)(R_REG(di->osh, &dregs->status1) & D64_XS1_AD_MASK); -+ active_desc = (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; -+ active_desc = B2I(active_desc, dma64dd_t); -+ if (end != active_desc) { -+ end = PREVTXD(active_desc); -+ } -+ } -+ } -+ -+ if ((start == 0) && (end > di->txout)) { -+ goto bogus; -+ } -+ -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ dmaaddr_t pa; -+ hnddma_seg_map_t *map = NULL; -+ uint size, j, nsegs; -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ prefetch_range(di->txp[NEXTTXD(i)], SKB_PREFETCH_LEN); -+#endif -+ -+ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow)); -+ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) - di->dataoffsethigh)); -+ -+ if (DMASGLIST_ENAB) { -+ map = &di->txp_dmah[i]; -+ size = map->origsize; -+ nsegs = map->nsegs; -+ if (nsegs > (uint)NTXDACTIVE(i, end)) { -+ di->xs0cd = i; -+ break; -+ } -+ } else { -+ size = (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK); -+ nsegs = 1; -+ } -+ -+ for (j = nsegs; j > 0; j--) { -+ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); -+ -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ if (j > 1) { -+ i = NEXTTXD(i); -+ } -+ } -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+ } -+ -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (txp); -+ -+bogus: -+ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+ return (NULL); -+} -+ -+static void * BCMFASTPATH -+dma64_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ uint16 i, curr; -+ void *rxp; -+ dmaaddr_t pa; -+ -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma64_rxenabled(di)); -+ -+ i = di->rxin; -+ -+ /* return if no packets posted */ -+ if (i == di->rxout) { -+ return (NULL); -+ } -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH -+ prefetch_range(di->rxp[NEXTRXD(i)], SKB_PREFETCH_LEN); -+#endif -+ -+ if (di->rxin == di->rs0cd) { -+ curr = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); -+ di->rs0cd = curr; -+ } else { -+ curr = di->rs0cd; -+ } -+ -+ /* ignore curr if forceall */ -+ if (!forceall && (i == curr)) { -+ return (NULL); -+ } -+ -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; -+ -+ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow)); -+ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) - di->dataoffsethigh)); -+ -+ /* clear this packet from the descriptor ring */ -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ DMA_UNMAP(di->osh, pa, -+ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+ -+ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); -+ -+ di->rxin = NEXTRXD(i); -+ -+ return (rxp); -+} -+ -+static bool -+_dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) -+{ -+ uint32 w; -+ OR_REG(osh, &dma64regs->control, D64_XC_AE); -+ w = R_REG(osh, &dma64regs->control); -+ AND_REG(osh, &dma64regs->control, ~D64_XC_AE); -+ return ((w & D64_XC_AE) == D64_XC_AE); -+} -+ -+/* -+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). -+ */ -+static void -+dma64_txrotate(dma_info_t *di) -+{ -+ uint16 ad; -+ uint nactive; -+ uint rot; -+ uint16 old, new; -+ uint32 w; -+ uint16 first, last; -+ -+ ASSERT(dma64_txsuspendedidle(di)); -+ -+ nactive = _dma_txactive(di); -+ ad = B2I((((R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK) -+ - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t); -+ rot = TXD(ad - di->txin); -+ -+ ASSERT(rot < di->ntxd); -+ -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; -+ } -+ -+ first = di->txin; -+ last = PREVTXD(di->txout); -+ -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); -+ -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; -+ if (new == (di->ntxd - 1)) { -+ w |= D64_CTRL1_EOT; -+ } -+ W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); -+ -+ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); -+ W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); -+ -+ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); -+ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); -+ -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); -+ W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef)); -+ -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ -+ /* Move the map */ -+ if (DMASGLIST_ENAB) { -+ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); -+ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); -+ } -+ -+ di->txp[old] = NULL; -+ } -+ -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ /* kick the chip */ -+ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(di->txout, dma64dd_t)); -+} -+ -+uint -+BCMATTACHFN(dma_addrwidth)(si_t *sih, void *dmaregs) -+{ -+ dma32regs_t *dma32regs; -+ osl_t *osh; -+ -+ osh = si_osh(sih); -+ -+ /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */ -+ /* DMA engine is 64-bit capable */ -+ if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) { -+ /* backplane are 64-bit capable */ -+ if (si_backplane64(sih)) { -+ /* If bus is System Backplane or PCIE then we can access 64-bits */ -+ if ((BUSTYPE(sih->bustype) == SI_BUS) || -+ ((BUSTYPE(sih->bustype) == PCI_BUS) && -+ ((sih->buscoretype == PCIE_CORE_ID) || -+ (sih->buscoretype == PCIE2_CORE_ID)))) { -+ return (DMADDRWIDTH_64); -+ } -+ } -+ -+ /* DMA64 is always 32-bit capable, AE is always TRUE */ -+ ASSERT(_dma64_addrext(osh, (dma64regs_t *)dmaregs)); -+ -+ return (DMADDRWIDTH_32); -+ } -+ -+ /* Start checking for 32-bit / 30-bit addressing */ -+ dma32regs = (dma32regs_t *)dmaregs; -+ -+ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ -+ if ((BUSTYPE(sih->bustype) == SI_BUS) || -+ ((BUSTYPE(sih->bustype) == PCI_BUS) && -+ ((sih->buscoretype == PCIE_CORE_ID) || -+ (sih->buscoretype == PCIE2_CORE_ID))) || -+ (_dma32_addrext(osh, dma32regs))) { -+ return (DMADDRWIDTH_32); -+ } -+ -+ /* Fallthru */ -+ return (DMADDRWIDTH_30); -+} -+ -+static int -+_dma_pktpool_set(dma_info_t *di, pktpool_t *pool) -+{ -+ ASSERT(di); -+ ASSERT(di->pktpool == NULL); -+ di->pktpool = pool; -+ return 0; -+} -+ -+static bool -+_dma_rxtx_error(dma_info_t *di, bool istx) -+{ -+ uint32 status1 = 0; -+ uint16 curr; -+ -+ if (DMA64_ENAB(di) && DMA64_MODE(di)) { -+ if (istx) { -+ status1 = R_REG(di->osh, &di->d64txregs->status1); -+ -+ if ((status1 & D64_XS1_XE_MASK) != D64_XS1_XE_NOERR) { -+ return TRUE; -+ } else if (si_coreid(di->sih) == GMAC_CORE_ID && si_corerev(di->sih) >= 4) { -+ curr = (uint16)(B2I(((R_REG(di->osh, &di->d64txregs->status0) & -+ D64_XS0_CD_MASK) - di->xmtptrbase) & -+ D64_XS0_CD_MASK, dma64dd_t)); -+ -+ if (NTXDACTIVE(di->txin, di->txout) != 0 && -+ curr == di->xs0cd_snapshot) { -+ -+ /* suspicious */ -+ return TRUE; -+ } -+ di->xs0cd_snapshot = di->xs0cd = curr; -+ -+ return FALSE; -+ } else { -+ return FALSE; -+ } -+ } -+ else { -+ -+ status1 = R_REG(di->osh, &di->d64rxregs->status1); -+ -+ if ((status1 & D64_RS1_RE_MASK) != D64_RS1_RE_NOERR) { -+ return TRUE; -+ } else { -+ return FALSE; -+ } -+ } -+ } else if (DMA32_ENAB(di)) { -+ return FALSE; -+ } else { -+ ASSERT(0); -+ return FALSE; -+ } -+ -+} -+ -+void -+_dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen) -+{ -+ di->rxburstlen = rxburstlen; -+ di->txburstlen = txburstlen; -+} -+ -+void -+_dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval) -+{ -+ switch (paramid) { -+ case HNDDMA_PID_TX_MULTI_OUTSTD_RD: -+ di->txmultioutstdrd = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_TX_PREFETCH_CTL: -+ di->txprefetchctl = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_TX_PREFETCH_THRESH: -+ di->txprefetchthresh = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_TX_BURSTLEN: -+ di->txburstlen = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_RX_PREFETCH_CTL: -+ di->rxprefetchctl = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_RX_PREFETCH_THRESH: -+ di->rxprefetchthresh = (uint8)paramval; -+ break; -+ -+ case HNDDMA_PID_RX_BURSTLEN: -+ di->rxburstlen = (uint8)paramval; -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static bool -+_dma_glom_enable(dma_info_t *di, uint32 val) -+{ -+ dma64regs_t *dregs = di->d64rxregs; -+ bool ret = TRUE; -+ if (val) { -+ OR_REG(di->osh, &dregs->control, D64_RC_GE); -+ if (!(R_REG(di->osh, &dregs->control) & D64_RC_GE)) -+ ret = FALSE; -+ } else { -+ AND_REG(di->osh, &dregs->control, ~D64_RC_GE); -+ } -+ return ret; -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.c 2017-11-09 17:53:44.051300000 +0800 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+#include -+ -+uint32 hr2_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ -+ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, -+ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ -+ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, -+ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ -+ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, -+ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, -+ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, -+ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ -+ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, -+ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ -+ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, -+ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ -+ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, -+ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ -+ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, -+ //#define I2S_CORE_ID 0x834 /* I2S core */ -+ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, -+ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ -+ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, -+ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ -+ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, -+ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ -+ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, -+ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ -+ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, -+ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ -+ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, -+ //#define EROM_CORE_ID 0x366 /* EROM core ID */ -+ 0x43b36601, 0x00000201, 0x18130005, -+ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, -+ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, -+ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, -+ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, -+ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, -+ 0x18134285, 0x18135385, 0x18136485, -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hr2_erom.h 2017-11-09 17:53:44.052298000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+ -+#ifndef _hr2_erom_h_ -+#define _hr2_erom_h_ -+ -+extern uint32 hr2_erom[]; -+ -+#endif //_hr2_erom_h_ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.c 2017-11-09 17:53:44.053293000 +0800 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Hurricane3 sudo EROM -+ * -+ */ -+#include -+ -+uint32 hr3_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18042005, 0x181100c5, -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hr3_erom.h 2017-11-09 17:53:44.054288000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Hurricane3 sudo EROM -+ * -+ */ -+ -+#ifndef _hr3_erom_h_ -+#define _hr3_erom_h_ -+ -+extern uint32 hr3_erom[]; -+ -+#endif /* _hr3_erom_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.c 2017-11-09 17:53:44.054324000 +0800 -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+#include -+ -+uint32 hx4_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ -+ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, -+ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ -+ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, -+ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, -+ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ -+ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, -+ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, -+ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, -+ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ -+ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, -+ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ -+ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, -+ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ -+ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, -+ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ -+ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, -+ //#define I2S_CORE_ID 0x834 /* I2S core */ -+ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, -+ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ -+ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, -+ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ -+ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, -+ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ -+ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, -+ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ -+ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, -+ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ -+ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, -+ //#define EROM_CORE_ID 0x366 /* EROM core ID */ -+ 0x43b36601, 0x00000201, 0x18130005, -+ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, -+ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, -+ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, -+ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, -+ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, -+ 0x18134285, 0x18135385, 0x18136485, -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/hx4_erom.h 2017-11-09 17:53:44.055299000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+ -+#ifndef _hx4_erom_h_ -+#define _hx4_erom_h_ -+ -+extern uint32 hx4_erom[]; -+ -+#endif //_hx4_erom_h_ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.c 2017-11-09 17:53:44.056295000 +0800 -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+#include -+ -+uint32 kt2_erom[] = { -+ //#define CC_CORE_ID 0x800 /* chipcommon core */ -+ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, -+ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ -+ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, -+ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ -+ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, -+ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, -+ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, -+ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ -+ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, -+ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, -+ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, -+ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ -+ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, -+ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ -+ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, -+ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ -+ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, -+ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ -+ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, -+ //#define I2S_CORE_ID 0x834 /* I2S core */ -+ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, -+ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ -+ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, -+ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ -+ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, -+ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ -+ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, -+ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ -+ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, -+ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ -+ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, -+ //#define EROM_CORE_ID 0x366 /* EROM core ID */ -+ 0x43b36601, 0x00000201, 0x18130005, -+ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, -+ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, -+ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, -+ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, -+ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, -+ 0x18134285, 0x18135385, 0x18136485, -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/kt2_erom.h 2017-11-09 17:53:44.057293000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Helix4 sudo EROM -+ * -+ */ -+ -+#ifndef _kt2_erom_h_ -+#define _kt2_erom_h_ -+ -+extern uint32 kt2_erom[]; -+ -+#endif //_kt2_erom_h_ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/linux_osl.c b/drivers/net/ethernet/broadcom/gmac/src/shared/linux_osl.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/linux_osl.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/linux_osl.c 2017-11-09 17:53:44.058299000 +0800 -@@ -0,0 +1,1266 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Linux OS Independent Layer -+ * -+ * $Id: linux_osl.c 322208 2012-03-20 01:53:23Z $ -+ */ -+ -+#define LINUX_PORT -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef mips -+#include -+#endif /* mips */ -+#include -+ -+ -+#include -+#include -+ -+#define PCI_CFG_RETRY 10 -+ -+#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ -+#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ -+ -+#ifdef DHD_USE_STATIC_BUF -+#define STATIC_BUF_MAX_NUM 16 -+#define STATIC_BUF_SIZE (PAGE_SIZE*2) -+#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) -+ -+typedef struct bcm_static_buf { -+ struct semaphore static_sem; -+ unsigned char *buf_ptr; -+ unsigned char buf_use[STATIC_BUF_MAX_NUM]; -+} bcm_static_buf_t; -+ -+static bcm_static_buf_t *bcm_static_buf = 0; -+ -+#define STATIC_PKT_MAX_NUM 8 -+ -+typedef struct bcm_static_pkt { -+ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; -+ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; -+ struct semaphore osl_pkt_sem; -+ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2]; -+} bcm_static_pkt_t; -+ -+static bcm_static_pkt_t *bcm_static_skb = 0; -+#endif /* DHD_USE_STATIC_BUF */ -+ -+typedef struct bcm_mem_link { -+ struct bcm_mem_link *prev; -+ struct bcm_mem_link *next; -+ uint size; -+ int line; -+ void *osh; -+ char file[BCM_MEM_FILENAME_LEN]; -+} bcm_mem_link_t; -+ -+struct osl_info { -+ osl_pubinfo_t pub; -+ uint magic; -+ void *pdev; -+ atomic_t malloced; -+ atomic_t pktalloced; /* Number of allocated packet buffers */ -+ uint failed; -+ uint bustype; -+ bcm_mem_link_t *dbgmem_list; -+ spinlock_t dbgmem_lock; -+ spinlock_t pktalloc_lock; -+}; -+ -+#define OSL_PKTTAG_CLEAR(p) \ -+do { \ -+ struct sk_buff *s = (struct sk_buff *)(p); \ -+ ASSERT(OSL_PKTTAG_SZ == 32); \ -+ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ -+ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ -+ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ -+ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ -+} while (0) -+ -+/* PCMCIA attribute space access macros */ -+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) -+struct pcmcia_dev { -+ dev_link_t link; /* PCMCIA device pointer */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -+ dev_node_t node; /* PCMCIA node structure */ -+#endif -+ void *base; /* Mapped attribute memory window */ -+ size_t size; /* Size of window */ -+ void *drv; /* Driver data */ -+}; -+#endif /* defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) */ -+ -+/* Global ASSERT type flag */ -+uint32 g_assert_type = FALSE; -+ -+static int16 linuxbcmerrormap[] = -+{ 0, /* 0 */ -+ -EINVAL, /* BCME_ERROR */ -+ -EINVAL, /* BCME_BADARG */ -+ -EINVAL, /* BCME_BADOPTION */ -+ -EINVAL, /* BCME_NOTUP */ -+ -EINVAL, /* BCME_NOTDOWN */ -+ -EINVAL, /* BCME_NOTAP */ -+ -EINVAL, /* BCME_NOTSTA */ -+ -EINVAL, /* BCME_BADKEYIDX */ -+ -EINVAL, /* BCME_RADIOOFF */ -+ -EINVAL, /* BCME_NOTBANDLOCKED */ -+ -EINVAL, /* BCME_NOCLK */ -+ -EINVAL, /* BCME_BADRATESET */ -+ -EINVAL, /* BCME_BADBAND */ -+ -E2BIG, /* BCME_BUFTOOSHORT */ -+ -E2BIG, /* BCME_BUFTOOLONG */ -+ -EBUSY, /* BCME_BUSY */ -+ -EINVAL, /* BCME_NOTASSOCIATED */ -+ -EINVAL, /* BCME_BADSSIDLEN */ -+ -EINVAL, /* BCME_OUTOFRANGECHAN */ -+ -EINVAL, /* BCME_BADCHAN */ -+ -EFAULT, /* BCME_BADADDR */ -+ -ENOMEM, /* BCME_NORESOURCE */ -+ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ -+ -EMSGSIZE, /* BCME_BADLENGTH */ -+ -EINVAL, /* BCME_NOTREADY */ -+ -EPERM, /* BCME_EPERM */ -+ -ENOMEM, /* BCME_NOMEM */ -+ -EINVAL, /* BCME_ASSOCIATED */ -+ -ERANGE, /* BCME_RANGE */ -+ -EINVAL, /* BCME_NOTFOUND */ -+ -EINVAL, /* BCME_WME_NOT_ENABLED */ -+ -EINVAL, /* BCME_TSPEC_NOTFOUND */ -+ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ -+ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ -+ -EIO, /* BCME_SDIO_ERROR */ -+ -ENODEV, /* BCME_DONGLE_DOWN */ -+ -EINVAL, /* BCME_VERSION */ -+ -EIO, /* BCME_TXFAIL */ -+ -EIO, /* BCME_RXFAIL */ -+ -ENODEV, /* BCME_NODEVICE */ -+ -EINVAL, /* BCME_NMODE_DISABLED */ -+ -ENODATA, /* BCME_NONRESIDENT */ -+ -+/* When an new error code is added to bcmutils.h, add os -+ * specific error translation here as well -+ */ -+/* check if BCME_LAST changed since the last time this function was updated */ -+#if BCME_LAST != -42 -+#error "You need to add a OS error translation in the linuxbcmerrormap \ -+ for new error code defined in bcmutils.h" -+#endif -+}; -+ -+/* translate bcmerrors into linux errors */ -+int -+osl_error(int bcmerror) -+{ -+ if (bcmerror > 0) -+ bcmerror = 0; -+ else if (bcmerror < BCME_LAST) -+ bcmerror = BCME_ERROR; -+ -+ /* Array bounds covered by ASSERT in osl_attach */ -+ return linuxbcmerrormap[-bcmerror]; -+} -+ -+extern uint8* dhd_os_prealloc(void *osh, int section, int size); -+ -+EXPORT_SYMBOL(osl_attach); -+osl_t * -+osl_attach(void *pdev, uint bustype, bool pkttag) -+{ -+ osl_t *osh; -+ -+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); -+ ASSERT(osh); -+ -+ bzero(osh, sizeof(osl_t)); -+ -+ /* Check that error map has the right number of entries in it */ -+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); -+ -+ osh->magic = OS_HANDLE_MAGIC; -+ atomic_set(&osh->malloced, 0); -+ osh->failed = 0; -+ osh->dbgmem_list = NULL; -+ spin_lock_init(&(osh->dbgmem_lock)); -+ osh->pdev = pdev; -+ osh->pub.pkttag = pkttag; -+ osh->bustype = bustype; -+ -+ switch (bustype) { -+ case PCI_BUS: -+ case SI_BUS: -+ case PCMCIA_BUS: -+ osh->pub.mmbus = TRUE; -+ break; -+ case JTAG_BUS: -+ case SDIO_BUS: -+ case USB_BUS: -+ case SPI_BUS: -+ case RPC_BUS: -+ osh->pub.mmbus = FALSE; -+ break; -+ default: -+ ASSERT(FALSE); -+ break; -+ } -+ -+#if defined(DHD_USE_STATIC_BUF) -+ if (!bcm_static_buf) { -+ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ -+ STATIC_BUF_TOTAL_LEN))) { -+ printk("can not alloc static buf!\n"); -+ } -+ else -+ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); -+ -+ -+ sema_init(&bcm_static_buf->static_sem, 1); -+ -+ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; -+ } -+ -+ if (!bcm_static_skb) { -+ int i; -+ void *skb_buff_ptr = 0; -+ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); -+ skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); -+ -+ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); -+ for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) -+ bcm_static_skb->pkt_use[i] = 0; -+ -+ sema_init(&bcm_static_skb->osl_pkt_sem, 1); -+ } -+#endif /* DHD_USE_STATIC_BUF */ -+ -+ spin_lock_init(&(osh->pktalloc_lock)); -+ -+#ifdef BCMDBG -+ if (pkttag) { -+ struct sk_buff *skb; -+ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb)); -+ } -+#endif -+ return osh; -+} -+ -+void -+osl_detach(osl_t *osh) -+{ -+ if (osh == NULL) -+ return; -+ -+#ifdef DHD_USE_STATIC_BUF -+ if (bcm_static_buf) { -+ bcm_static_buf = 0; -+ } -+ if (bcm_static_skb) { -+ bcm_static_skb = 0; -+ } -+#endif -+ -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); -+ kfree(osh); -+} -+ -+static struct sk_buff *osl_alloc_skb(unsigned int len) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -+ gfp_t flags = GFP_ATOMIC; -+ -+ return __dev_alloc_skb(len, flags); -+#else -+ return dev_alloc_skb(len); -+#endif -+} -+ -+/* Convert a driver packet to native(OS) packet -+ * In the process, packettag is zeroed out before sending up -+ * IP code depends on skb->cb to be setup correctly with various options -+ * In our case, that means it should be 0 -+ */ -+struct sk_buff * BCMFASTPATH -+osl_pkt_tonative(osl_t *osh, void *pkt) -+{ -+ struct sk_buff *nskb; -+ -+ if (osh->pub.pkttag) -+ OSL_PKTTAG_CLEAR(pkt); -+ -+ /* Decrement the packet counter */ -+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { -+ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); -+ } -+ return (struct sk_buff *)pkt; -+} -+ -+/* Convert a native(OS) packet to driver packet. -+ * In the process, native packet is destroyed, there is no copying -+ * Also, a packettag is zeroed out -+ */ -+void * BCMFASTPATH -+osl_pkt_frmnative(osl_t *osh, void *pkt) -+{ -+ struct sk_buff *nskb; -+ -+ if (osh->pub.pkttag) -+ OSL_PKTTAG_CLEAR(pkt); -+ -+ /* Increment the packet counter */ -+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { -+ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); -+ } -+ return (void *)pkt; -+} -+ -+/* Return a new packet. zero out pkttag */ -+void * BCMFASTPATH -+osl_pktget(osl_t *osh, uint len) -+{ -+ struct sk_buff *skb; -+ -+ if ((skb = osl_alloc_skb(len))) { -+ skb_put(skb, len); -+ skb->priority = 0; -+ -+ atomic_inc(&osh->pktalloced); -+ } -+ -+ PKTSETCLINK(skb, NULL); -+ -+ return ((void*) skb); -+} -+ -+/* Free the driver packet. Free the tag if present */ -+void BCMFASTPATH -+osl_pktfree(osl_t *osh, void *p, bool send) -+{ -+ struct sk_buff *skb, *nskb; -+ -+ skb = (struct sk_buff*) p; -+ -+ if (send && osh->pub.tx_fn) -+ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); -+ -+ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); -+ -+ /* perversion: we use skb->next to chain multi-skb packets */ -+ while (skb) { -+ nskb = skb->next; -+ skb->next = NULL; -+ -+ -+ { -+ if (skb->destructor) -+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if -+ * destructor exists -+ */ -+ dev_kfree_skb_any(skb); -+ else -+ /* can free immediately (even in_irq()) if destructor -+ * does not exist -+ */ -+ dev_kfree_skb(skb); -+ } -+ atomic_dec(&osh->pktalloced); -+ skb = nskb; -+ } -+} -+ -+#ifdef DHD_USE_STATIC_BUF -+void* -+osl_pktget_static(osl_t *osh, uint len) -+{ -+ int i = 0; -+ struct sk_buff *skb; -+ -+ if (len > (PAGE_SIZE*2)) { -+ printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); -+ return osl_pktget(osh, len); -+ } -+ -+ down(&bcm_static_skb->osl_pkt_sem); -+ -+ if (len <= PAGE_SIZE) { -+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { -+ if (bcm_static_skb->pkt_use[i] == 0) -+ break; -+ } -+ -+ if (i != STATIC_PKT_MAX_NUM) { -+ bcm_static_skb->pkt_use[i] = 1; -+ up(&bcm_static_skb->osl_pkt_sem); -+ skb = bcm_static_skb->skb_4k[i]; -+ skb->tail = skb->data + len; -+ skb->len = len; -+ return skb; -+ } -+ } -+ -+ -+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { -+ if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0) -+ break; -+ } -+ -+ if (i != STATIC_PKT_MAX_NUM) { -+ bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; -+ up(&bcm_static_skb->osl_pkt_sem); -+ skb = bcm_static_skb->skb_8k[i]; -+ skb->tail = skb->data + len; -+ skb->len = len; -+ return skb; -+ } -+ -+ up(&bcm_static_skb->osl_pkt_sem); -+ printk("%s: all static pkt in use!\n", __FUNCTION__); -+ return osl_pktget(osh, len); -+} -+ -+void -+osl_pktfree_static(osl_t *osh, void *p, bool send) -+{ -+ int i; -+ -+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { -+ if (p == bcm_static_skb->skb_4k[i]) { -+ down(&bcm_static_skb->osl_pkt_sem); -+ bcm_static_skb->pkt_use[i] = 0; -+ up(&bcm_static_skb->osl_pkt_sem); -+ return; -+ } -+ } -+ -+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { -+ if (p == bcm_static_skb->skb_8k[i]) { -+ down(&bcm_static_skb->osl_pkt_sem); -+ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; -+ up(&bcm_static_skb->osl_pkt_sem); -+ return; -+ } -+ } -+ -+ return osl_pktfree(osh, p, send); -+} -+#endif /* DHD_USE_STATIC_BUF */ -+ -+uint32 -+osl_pci_read_config(osl_t *osh, uint offset, uint size) -+{ -+ uint val = 0; -+ uint retry = PCI_CFG_RETRY; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ /* only 4byte access supported */ -+ ASSERT(size == 4); -+ -+ do { -+ pci_read_config_dword(osh->pdev, offset, &val); -+ if (val != 0xffffffff) -+ break; -+ } while (retry--); -+ -+#ifdef BCMDBG -+ if (retry < PCI_CFG_RETRY) -+ printk("PCI CONFIG READ access to %d required %d retries\n", offset, -+ (PCI_CFG_RETRY - retry)); -+#endif /* BCMDBG */ -+ -+ return (val); -+} -+ -+void -+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) -+{ -+ uint retry = PCI_CFG_RETRY; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ /* only 4byte access supported */ -+ ASSERT(size == 4); -+ -+ do { -+ pci_write_config_dword(osh->pdev, offset, val); -+ if (offset != PCI_BAR0_WIN) -+ break; -+ if (osl_pci_read_config(osh, offset, size) == val) -+ break; -+ } while (retry--); -+ -+#ifdef BCMDBG -+ if (retry < PCI_CFG_RETRY) -+ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset, -+ (PCI_CFG_RETRY - retry)); -+#endif /* BCMDBG */ -+} -+ -+/* return bus # for the pci device pointed by osh->pdev */ -+uint -+osl_pci_bus(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); -+ -+ return ((struct pci_dev *)osh->pdev)->bus->number; -+} -+ -+/* return slot # for the pci device pointed by osh->pdev */ -+uint -+osl_pci_slot(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); -+ -+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); -+} -+ -+/* return the pci device pointed by osh->pdev */ -+struct pci_dev * -+osl_pci_device(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); -+ -+ return osh->pdev; -+} -+ -+static void -+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) -+{ -+} -+ -+void -+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) -+{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); -+} -+ -+void -+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) -+{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); -+} -+ -+void * -+osl_malloc(osl_t *osh, uint size) -+{ -+ void *addr; -+ -+ /* only ASSERT if osh is defined */ -+ if (osh) -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); -+ -+#ifdef DHD_USE_STATIC_BUF -+ if (bcm_static_buf) -+ { -+ int i = 0; -+ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) -+ { -+ down(&bcm_static_buf->static_sem); -+ -+ for (i = 0; i < STATIC_BUF_MAX_NUM; i++) -+ { -+ if (bcm_static_buf->buf_use[i] == 0) -+ break; -+ } -+ -+ if (i == STATIC_BUF_MAX_NUM) -+ { -+ up(&bcm_static_buf->static_sem); -+ printk("all static buff in use!\n"); -+ goto original; -+ } -+ -+ bcm_static_buf->buf_use[i] = 1; -+ up(&bcm_static_buf->static_sem); -+ -+ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); -+ if (osh) -+ atomic_add(size, &osh->malloced); -+ -+ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); -+ } -+ } -+original: -+#endif /* DHD_USE_STATIC_BUF */ -+ -+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { -+ if (osh) -+ osh->failed++; -+ return (NULL); -+ } -+ if (osh) -+ atomic_add(size, &osh->malloced); -+ -+ return (addr); -+} -+ -+void -+osl_mfree(osl_t *osh, void *addr, uint size) -+{ -+#ifdef DHD_USE_STATIC_BUF -+ if (bcm_static_buf) -+ { -+ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr -+ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) -+ { -+ int buf_idx = 0; -+ -+ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; -+ -+ down(&bcm_static_buf->static_sem); -+ bcm_static_buf->buf_use[buf_idx] = 0; -+ up(&bcm_static_buf->static_sem); -+ -+ if (osh) { -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); -+ atomic_sub(size, &osh->malloced); -+ } -+ return; -+ } -+ } -+#endif /* DHD_USE_STATIC_BUF */ -+ if (osh) { -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); -+ atomic_sub(size, &osh->malloced); -+ } -+ kfree(addr); -+} -+ -+uint -+osl_malloced(osl_t *osh) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (atomic_read(&osh->malloced)); -+} -+ -+uint -+osl_malloc_failed(osl_t *osh) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (osh->failed); -+} -+ -+ -+uint -+osl_dma_consistent_align(void) -+{ -+ return (PAGE_SIZE); -+} -+ -+void* -+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) -+{ -+#ifdef CONFIG_BCM_IPROC_GMAC_ACP -+ void *va; -+ uint16 align = (1 << align_bits); -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) -+ size += align; -+ *alloced = size; -+ -+ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); -+ if (va) -+ *pap = (ulong)__virt_to_phys((ulong)va); -+ return va; -+ -+#else -+ void *ret; -+// int gfp = GFP_KERNEL; //GFP_ATOMIC | GFP_DMA; -+ /* platform device reference */ -+ struct platform_device *pdev; -+ -+ uint16 align = (1 << align_bits); -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) -+ size += align; -+ *alloced = size; -+ -+// ret = (void *)__get_free_pages(gfp, get_order(size)); -+// if (ret != NULL) { -+// memset(ret, 0, size); -+// *pap = virt_to_phys(ret); -+// } -+ pdev = (struct platform_device *)osh->pdev; -+ ret = dma_alloc_coherent(&pdev->dev, size, (dma_addr_t*)pap, GFP_KERNEL); -+ return ret; -+ -+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+} -+ -+void -+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) -+{ -+#ifdef CONFIG_BCM_IPROC_GMAC_ACP -+ kfree(va); -+#else -+ /* platform device reference */ -+ struct platform_device *pdev; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+// free_pages((unsigned long)va, get_order(size)); -+ pdev = (struct platform_device *)osh->pdev; -+ dma_free_coherent(&pdev->dev, size, va, (dma_addr_t)pa); -+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+} -+ -+uint BCMFASTPATH -+osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) -+{ -+ int dir; -+ /* platform device reference */ -+ struct platform_device *pdev; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ pdev = (struct platform_device *)osh->pdev; -+ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; -+ -+#if defined(BCMDMASGLISTOSL) -+ if (dmah != NULL) { -+ int32 nsegs, i, totsegs = 0, totlen = 0; -+ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2]; -+ struct sk_buff *skb; -+ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { -+ sg = &_sg[totsegs]; -+ if (skb_is_nonlinear(skb)) { -+ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); -+ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS)); -+ #ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ dma_map_sg(&pdev->dev, sg, nsegs, dir); -+ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+ } else { -+ nsegs = 1; -+ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS); -+ sg->page_link = 0; -+ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); -+ #ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ dma_map_single(&pdev->dev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir); -+ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+ } -+ totsegs += nsegs; -+ totlen += PKTLEN(osh, skb); -+ } -+ dmah->nsegs = totsegs; -+ dmah->origsize = totlen; -+ for (i = 0, sg = _sg; i < totsegs; i++, sg++) { -+ dmah->segs[i].addr = sg_phys(sg); -+ dmah->segs[i].length = sg->length; -+ } -+ #ifdef CONFIG_BCM_IPROC_GMAC_ACP -+ return virt_to_phys(va); -+ #else -+ return dmah->segs[0].addr; -+ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+ } -+#endif /* defined(BCMDMASGLISTOSL) */ -+ -+#ifdef CONFIG_BCM_IPROC_GMAC_ACP -+ return virt_to_phys(va); -+#else -+ return dma_map_single(&pdev->dev, va, size, dir); -+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ -+} -+ -+void BCMFASTPATH -+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) -+{ -+#ifndef CONFIG_BCM_IPROC_GMAC_ACP -+ int dir; -+ /* platform device reference */ -+ struct platform_device *pdev; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ pdev = (struct platform_device *)osh->pdev; -+ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; -+ dma_unmap_single(&pdev->dev, (uint32)pa, size, dir); -+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ -+} -+ -+ -+void -+osl_delay(uint usec) -+{ -+ uint d; -+ -+ while (usec > 0) { -+ d = MIN(usec, 1000); -+ udelay(d); -+ usec -= d; -+ } -+} -+ -+/* Clone a packet. -+ * The pkttag contents are NOT cloned. -+ */ -+void * -+osl_pktdup(osl_t *osh, void *skb) -+{ -+ void * p; -+ -+ /* clear the CTFBUF flag if set and map the rest of the buffer -+ * before cloning. -+ */ -+ PKTCTFMAP(osh, skb); -+ -+ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) -+ return NULL; -+ -+ /* skb_clone copies skb->cb.. we don't want that */ -+ if (osh->pub.pkttag) -+ OSL_PKTTAG_CLEAR(p); -+ -+ /* Increment the packet counter */ -+ atomic_inc(&osh->pktalloced); -+ return (p); -+} -+ -+ -+/* -+ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access -+ */ -+#ifdef OSLREGOPS -+uint8 -+osl_readb(osl_t *osh, volatile uint8 *r) -+{ -+ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ return (uint8)((rreg)(ctx, (void*)r, sizeof(uint8))); -+} -+ -+ -+uint16 -+osl_readw(osl_t *osh, volatile uint16 *r) -+{ -+ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ return (uint16)((rreg)(ctx, (void*)r, sizeof(uint16))); -+} -+ -+uint32 -+osl_readl(osl_t *osh, volatile uint32 *r) -+{ -+ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ return (uint32)((rreg)(ctx, (void*)r, sizeof(uint32))); -+} -+ -+void -+osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v) -+{ -+ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ ((wreg)(ctx, (void*)r, v, sizeof(uint8))); -+} -+ -+ -+void -+osl_writew(osl_t *osh, volatile uint16 *r, uint16 v) -+{ -+ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ ((wreg)(ctx, (void*)r, v, sizeof(uint16))); -+} -+ -+void -+osl_writel(osl_t *osh, volatile uint32 *r, uint32 v) -+{ -+ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; -+ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; -+ -+ ((wreg)(ctx, (void*)r, v, sizeof(uint32))); -+} -+#endif /* OSLREGOPS */ -+ -+/* -+ * BINOSL selects the slightly slower function-call-based binary compatible osl. -+ */ -+#ifdef BINOSL -+ -+uint32 -+osl_sysuptime(void) -+{ -+ return ((uint32)jiffies * (1000 / HZ)); -+} -+ -+int -+osl_printf(const char *format, ...) -+{ -+ va_list args; -+ static char printbuf[1024]; -+ int len; -+ -+ /* sprintf into a local buffer because there *is* no "vprintk()".. */ -+ va_start(args, format); -+ len = vsnprintf(printbuf, 1024, format, args); -+ va_end(args); -+ -+ if (len > sizeof(printbuf)) { -+ printk("osl_printf: buffer overrun\n"); -+ return (0); -+ } -+ -+ return (printk("%s", printbuf)); -+} -+ -+int -+osl_sprintf(char *buf, const char *format, ...) -+{ -+ va_list args; -+ int rc; -+ -+ va_start(args, format); -+ rc = vsprintf(buf, format, args); -+ va_end(args); -+ return (rc); -+} -+ -+int -+osl_snprintf(char *buf, size_t n, const char *format, ...) -+{ -+ va_list args; -+ int rc; -+ -+ va_start(args, format); -+ rc = vsnprintf(buf, n, format, args); -+ va_end(args); -+ return (rc); -+} -+ -+int -+osl_vsprintf(char *buf, const char *format, va_list ap) -+{ -+ return (vsprintf(buf, format, ap)); -+} -+ -+int -+osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap) -+{ -+ return (vsnprintf(buf, n, format, ap)); -+} -+ -+int -+osl_strcmp(const char *s1, const char *s2) -+{ -+ return (strcmp(s1, s2)); -+} -+ -+int -+osl_strncmp(const char *s1, const char *s2, uint n) -+{ -+ return (strncmp(s1, s2, n)); -+} -+ -+int -+osl_strlen(const char *s) -+{ -+ return (strlen(s)); -+} -+ -+char* -+osl_strcpy(char *d, const char *s) -+{ -+ return (strcpy(d, s)); -+} -+ -+char* -+osl_strncpy(char *d, const char *s, uint n) -+{ -+ return (strncpy(d, s, n)); -+} -+ -+char* -+osl_strchr(const char *s, int c) -+{ -+ return (strchr(s, c)); -+} -+ -+char* -+osl_strrchr(const char *s, int c) -+{ -+ return (strrchr(s, c)); -+} -+ -+void* -+osl_memset(void *d, int c, size_t n) -+{ -+ return memset(d, c, n); -+} -+ -+void* -+osl_memcpy(void *d, const void *s, size_t n) -+{ -+ return memcpy(d, s, n); -+} -+ -+void* -+osl_memmove(void *d, const void *s, size_t n) -+{ -+ return memmove(d, s, n); -+} -+ -+int -+osl_memcmp(const void *s1, const void *s2, size_t n) -+{ -+ return memcmp(s1, s2, n); -+} -+ -+uint32 -+osl_readl(volatile uint32 *r) -+{ -+ return (readl(r)); -+} -+ -+uint16 -+osl_readw(volatile uint16 *r) -+{ -+ return (readw(r)); -+} -+ -+uint8 -+osl_readb(volatile uint8 *r) -+{ -+ return (readb(r)); -+} -+ -+void -+osl_writel(uint32 v, volatile uint32 *r) -+{ -+ writel(v, r); -+} -+ -+void -+osl_writew(uint16 v, volatile uint16 *r) -+{ -+ writew(v, r); -+} -+ -+void -+osl_writeb(uint8 v, volatile uint8 *r) -+{ -+ writeb(v, r); -+} -+ -+void * -+osl_uncached(void *va) -+{ -+#ifdef mips -+ return ((void*)KSEG1ADDR(va)); -+#else -+ return ((void*)va); -+#endif /* mips */ -+} -+ -+void * -+osl_cached(void *va) -+{ -+#ifdef mips -+ return ((void*)KSEG0ADDR(va)); -+#else -+ return ((void*)va); -+#endif /* mips */ -+} -+ -+uint -+osl_getcycles(void) -+{ -+ uint cycles; -+ -+#if defined(mips) -+ cycles = read_c0_count() * 2; -+#elif defined(__i386__) -+ rdtscl(cycles); -+#else -+ cycles = 0; -+#endif /* defined(mips) */ -+ return cycles; -+} -+ -+void * -+osl_reg_map(uint32 pa, uint size) -+{ -+ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); -+} -+ -+void -+osl_reg_unmap(void *va) -+{ -+ iounmap(va); -+} -+ -+int -+osl_busprobe(uint32 *val, uint32 addr) -+{ -+#ifdef mips -+ return get_dbe(*val, (uint32 *)addr); -+#else -+ *val = readl((uint32 *)(uintptr)addr); -+ return 0; -+#endif /* mips */ -+} -+ -+bool -+osl_pktshared(void *skb) -+{ -+ return (((struct sk_buff*)skb)->cloned); -+} -+ -+uchar* -+osl_pktdata(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->data); -+} -+ -+uint -+osl_pktlen(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->len); -+} -+ -+uint -+osl_pktheadroom(osl_t *osh, void *skb) -+{ -+ return (uint) skb_headroom((struct sk_buff *) skb); -+} -+ -+uint -+osl_pkttailroom(osl_t *osh, void *skb) -+{ -+ return (uint) skb_tailroom((struct sk_buff *) skb); -+} -+ -+void* -+osl_pktnext(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->next); -+} -+ -+void -+osl_pktsetnext(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; -+} -+ -+void -+osl_pktsetlen(osl_t *osh, void *skb, uint len) -+{ -+ __pskb_trim((struct sk_buff*)skb, len); -+} -+ -+uchar* -+osl_pktpush(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_push((struct sk_buff*)skb, bytes)); -+} -+ -+uchar* -+osl_pktpull(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_pull((struct sk_buff*)skb, bytes)); -+} -+ -+void* -+osl_pkttag(void *skb) -+{ -+ return ((void*)(((struct sk_buff*)skb)->cb)); -+} -+ -+void* -+osl_pktlink(void *skb) -+{ -+ return (((struct sk_buff*)skb)->prev); -+} -+ -+void -+osl_pktsetlink(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; -+} -+ -+uint -+osl_pktprio(void *skb) -+{ -+ return (((struct sk_buff*)skb)->priority); -+} -+ -+void -+osl_pktsetprio(void *skb, uint x) -+{ -+ ((struct sk_buff*)skb)->priority = x; -+} -+#endif /* BINOSL */ -+ -+uint -+osl_pktalloced(osl_t *osh) -+{ -+ return (atomic_read(&osh->pktalloced)); -+} -+ -+/* Linux Kernel: File Operations: start */ -+void * -+osl_os_open_image(char *filename) -+{ -+ struct file *fp; -+ -+ fp = filp_open(filename, O_RDONLY, 0); -+ /* -+ * 2.6.11 (FC4) supports filp_open() but later revs don't? -+ * Alternative: -+ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); -+ * ??? -+ */ -+ if (IS_ERR(fp)) -+ fp = NULL; -+ -+ return fp; -+} -+ -+int -+osl_os_get_image_block(char *buf, int len, void *image) -+{ -+ struct file *fp = (struct file *)image; -+ int rdlen; -+ -+ if (!image) -+ return 0; -+ -+ rdlen = kernel_read(fp, fp->f_pos, buf, len); -+ if (rdlen > 0) -+ fp->f_pos += rdlen; -+ -+ return rdlen; -+} -+ -+void -+osl_os_close_image(void *image) -+{ -+ if (image) -+ filp_close((struct file *)image, NULL); -+} -+/* Linux Kernel: File Operations: end */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/nvramstubs.c b/drivers/net/ethernet/broadcom/gmac/src/shared/nvramstubs.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/nvramstubs.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/nvramstubs.c 2017-11-09 17:53:44.059297000 +0800 -@@ -0,0 +1,341 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * Stubs for NVRAM functions for platforms without flash -+ * -+ * $Id: nvramstubs.c 325991 2012-04-05 10:16:42Z kenlo $ -+ */ -+ -+#include -+#include -+#include -+#undef strcmp -+#define strcmp(s1,s2) 0 /* always match */ -+#include -+ -+int -+nvram_init(void *sih) -+{ -+ return 0; -+} -+ -+int -+nvram_append(void *sb, char *vars, uint varsz) -+{ -+ return 0; -+} -+ -+void -+nvram_exit(void *sih) -+{ -+} -+ -+/* fake nvram tuples */ -+typedef struct { -+ char *name; -+ char *value; -+} nvram_t; -+ -+static nvram_t fake_nvram[] = { -+ {"boardtype", "0x058d"}, -+ {"boardnum", "0x010"}, -+ {"boardrev", "0x1100"}, -+ {"boardflags", "0x710"}, -+ {"boardflags2", "0"}, -+ {"sromrev", "8"}, -+ {"clkfreq", "133,133,133"}, -+ {"xtalfreq", "125000"}, -+ {"et_txq_thresh", "1024"}, -+ {"et_rx_rate_limit","1"}, -+ {"sdram_config", "0x103"}, -+ {"swgmacet", "et2"}, -+ {"brcmtag", "1"}, -+ //{"ethaddr", "00:90:4c:06:a5:72"}, -+#ifdef FOUR_PORT_CONFIG -+ {"vlan1hwname", "et2"}, -+ {"vlan1ports", "0 1 2 8*"}, -+ {"vlan2hwname", "et2"}, -+ {"vlan2ports", "3 8*"}, -+ {"wanport", "3"}, -+#else -+ {"vlan1hwname", "et2"}, -+ {"vlan1ports", "0 1 2 3 8*"}, -+ {"vlan2hwname", "et2"}, -+ {"vlan2ports", "4 8*"}, -+ {"wanport", "4"}, -+#endif -+ {"landevs", "vlan1"}, -+ {"wandevs", "et0"}, -+ {"lan_ipaddr", "192.168.1.1"}, -+ {"lan_netmask", "255.255.255.0"}, -+ {"boot_wait", "on"}, -+ {"wait_time", "3"}, -+ {"watchdog", "0"}, -+ {"et_msglevel", "0xFFFFFFFF"} -+}; -+#define fake_nvram_size sizeof(fake_nvram)/sizeof(fake_nvram[0]) -+ -+#ifndef FAKE_NVRAM -+ -+#if defined(CONFIG_MACH_IPROC_P7) -+#define CONFIG_SPI_BASE 0xf0000000 -+#else -+#define CONFIG_SPI_BASE 0x1e000000 -+#endif /* CONFIG_MACH_IPROC_P7 */ -+#define CONFIG_ENV_OFFSET 0xc0000 /* 30000-b0000 - use last 10000 for env */ -+#define CONFIG_ENV_SIZE 0x10000 /* 64K */ -+#define CONFIG_ENV_MAX_ENTRIES 512 -+ -+#define UBOOT_ENV_ADDR CONFIG_SPI_BASE+CONFIG_ENV_OFFSET -+#define UBOOT_ENV_SIZE CONFIG_ENV_SIZE -+#define UBOOT_ENV_MAX_NUM CONFIG_ENV_MAX_ENTRIES -+ -+static uint8 u_boot_env[UBOOT_ENV_SIZE]; -+static bool u_boot_env_loaded=false; -+static nvram_t env_list[UBOOT_ENV_MAX_NUM]; -+static int uboot_vars_start = UBOOT_ENV_ADDR; -+static int uboot_nvram_max = UBOOT_ENV_SIZE; -+ -+/* pass envaddr= in bootargs */ -+static int __init envaddr_setup(char *str) -+{ -+ int ret =0; -+ unsigned long ul=0; -+ -+ ret = kstrtoul(str, 16, &ul); -+ -+ if (!ret) { -+ uboot_vars_start = ul; -+ printk("NVRAM: assign 0x%08x\n", uboot_vars_start); -+ } -+ -+ return !ret; -+} -+__setup("envaddr=", envaddr_setup); -+ -+/* -+APIs for access into uboot env vars -+*/ -+ -+int -+nvram_env_init(void) -+{ -+ volatile void *envbuf; -+ char *dp, *sp, *name, *value, *dp_end; -+ char sep = '\0'; -+ int idx=0; -+ -+ -+ printk("NVRAM: map 0x%08x\n", uboot_vars_start); -+ -+ /* map uboot env */ -+ if ((envbuf = (uint8*)ioremap(uboot_vars_start, UBOOT_ENV_SIZE)) == NULL) { -+ printk("%s: ioremap() failed\n", __FUNCTION__); -+ return -ENOMEM; -+ } -+ -+ /* copy memory into buffer */ -+ memcpy((void*)u_boot_env, (void *) envbuf, uboot_nvram_max); -+ -+ /* clear fake entry set */ -+ memset(env_list, 0, sizeof(env_list)); -+ -+ /* load uboot fake nvram buffer */ -+ /* point to first data */ -+ dp = (char*)u_boot_env; -+ /* point to data buffer */ -+ dp += 4; -+ dp_end = (char*)((uint32)u_boot_env+UBOOT_ENV_SIZE); -+ -+ /* point to first data */ -+ do { -+ /* skip leading white space */ -+ while ((*dp == ' ') || (*dp == '\t')) { -+ ++dp; -+ } -+ -+ /* skip comment lines */ -+ if (*dp == '#') { -+ while (*dp && (*dp != sep)) { -+ ++dp; -+ } -+ ++dp; -+ continue; -+ } -+ -+ /* parse name */ -+ for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp) { -+ ; -+ } -+ -+ *dp++ = '\0'; /* terminate name */ -+ -+ /* parse value; deal with escapes */ -+ for (value = sp = dp; *dp && (*dp != sep); ++dp) { -+ if ((*dp == '\\') && *(dp + 1)) { -+ ++dp; -+ } -+ *sp++ = *dp; -+ } -+ *sp++ = '\0'; /* terminate value */ -+ ++dp; -+ -+ /* enter into hash table */ -+ env_list[idx].name = name; -+ env_list[idx].value = value; -+ //printk("entry%d %s=%s\n", idx, name, value); -+ idx++; -+ -+ /* check if table is full */ -+ if (idx >= UBOOT_ENV_MAX_NUM ) { -+ printk("%s: WARNING - UBoot environment table is full\n", __FUNCTION__); -+ break; -+ } -+ /* check if end of table */ -+ } while ((dp < dp_end) && *dp); /* size check needed for text */ -+ -+ u_boot_env_loaded = true; -+ -+ /* unmap uboot env */ -+ iounmap(envbuf); -+ -+ return 0; -+} -+#endif -+ -+int -+nvram_env_gmac_name(int gmac, char *name) -+{ -+ int ret=0; -+ switch (gmac) -+ { -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_GH2)) -+ case 0: -+ strcpy(name, "ethaddr"); -+ break; -+ case 1: -+ sprintf(name, "eth1addr"); -+ break; -+#elif (defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3)) -+ case 0: -+ strcpy(name, "ethaddr"); -+ break; -+#endif -+ default: -+ strcpy(name, "unknown"); -+ ret = -1; -+ break; -+ } -+ return ret; -+ -+} -+ -+char * -+nvram_get(const char *name) -+{ -+ int i, len; -+ nvram_t *tuple; -+ int num_entries; -+ -+ if (!name) { -+ return (char *) 0; -+ } -+ -+ len = strlen(name); -+ if (len == 0) { -+ return (char *) 0; -+ } -+ -+#if defined(CONFIG_MACH_SB2) && defined(CONFIG_MACH_IPROC_EMULATION) -+ static char macAddr[17]; /* = "d4:ae:52:bc:a5:09" */ -+ -+ if (name[0] == 'e' && name[1] == 't' && name[2] == 'h' && name[3] == 'a' && -+ name[4] == 'd' && name[5] == 'd' && name[6] == 'r') -+ { -+ macAddr[0] = 'd'; macAddr[1] = '4'; macAddr[2] = ':'; -+ macAddr[3] = 'a'; macAddr[4] = 'e'; macAddr[5] = ':'; -+ macAddr[6] = '5'; macAddr[7] = '2'; macAddr[8] = ':'; -+ macAddr[9] = 'b'; macAddr[10] = 'c'; macAddr[11] = ':'; -+ macAddr[12] = 'a'; macAddr[13] = '5'; macAddr[14] = ':'; -+ macAddr[15] = '0'; macAddr[16] = '9'; -+ return((char *)macAddr); -+ } /* else if (name[0] == 'e' && name[1] == 't' && name[2] == 'h' && name[3] == '1' && -+ name[4] == 'a' && name[5] == 'd' && name[6] == 'd' && name[7] == 'r') -+ { -+ macAddr[0] = 'd'; macAddr[1] = '5'; macAddr[2] = ':'; -+ macAddr[3] = 'a'; macAddr[4] = 'e'; macAddr[5] = ':'; -+ macAddr[6] = '5'; macAddr[7] = '3'; macAddr[8] = ':'; -+ macAddr[9] = 'b'; macAddr[10] = 'c'; macAddr[11] = ':'; -+ macAddr[12] = 'a'; macAddr[13] = '6'; macAddr[14] = ':'; -+ macAddr[15] = '0'; macAddr[16] = 'a'; -+ return((char *)macAddr); -+ } */ -+#endif -+ -+#ifndef FAKE_NVRAM -+ tuple = &env_list[0]; -+ num_entries = sizeof(env_list)/sizeof(nvram_t); -+ -+ if (!u_boot_env_loaded) { -+ nvram_env_init(); -+ } -+ -+ /* first check the uboot NVRAM variables */ -+ for (i = 0; i < num_entries; i++) { -+ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { -+ /*printf("%s (NVRAM) %s: %s\n", __FUNCTION__, name, tuple->value);*/ -+ return tuple->value; -+ } -+ tuple++; -+ } -+#endif -+ -+ /* if cant find then check fake table above */ -+ tuple = &fake_nvram[0]; -+ num_entries = fake_nvram_size; -+ for (i = 0; i < num_entries; i++) { -+ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { -+ /*printf("%s (STUBS) %s: %s\n", __FUNCTION__, name, tuple->value);*/ -+ return tuple->value; -+ } -+ tuple++; -+ } -+ -+ return (char *) 0; -+} -+ -+int -+nvram_set(const char *name, const char *value) -+{ -+ return 0; -+} -+ -+int -+nvram_unset(const char *name) -+{ -+ return 0; -+} -+ -+int -+nvram_commit(void) -+{ -+ return 0; -+} -+ -+int -+nvram_getall(char *buf, int count) -+{ -+ /* add null string as terminator */ -+ if (count < 1) { -+ return BCME_BUFTOOSHORT; -+ } -+ *buf = '\0'; -+ return 0; -+} -+ -+static int __init iproc_nvram_init(void) -+{ -+ nvram_env_init(); -+ return 0; -+} -+subsys_initcall(iproc_nvram_init); -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/phy542xx.c b/drivers/net/ethernet/broadcom/gmac/src/shared/phy542xx.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/phy542xx.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/phy542xx.c 2017-11-09 17:53:44.061289000 +0800 -@@ -0,0 +1,336 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the external phy -+ * -+ */ -+#include -+#include -+#include "../../../mdio/iproc_mdio.h" -+#include "bcmiproc_phy.h" -+#include "phy542xx.h" -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+#define PHY542XX_RDB_REG_RD phy542xx_rdb_reg_read -+#define PHY542XX_RDB_REG_WR phy542xx_rdb_reg_write -+#define PHY542XX_REG_RD phy542xx_reg_read -+#define PHY542XX_REG_WR phy542xx_reg_write -+ -+static int -+phy542xx_rdb_reg_read(u32 phy_addr, u32 reg_addr, u16 *data) -+{ -+ int rv = SOC_E_NONE; -+ -+ /* MDIO write the RDB reg. address to reg.0x1E = */ -+ iproc_mii_write(MII_DEV_EXT, phy_addr, BCM542XX_REG_RDB_ADDR, -+ (0xffff & reg_addr)); -+ -+ /* MDIO read from reg.0x1F to get the RDB register's value as */ -+ iproc_mii_read(MII_DEV_EXT, phy_addr, BCM542XX_REG_RDB_DATA, data); -+ -+ return rv; -+} -+ -+static int -+phy542xx_rdb_reg_write(u32 phy_addr, u32 reg_addr, u16 data) -+{ -+ int rv = SOC_E_NONE; -+ -+ /* MDIO write the RDB reg. address to reg.0x1E = */ -+ iproc_mii_write(MII_DEV_EXT, phy_addr, BCM542XX_REG_RDB_ADDR, -+ (0xffff & reg_addr)); -+ -+ /* MDIO write to reg.0x1F to set the RDB resister's value as */ -+ iproc_mii_write(MII_DEV_EXT, phy_addr, BCM542XX_REG_RDB_DATA, data); -+ -+ return rv; -+} -+ -+int -+phy542xx_reg_read(u32 phy_addr, u32 flags, int reg_addr, u16 *data) -+{ -+ int rv = SOC_E_NONE; -+ u16 val; -+ -+ if (flags & PHY_REG_FLAGS_FIBER) { /* fiber registers */ -+ if (reg_addr <= 0x0f) { -+ if (flags & PHY_REG_FLAGS_1000X) { -+ /* 54220 fiber is controlled by Secondary SerDes */ -+ PHY542XX_RDB_REG_RD(phy_addr, -+ (reg_addr | BCM542XX_REG_RDB_2ND_SERDES_BASE), data); -+ } else { -+ /* Map 1000X page */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, &val); -+ val |= BCM542XX_REG_MODE_CTRL_1000X_EN; -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, val); -+ -+ /* Read 1000X IEEE register */ -+ iproc_mii_read(MII_DEV_EXT, phy_addr, reg_addr, data); -+ -+ /* Restore IEEE mapping */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, &val); -+ val &= ~BCM542XX_REG_MODE_CTRL_1000X_EN; -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, val); -+ } -+ } -+ } else if (flags & PHY_REG_FLAGS_RDB) { -+ PHY542XX_RDB_REG_RD(phy_addr, reg_addr, data); -+ } else { -+ iproc_mii_read(MII_DEV_EXT, phy_addr, reg_addr, data); -+ } -+ -+ return rv; -+} -+ -+ -+int -+phy542xx_reg_write(u32 phy_addr, u32 flags, int reg_addr, u16 data) -+{ -+ int rv = SOC_E_NONE; -+ u16 val; -+ -+ if (flags & PHY_REG_FLAGS_FIBER) { /* fiber registers */ -+ if (reg_addr <= 0x0f) { -+ if (flags & PHY_REG_FLAGS_1000X) { -+ /* 54220 fiber is controlled by Secondary SerDes */ -+ PHY542XX_RDB_REG_WR(phy_addr, -+ (reg_addr | BCM542XX_REG_RDB_2ND_SERDES_BASE), data); -+ } else { -+ /* Map 1000X page */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, &val); -+ val |= BCM542XX_REG_MODE_CTRL_1000X_EN; -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, val); -+ -+ /* Write 1000X IEEE register */ -+ iproc_mii_write(MII_DEV_EXT, phy_addr, reg_addr, data); -+ -+ /* Restore IEEE mapping */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, &val); -+ val &= ~BCM542XX_REG_MODE_CTRL_1000X_EN; -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, val); -+ } -+ } -+ } else if (flags & PHY_REG_FLAGS_RDB) { -+ PHY542XX_RDB_REG_WR(phy_addr, reg_addr, data); -+ } else { -+ iproc_mii_write(MII_DEV_EXT, phy_addr, reg_addr, data); -+ } -+ -+ return rv; -+} -+ -+static int -+phy542xx_ge_reset(u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ u16 val; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ /* Reset the PHY */ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, &val); -+ val |= MII_CTRL_RESET; -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, val); -+ -+ SPINWAIT((!PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, &val) && -+ (val & MII_CTRL_RESET)), 100000); -+ -+ /* Check if out of reset */ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, &val); -+ if (val & MII_CTRL_RESET) { -+ NET_ERROR(("%s reset not complete\n", __FUNCTION__)); -+ rv = SOC_E_TIMEOUT; -+ } else { -+ NET_TRACE(("%s reset complete\n", __FUNCTION__)); -+ } -+ -+ return rv; -+} -+ -+static int -+phy542xx_ge_init(u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ u16 val; -+ -+ /* -+ * Enable direct RDB addressing mode, write to Expansion register -+ * 0x7E = 0x0000 -+ * - MDIO write to reg 0x17 = 0x0F7E -+ * - MDIO write to reg 0x15 = 0x0000 -+ */ -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, -+ BCM542XX_REG_EXP_SEL, BCM542XX_REG_EXP_SELECT_7E); -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, -+ BCM542XX_REG_EXP_DATA, BCM542XX_REG_EXP_RDB_EN); -+ -+ /* Configure auto-detect Medium */ -+ PHY542XX_RDB_REG_RD(phy_addr, MIIM_BCM542xx_RDB_AUTO_DETECT_MEDIUM, &val); -+ val &= ~BCM542XX_REG_MII_AUTO_DET_MASK; -+ /* Enable dual serdes auto-detect medium */ -+ val |= (BCM542XX_REG_MII_AUTO_DET_MED_2ND_SERDES | -+ BCM542XX_REG_MII_FIBER_IN_USE_LED | -+ BCM542XX_REG_MII_FIBER_LED | -+ BCM542XX_REG_MII_FIBER_SD_SYNC); -+ /* Enable auto-detect medium */ -+ val |= BCM542XX_REG_MII_AUTO_DET_MED_EN; -+ /* Fiber selected when both media are active */ -+ val |= (BCM542XX_REG_MII_AUTO_DET_MED_PRI | -+ BCM542XX_REG_MII_AUTO_DET_MED_DEFAULT); -+ PHY542XX_RDB_REG_WR(phy_addr, MIIM_BCM542xx_RDB_AUTO_DETECT_MEDIUM, val); -+ -+ /* Power up primary SerDes, Fiber MII_CONTROL Reg. bit[11]*/ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_PRI_SERDES, PHY_MII_CTRLr_ADDR, &val); -+ val &= ~MII_CTRL_PD; -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_PRI_SERDES, PHY_MII_CTRLr_ADDR, val); -+ -+ /* MODE_CONTROL register, DIGX_SHD_1C_1F, RDB_0x21 */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, &val); -+ val &= ~(BCM542XX_REG_MODE_CNTL_MODE_SEL_1 | -+ BCM542XX_REG_MODE_CNTL_MODE_SEL_2); -+ val |= BCM542XX_REG_MODE_SEL_SGMII_2_COPPER; -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MODE_CTRL, val); -+ -+ /* COPPER INTERFACE */ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, &val); -+ val &= ~MII_CTRL_PD; -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, val); -+ -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, MII_CTRL1000, ADVERTISE_1000FULL); -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_CTRLr_ADDR, -+ (BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART)); -+ -+ /* Enable/disable auto-detection between SGMII-slave and 1000BASE-X */ -+ /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_EXT_SERDES_CTRL, &val); -+ val &= ~(BCM542XX_REG_EXT_SERDES_FX_MASK); -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_EXT_SERDES_CTRL, val); -+ -+ /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_SGMII_SLAVE, &val); -+ val &= ~(BCM542XX_REG_SGMII_SLAVE_AUTO); -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_SGMII_SLAVE, val); -+ -+ /* FIBER INTERFACE */ -+ /* Remove power down of SerDes */ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_1000X, PHY_MII_CTRLr_ADDR, &val); -+ val &= ~MII_CTRL_PD; -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_1000X, PHY_MII_CTRLr_ADDR, val); -+ -+ /* Set the advertisement of serdes */ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_1000X, PHY_MII_ANAr_ADDR, &val); -+ val |= (MII_ANA_FD_1000X | MII_ANA_HD_1000X | -+ MII_ANA_1000X_PAUSE | MII_ANA_1000X_ASYM_PAUSE); -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_1000X, PHY_MII_ANAr_ADDR, val); -+ -+ /* Enable auto-detection between SGMII-slave and 1000BASE-X */ -+ /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ -+ val = (BCM542XX_REG_EXT_SERDES_LED | BCM542XX_REG_EXT_SEL_SYNC_ST | -+ BCM542XX_REG_EXT_SELECT_SD | BCM542XX_REG_EXT_SERDES_SEL); -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_EXT_SERDES_CTRL, val); -+ -+ /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_SGMII_SLAVE, &val); -+ val &= ~(BCM542XX_REG_SGMII_SLAVE_AUTO); -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_SGMII_SLAVE, val); -+ -+ /* Miscellanous Control Reg., CORE_SHD18_111, RDB_0x02f */ -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_MII_MISC_CTRL, 0x2007); -+ -+ /* Second SERDES 100-FX CONTROL Register, RDB_0xb17 */ -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_2ND_SERDES_MISC_1000X, 0x0); -+ -+ /* Default SerDes config & restart autonegotiation */ -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_1000X, PHY_MII_CTRLr_ADDR, -+ (BMCR_FULLDPLX | BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART)); -+ -+ return rv; -+} -+ -+int -+phy542xx_reset_setup(u32 phy_addr) -+{ -+ int rv = SOC_E_NONE; -+ -+ NET_TRACE(("%s enter\n", __FUNCTION__)); -+ -+ rv = phy542xx_ge_reset(phy_addr); -+ -+ if (SOC_SUCCESS(rv)) { -+ rv = phy542xx_ge_init(phy_addr); -+ } -+ -+ return rv; -+} -+ -+int -+phy542xx_init(u32 phy_addr) -+{ -+ u16 phyid0, phyid1; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_PHY_ID0r_ADDR, &phyid0); -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_NONE, PHY_MII_PHY_ID1r_ADDR, &phyid1); -+ -+ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); -+ -+ phy542xx_reset_setup(phy_addr); -+ -+ return 0; -+} -+ -+int -+phy542xx_enable_set(u32 phy_addr, int enable) -+{ -+ u16 val; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ PHY542XX_REG_RD(phy_addr, PHY_REG_FLAGS_PRI_SERDES, PHY_MII_CTRLr_ADDR, &val); -+ if (enable) { -+ val &= ~MII_CTRL_PD; -+ } else { -+ val |= MII_CTRL_PD; -+ } -+ PHY542XX_REG_WR(phy_addr, PHY_REG_FLAGS_PRI_SERDES, PHY_MII_CTRLr_ADDR, val); -+ -+ return SOC_E_NONE; -+} -+ -+int -+phy542xx_force_auto_mdix(u32 phy_addr, int enable) -+{ -+ u16 val; -+ -+ NET_TRACE(("%s: phy_addr %d\n", __FUNCTION__, phy_addr)); -+ -+ PHY542XX_RDB_REG_RD(phy_addr, BCM542XX_REG_RDB_COPPER_MISC_CTRL, &val); -+ if (enable) { -+ val |= BCM542XX_REG_MISC_CTRL_FORCE_AUTO_MDIX; -+ } else { -+ val &= ~BCM542XX_REG_MISC_CTRL_FORCE_AUTO_MDIX; -+ } -+ PHY542XX_RDB_REG_WR(phy_addr, BCM542XX_REG_RDB_COPPER_MISC_CTRL, val); -+ -+ return SOC_E_NONE; -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.c b/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.c 2017-11-09 17:53:44.061307000 +0800 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Saber2 sudo EROM -+ * -+ */ -+#include -+ -+uint32 sb2_erom[] = { -+ // LOOP 1 : #define MFGID_BRCM 0x4bf /* Manufacturer Ids (mfg) */ -+ // #define CC_CORE_ID 0x800 /* chipcommon core (cid) */ -+ 0x4bf80001, -+ // crev = 0x2a, nsw = 0x0 (mask = 0x0x00f80000), nmw = 0x1 (mask = 0x0007c000), nsp = 0x1 (mask = 0x00003e00), nmp = 0x0 (mask = 0x000001f0) -+ 0x2a004201, -+ // First Slave Address Descriptor should be port 0: the main register space for the core -+ // addr1 = 0x18000000 (mask = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x18000005, -+ // Now get master wrappers (i = 0) -+ // addr1 = 0x18120000 (AD_ADDR_MASK = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x181200c5, -+ -+ // LOOP 2 : #define MFGID_BRCM 0x4bf /* Manufacturer Ids (mfg) */ -+ // #define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ // cia = 0x4bf82d01 -+ // cid = 0x82d (cia & CIA_CID_MASK(0x000fff00)) >> CIA_CID_SHIFT(8), mfg = 0x4bf (cia & CIA_MFG_MASK(0xfff00000)) >> CIA_MFG_SHIFT(20) -+ 0x4bf82d01, -+ // cib = 0x04004211 -+ // crev = 0x04 (cib & CIB_REV_MASK(0xff000000)) >> CIB_REV_SHIFT(24), nmw = 0x01 (cib & CIB_NMW_MASK(0x0007c000)) >> CIB_NMW_SHIFT(14) -+ // nsw = 0x0 (cib & CIB_NSW_MASK(0x00f80000)) >> CIB_NSW_SHIFT(19), nmp = 0x01 (cib & CIB_NMP_MASK(0x000001f0)) >> CIB_NMP_SHIFT(4) -+ // nsp = 0x01 (cib & CIB_NSP_MASK(0x00003e00)) >> CIB_NSP_SHIFT(9) -+ 0x04004211, -+ // mpd = 0x00000103 -+ 0x00000103, -+ // First Slave Address Descriptor should be port 0: the main register space for the core -+ // addr1 = 0x18042000 (AD_ADDR_MASK = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x18042005, -+ // Now get master wrappers (i = 0) -+ // addr1 = 0x18110000 (AD_ADDR_MASK = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x181100c5, -+ -+ // LOOP 3 : #define MFGID_BRCM 0x4bf /* Manufacturer Ids (mfg) */ -+ // #define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+ // cia = 0x4bf82d01 -+ // cid = 0x82d (cia & CIA_CID_MASK(0x000fff00)) >> CIA_CID_SHIFT(8), mfg = 0x4bf (cia & CIA_MFG_MASK(0xfff00000)) >> CIA_MFG_SHIFT(20) -+ 0x4bf82d01, -+ // cib = 0x04004211 -+ // crev = 0x04 (cib & CIB_REV_MASK(0xff000000)) >> CIB_REV_SHIFT(24), nmw = 0x01 (cib & CIB_NMW_MASK(0x0007c000)) >> CIB_NMW_SHIFT(14) -+ // nsw = 0x0 (cib & CIB_NSW_MASK(0x00f80000)) >> CIB_NSW_SHIFT(19), nmp = 0x01 (cib & CIB_NMP_MASK(0x000001f0)) >> CIB_NMP_SHIFT(4) -+ // nsp = 0x01 (cib & CIB_NSP_MASK(0x00003e00)) >> CIB_NSP_SHIFT(9) -+ 0x04004211, -+ // mpd = 0x00000203 -+ 0x00000203, -+ // First Slave Address Descriptor should be port 0: the main register space for the core -+ // addr1 = 0x1804a000 (AD_ADDR_MASK = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x1804a005, -+ // Now get master wrappers (i = 0) -+ // addr1 = 0x18110000 (AD_ADDR_MASK = 0xfffff000), addrh = 0x0 (AD_AG32 = 0x00000008), sizeh = 0x0, -+ // sz = 0x0 (AD_SZ_MASK = 0x00000030), sizel = 0x00001000 (0x00001000 << (sz >> 4)) -+ 0x181110c5, -+ -+ // END of parse loop 0x0f = (ER_END(0x0e) | ER_VALID(0x01)) -+ 0x0000000f -+}; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.h b/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/sb2_erom.h 2017-11-09 17:53:44.062302000 +0800 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet -+ * Saber2 sudo EROM -+ * -+ */ -+ -+#ifndef _sb2_erom_h_ -+#define _sb2_erom_h_ -+ -+extern uint32 sb2_erom[]; -+ -+#endif /* _sb2_erom_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/sgmiiplus2_serdes.c b/drivers/net/ethernet/broadcom/gmac/src/shared/sgmiiplus2_serdes.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/sgmiiplus2_serdes.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/sgmiiplus2_serdes.c 2017-11-09 17:53:44.063293000 +0800 -@@ -0,0 +1,102 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * These routines provide access to the serdes -+ * -+ */ -+ -+/* ---- Include Files ---------------------------------------------------- */ -+#include -+#include -+#include "bcmiproc_serdes.h" -+#include "bcmiproc_serdes_def.h" -+#include "../../../mdio/iproc_mdio.h" -+ -+/* ---- External Variable Declarations ----------------------------------- */ -+/* ---- External Function Prototypes ------------------------------------- */ -+/* ---- Public Variables ------------------------------------------------- */ -+/* ---- Private Constants and Types -------------------------------------- */ -+/* ---- Private Variables ------------------------------------------------ */ -+ -+/* debug/trace */ -+//#define BCMDBG -+//#define BCMDBG_ERR -+#ifdef BCMDBG -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) printf args -+#elif defined(BCMDBG_ERR) -+#define NET_ERROR(args) printf args -+#define NET_TRACE(args) -+#else -+#define NET_ERROR(args) -+#define NET_TRACE(args) -+#endif /* BCMDBG */ -+#define NET_REG_TRACE(args) -+ -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+ -+void -+sgmiiplus2_serdes_reset(uint eth_num, uint phyaddr) -+{ -+ uint16 ctrl; -+ -+ ASSERT(phyaddr < MAXEPHY); -+ -+ if (phyaddr == EPHY_NOREG) -+ return; -+ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x1f, 0x0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0, 0x8000); -+ -+ udelay(100); -+ -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, 0x0, &ctrl); -+ if (ctrl & 0x8000) -+ NET_ERROR(("et%d: %s serdes reset not complete\n", eth_num, __FUNCTION__)); -+ -+} -+ -+int -+sgmiiplus2_serdes_init(uint eth_num, uint phyaddr) -+{ -+ u16 id1, id2; -+ -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, 0x0002, &id1); -+ iproc_mii_read(MII_DEV_LOCAL, phyaddr, 0x0003, &id2); -+ printf("Internal phyaddr %d: Get PHY ID0:%.4x, ID1:%.4x\n", phyaddr, id1, id2); -+ -+ /* Disable PLL */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x0000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x062f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x0000); -+ -+ /* Disable lmtcal (broadcast to all lanes) */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x001f); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8480); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0012, 0x83f8); -+ -+ /* Auto negotiation 10/100/1G - SGMII Slave (broadcast to all lanes) */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8300); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x0100); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8340); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001a, 0x0003); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x0000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0000, 0x1140); -+ -+ /* Change PLL calibration threshold to 0xc */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0xffd0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001e, 0x0000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8180); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0011, 0x0600); -+ -+ /* Enable PLL */ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x001f, 0x8000); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x0010, 0x262f); -+ -+ return 0; -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/siutils.c b/drivers/net/ethernet/broadcom/gmac/src/shared/siutils.c ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/siutils.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/siutils.c 2017-11-09 17:53:44.065294000 +0800 -@@ -0,0 +1,1409 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+ * -+ * Misc utility routines for accessing chip-specific features -+ * of the SiliconBackplane-based Broadcom chips. -+ * -+ * $Id: siutils.c 328955 2012-04-23 09:06:12Z $ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "siutils_priv.h" -+ -+/* local prototypes */ -+static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, uint *varsz); -+static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, -+ uint *origidx, void *regs); -+ -+static void si_nvram_process(si_info_t *sii, char *pvars); -+/* dev path concatenation util */ -+static char *si_devpathvar(si_t *sih, char *var, int len, const char *name); -+static bool _si_clkctl_cc(si_info_t *sii, uint mode); -+ -+/* global variable to indicate reservation/release of gpio's */ -+static uint32 si_gpioreservation = 0; -+ -+/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ -+ -+/* -+ * Allocate a si handle. -+ * devid - pci device id (used to determine chip#) -+ * osh - opaque OS handle -+ * regs - virtual address of initial core registers -+ * bustype - pci/pcmcia/sb/sdio/etc -+ * vars - pointer to a pointer area for "environment" variables -+ * varsz - pointer to int to return the size of the vars -+ */ -+si_t * -+BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, uint *varsz) -+{ -+ si_info_t *sii; -+ si_t *sih; -+ -+ /* alloc si_info_t */ -+ if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { -+ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); -+ return (NULL); -+ } -+ -+ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { -+ MFREE(osh, sii, sizeof(si_info_t)); -+ SI_ERROR(("%s si_doattach() failed\n", __FUNCTION__)); -+ return (NULL); -+ } -+ sii->vars = vars ? *vars : NULL; -+ sii->varsz = varsz ? *varsz : 0; -+ -+ sih = (si_t*)sii; -+ printk("%s socitype(0x%x) chip(0x%x) chiprev(0x%x) chippkg(0x%x)\n", -+ __FUNCTION__, sih->socitype, sih->chip, sih->chiprev, sih->chippkg); -+ -+ return (si_t *)sii; -+} -+ -+static bool -+BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, -+ uint *origidx, void *regs) -+{ -+ bool pci, pcie; -+ uint i; -+ uint pciidx, pcieidx, pcirev, pcierev; -+ -+ cc = si_setcoreidx(&sii->pub, SI_CC_IDX); -+ ASSERT((uintptr)cc); -+ -+ /* get chipcommon rev */ -+ sii->pub.ccrev = (int)si_corerev(&sii->pub); -+ -+ /* get chipcommon chipstatus */ -+ if (sii->pub.ccrev >= 11) { -+ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); -+ } -+ -+ /* get chipcommon capabilites */ -+ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); -+ /* get chipcommon extended capabilities */ -+ if (sii->pub.ccrev >= 35) { -+ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); -+ } -+ -+ /* get pmu rev and caps */ -+ if (sii->pub.cccaps & CC_CAP_PMU) { -+ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); -+ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; -+ } -+ -+ SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", -+ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, -+ sii->pub.pmucaps)); -+ -+ /* figure out bus/orignal core idx */ -+ sii->pub.buscoretype = NODEV_CORE_ID; -+ sii->pub.buscorerev = (uint)NOREV; -+ sii->pub.buscoreidx = BADIDX; -+ -+ pci = pcie = FALSE; -+ pcirev = pcierev = (uint)NOREV; -+ pciidx = pcieidx = BADIDX; -+ -+ for (i = 0; i < sii->numcores; i++) { -+ uint cid, crev; -+ -+ si_setcoreidx(&sii->pub, i); -+ cid = si_coreid(&sii->pub); -+ crev = si_corerev(&sii->pub); -+ -+ /* Display cores found */ -+ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", -+ i, cid, crev, sii->coresba[i], sii->regs[i])); -+ -+ /* find the core idx before entering this func. */ -+ if ((savewin && (savewin == sii->coresba[i])) || -+ (regs == sii->regs[i])) { -+ *origidx = i; -+ } -+ } -+ -+ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, -+ sii->pub.buscorerev)); -+ -+ /* return to the original core */ -+ si_setcoreidx(&sii->pub, *origidx); -+ -+ return TRUE; -+} -+ -+static void -+BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars) -+{ -+ /* get boardtype and boardrev */ -+ switch (BUSTYPE(sii->pub.bustype)) { -+ case SI_BUS: -+ sii->pub.boardvendor = VENDOR_BROADCOM; -+ if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0)) { -+ if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0) { -+ sii->pub.boardtype = 0xffff; -+ } -+ } -+ break; -+ } -+ -+ if (sii->pub.boardtype == 0) { -+ SI_ERROR(("si_doattach: unknown board type\n")); -+ ASSERT(sii->pub.boardtype); -+ } -+ -+ sii->pub.boardrev = getintvar(pvars, "boardrev"); -+ sii->pub.boardflags = getintvar(pvars, "boardflags"); -+} -+ -+static si_info_t * -+BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, uint *varsz) -+{ -+ struct si_pub *sih = &sii->pub; -+ uint32 w, savewin; -+ chipcregs_t *cc; -+ char *pvars = NULL; -+ uint origidx; -+ ASSERT(GOODREGS(regs)); -+ -+ bzero((uchar*)sii, sizeof(si_info_t)); -+ -+ savewin = 0; -+ sih->buscoreidx = BADIDX; -+ sii->curmap = regs; -+ sii->sdh = sdh; -+ sii->osh = osh; -+ -+ /* find Chipcommon address */ -+ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); -+ -+ sih->bustype = bustype; -+ if (bustype != BUSTYPE(bustype)) { -+ SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", -+ bustype, BUSTYPE(bustype))); -+ return NULL; -+ } -+ -+ /* ChipID recognition. -+ * We assume we can read chipid at offset 0 from the regs arg. -+ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), -+ * some way of recognizing them needs to be added here. -+ */ -+ if (!cc) { -+ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); -+ return NULL; -+ } -+ w = R_REG(osh, &cc->chipid); -+ printk("%s chipid: 0x%x\n", __FUNCTION__, w); -+#if defined(CONFIG_MACH_IPROC_P7) -+ sih->socitype = SOCI_AI; -+ /* get chip id rev & pkg */ -+ sih->chip = w & 0xfffff; -+ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; -+ w = R_REG(osh, &cc->capabilities); -+ sih->chiprev = w & 0xff; -+#else -+ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; -+ /* Might as wll fill in chip id rev & pkg */ -+ sih->chip = w & CID_ID_MASK; -+ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; -+ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; -+ /* printk("%s chip: 0x%x; chiprev: 0x%x; chippkg: 0x%x\n", __FUNCTION__, sih->chip, sih->chiprev, sih->chippkg); */ -+#endif /* CONFIG_MACH_IPROC_P7 */ -+ -+ sih->issim = IS_SIM(sih->chippkg); -+ -+ /* scan for cores */ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ SI_MSG(("Found chip type SB (0x%08x)\n", w)); -+ sb_scan(sih, regs, devid); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ SI_MSG(("Found chip type %s (0x%08x)\n", (CHIPTYPE(sih->socitype) == SOCI_AI) ? "AI" : "NS", w)); -+ ai_scan(sih, (void *)(uintptr)cc, devid); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); -+ ub_scan(sih, (void *)(uintptr)cc, devid); -+ } else { -+ SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); -+ return NULL; -+ } -+ -+ /* no cores found, bail out */ -+ if (sii->numcores == 0) { -+ SI_ERROR(("si_doattach: could not find any cores\n")); -+ return NULL; -+ } -+ /* bus/core/clk setup */ -+ origidx = SI_CC_IDX; -+ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { -+ SI_ERROR(("si_doattach: si_buscore_setup failed\n")); -+ goto exit; -+ } -+ -+ spin_lock_init(&sih->sih_lock); -+ -+ /* Init nvram from flash if it exists */ -+ nvram_init((void *)sih); -+ -+ pvars = vars ? *vars : NULL; -+ si_nvram_process(sii, pvars); -+ -+ /* bootloader should retain default pulls */ -+#ifndef BCM_BOOTLOADER -+ if (sih->ccrev >= 20) { -+ uint32 gpiopullup = 0, gpiopulldown = 0; -+ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); -+ ASSERT(cc != NULL); -+ -+ W_REG(osh, &cc->gpiopullup, gpiopullup); -+ W_REG(osh, &cc->gpiopulldown, gpiopulldown); -+ si_setcoreidx(sih, origidx); -+ } -+#endif /* !BCM_BOOTLOADER */ -+ -+ -+ /* setup the GPIO based LED powersave register */ -+ if (sih->ccrev >= 16) { -+ if ((w = getintvar(pvars, "leddc")) == 0) { -+ w = DEFAULT_GPIOTIMERVAL; -+ } -+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); -+ } -+ -+#if !defined(_CFE_) || defined(CFG_WL) -+ /* enable GPIO interrupts when clocks are off */ -+ if (sih->ccrev >= 21) { -+ uint32 corecontrol; -+ corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), -+ 0, 0); -+ corecontrol |= CC_ASYNCGPIO; -+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), -+ corecontrol, corecontrol); -+ } -+#endif /* !_CFE_ || CFG_WL */ -+ -+ return (sii); -+exit: -+ return NULL; -+} -+ -+/* may be called with core in reset */ -+void -+BCMATTACHFN(si_detach)(si_t *sih) -+{ -+ si_info_t *sii; -+ uint idx; -+ -+ sii = SI_INFO(sih); -+ if (sii == NULL) { -+ return; -+ } -+ -+ if (BUSTYPE(sih->bustype) == SI_BUS) { -+ for (idx = 0; idx < SI_MAXCORES; idx++) { -+ if (sii->regs[idx]) { -+ REG_UNMAP(sii->regs[idx]); -+ sii->regs[idx] = NULL; -+ } -+ } -+ } -+ -+ MFREE(sii->osh, sii, sizeof(si_info_t)); -+} -+ -+void * -+si_osh(si_t *sih) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ return sii->osh; -+} -+ -+void -+si_setosh(si_t *sih, osl_t *osh) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ if (sii->osh != NULL) { -+ SI_ERROR(("osh is already set....\n")); -+ ASSERT(!sii->osh); -+ } -+ sii->osh = osh; -+} -+ -+uint -+si_intflag(si_t *sih) -+{ -+ si_info_t *sii = SI_INFO(sih); -+ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_intflag(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return R_REG(sii->osh, ((uint32 *)(uintptr) -+ (sii->oob_router + OOB_STATUSA))); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+uint -+si_flag(si_t *sih) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_flag(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_flag(sih); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_flag(sih); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+void -+si_setint(si_t *sih, int siflag) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_setint(sih, siflag); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_setint(sih, siflag); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_setint(sih, siflag); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+uint -+si_coreid(si_t *sih) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ return sii->coreid[sii->curidx]; -+} -+ -+uint -+si_coreidx(si_t *sih) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ return sii->curidx; -+} -+ -+/* return the core-type instantiation # of the current core */ -+uint -+si_coreunit(si_t *sih) -+{ -+ si_info_t *sii; -+ uint idx; -+ uint coreid; -+ uint coreunit; -+ uint i; -+ -+ sii = SI_INFO(sih); -+ coreunit = 0; -+ -+ idx = sii->curidx; -+ -+ ASSERT(GOODREGS(sii->curmap)); -+ coreid = si_coreid(sih); -+ -+ /* count the cores of our type */ -+ for (i = 0; i < idx; i++) { -+ if (sii->coreid[i] == coreid) { -+ coreunit++; -+ } -+ } -+ -+ return (coreunit); -+} -+ -+uint -+si_corevendor(si_t *sih) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_corevendor(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_corevendor(sih); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_corevendor(sih); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+bool -+si_backplane64(si_t *sih) -+{ -+ return ((sih->cccaps & CC_CAP_BKPLN64) != 0); -+} -+ -+uint -+si_corerev(si_t *sih) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_corerev(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_corerev(sih); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_corerev(sih); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+/* return index of coreid or BADIDX if not found */ -+uint -+si_findcoreidx(si_t *sih, uint coreid, uint coreunit) -+{ -+ si_info_t *sii; -+ uint found; -+ uint i; -+ -+ sii = SI_INFO(sih); -+ -+ found = 0; -+ -+ for (i = 0; i < sii->numcores; i++) { -+ if (sii->coreid[i] == coreid) { -+ if (found == coreunit) -+ return (i); -+ found++; -+ } -+ } -+ -+ return (BADIDX); -+} -+ -+/* return list of found cores */ -+uint -+si_corelist(si_t *sih, uint coreid[]) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ -+ bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); -+ return (sii->numcores); -+} -+ -+/* return current register mapping */ -+void * -+si_coreregs(si_t *sih) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ ASSERT(GOODREGS(sii->curmap)); -+ -+ return (sii->curmap); -+} -+ -+/* -+ * This function changes logical "focus" to the indicated core; -+ * must be called with interrupts off. -+ * Moreover, callers should keep interrupts off during switching out of and back to d11 core -+ */ -+void * -+si_setcore(si_t *sih, uint coreid, uint coreunit) -+{ -+ uint idx; -+ -+ idx = si_findcoreidx(sih, coreid, coreunit); -+ if (!GOODIDX(idx)) { -+ return (NULL); -+ } -+ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_setcoreidx(sih, idx); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_setcoreidx(sih, idx); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_setcoreidx(sih, idx); -+ } -+ -+ ASSERT(0); -+ return NULL; -+} -+ -+void * -+si_setcoreidx(si_t *sih, uint coreidx) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_setcoreidx(sih, coreidx); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_setcoreidx(sih, coreidx); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_setcoreidx(sih, coreidx); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+/* Turn off interrupt as required by sb_setcore, before switch core */ -+void * -+si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) -+{ -+ void *cc; -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ -+ if (SI_FAST(sii)) { -+ /* Overloading the origidx variable to remember the coreid, -+ * this works because the core ids cannot be confused with -+ * core indices. -+ */ -+ *origidx = coreid; -+ if (coreid == CC_CORE_ID) { -+ return (void *)CCREGS_FAST(sii); -+ } else if (coreid == sih->buscoretype) { -+ return (void *)PCIEREGS(sii); -+ } -+ } -+ INTR_OFF(sii, *intr_val); -+ *origidx = sii->curidx; -+ cc = si_setcore(sih, coreid, 0); -+ ASSERT(cc != NULL); -+ -+ return cc; -+} -+ -+/* restore coreidx and restore interrupt */ -+void -+si_restore_core(si_t *sih, uint coreid, uint intr_val) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) { -+ return; -+ } -+ -+ si_setcoreidx(sih, coreid); -+ INTR_RESTORE(sii, intr_val); -+} -+ -+int -+si_numaddrspaces(si_t *sih) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_numaddrspaces(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_numaddrspaces(sih); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_numaddrspaces(sih); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+uint32 -+si_addrspace(si_t *sih, uint asidx) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_addrspace(sih, asidx); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_addrspace(sih, asidx); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_addrspace(sih, asidx); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+uint32 -+si_addrspacesize(si_t *sih, uint asidx) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_addrspacesize(sih, asidx); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_addrspacesize(sih, asidx); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_addrspacesize(sih, asidx); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+void -+si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) -+{ -+ /* Only supported for SOCI_AI */ -+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_coreaddrspaceX(sih, asidx, addr, size); -+ } else { -+ *size = 0; -+ } -+} -+ -+uint32 -+si_core_cflags(si_t *sih, uint32 mask, uint32 val) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_core_cflags(sih, mask, val); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_core_cflags(sih, mask, val); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_core_cflags(sih, mask, val); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+void -+si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_core_cflags_wo(sih, mask, val); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_core_cflags_wo(sih, mask, val); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_core_cflags_wo(sih, mask, val); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+uint32 -+si_core_sflags(si_t *sih, uint32 mask, uint32 val) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_core_sflags(sih, mask, val); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_core_sflags(sih, mask, val); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_core_sflags(sih, mask, val); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+bool -+si_iscoreup(si_t *sih) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_iscoreup(sih); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_iscoreup(sih); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_iscoreup(sih); -+ } -+ -+ ASSERT(0); -+ return FALSE; -+} -+ -+uint -+si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) -+{ -+ /* only for AI back plane chips */ -+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return (ai_wrap_reg(sih, offset, mask, val)); -+ } -+ return 0; -+} -+ -+uint -+si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ return sb_corereg(sih, coreidx, regoff, mask, val); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ return ai_corereg(sih, coreidx, regoff, mask, val); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ return ub_corereg(sih, coreidx, regoff, mask, val); -+ } -+ -+ ASSERT(0); -+ return 0; -+} -+ -+void -+si_core_disable(si_t *sih, uint32 bits) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_core_disable(sih, bits); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_core_disable(sih, bits); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_core_disable(sih, bits); -+ } -+} -+ -+void -+si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_core_reset(sih, bits, resetbits); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_core_reset(sih, bits, resetbits); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_core_reset(sih, bits, resetbits); -+ } -+} -+ -+/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ -+int -+si_corebist(si_t *sih) -+{ -+ uint32 cflags; -+ int result = 0; -+ -+ /* Read core control flags */ -+ cflags = si_core_cflags(sih, 0, 0); -+ -+ /* Set bist & fgc */ -+ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); -+ -+ /* Wait for bist done */ -+ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); -+ -+ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) { -+ result = BCME_ERROR; -+ } -+ -+ /* Reset core control flags */ -+ si_core_cflags(sih, 0xffff, cflags); -+ -+ return result; -+} -+ -+static uint32 -+BCMINITFN(factor6)(uint32 x) -+{ -+ switch (x) { -+ case CC_F6_2: return 2; -+ case CC_F6_3: return 3; -+ case CC_F6_4: return 4; -+ case CC_F6_5: return 5; -+ case CC_F6_6: return 6; -+ case CC_F6_7: return 7; -+ default: return 0; -+ } -+} -+ -+/* calculate the speed the SI would run at given a set of clockcontrol values */ -+uint32 -+BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m) -+{ -+ uint32 n1, n2, clock, m1, m2, m3, mc; -+ -+ n1 = n & CN_N1_MASK; -+ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; -+ -+ if (pll_type == PLL_TYPE6) { -+ if (m & CC_T6_MMASK) { -+ return CC_T6_M1; -+ } else { -+ return CC_T6_M0; -+ } -+ } else if ((pll_type == PLL_TYPE1) || -+ (pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE7)) { -+ n1 = factor6(n1); -+ n2 += CC_F5_BIAS; -+ } else if (pll_type == PLL_TYPE2) { -+ n1 += CC_T2_BIAS; -+ n2 += CC_T2_BIAS; -+ ASSERT((n1 >= 2) && (n1 <= 7)); -+ ASSERT((n2 >= 5) && (n2 <= 23)); -+ } else if (pll_type == PLL_TYPE5) { -+ return (100000000); -+ } else { -+ ASSERT(0); -+ } -+ -+ /* PLL types 3 and 7 use BASE2 (25Mhz) */ -+ if ((pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE7)) { -+ clock = CC_CLOCK_BASE2 * n1 * n2; -+ } else { -+ clock = CC_CLOCK_BASE1 * n1 * n2; -+ } -+ -+ if (clock == 0) { -+ return 0; -+ } -+ -+ m1 = m & CC_M1_MASK; -+ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; -+ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; -+ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; -+ -+ if ((pll_type == PLL_TYPE1) || -+ (pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE7)) { -+ m1 = factor6(m1); -+ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) { -+ m2 += CC_F5_BIAS; -+ } else { -+ m2 = factor6(m2); -+ } -+ m3 = factor6(m3); -+ -+ switch (mc) { -+ case CC_MC_BYPASS: return (clock); -+ case CC_MC_M1: return (clock / m1); -+ case CC_MC_M1M2: return (clock / (m1 * m2)); -+ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); -+ case CC_MC_M1M3: return (clock / (m1 * m3)); -+ default: return (0); -+ } -+ } else { -+ ASSERT(pll_type == PLL_TYPE2); -+ -+ m1 += CC_T2_BIAS; -+ m2 += CC_T2M2_BIAS; -+ m3 += CC_T2_BIAS; -+ ASSERT((m1 >= 2) && (m1 <= 7)); -+ ASSERT((m2 >= 3) && (m2 <= 10)); -+ ASSERT((m3 >= 2) && (m3 <= 7)); -+ -+ if ((mc & CC_T2MC_M1BYP) == 0) { -+ clock /= m1; -+ } -+ if ((mc & CC_T2MC_M2BYP) == 0) { -+ clock /= m2; -+ } -+ if ((mc & CC_T2MC_M3BYP) == 0) { -+ clock /= m3; -+ } -+ -+ return (clock); -+ } -+} -+ -+uint32 -+BCMINITFN(si_clock)(si_t *sih) -+{ -+ if (sih->chippkg == BCM4709_PKG_ID) { -+ return NS_SI_CLOCK; -+ } -+ return NS_SLOW_SI_CLOCK; -+} -+ -+#if defined(BCMDBG) -+/* print interesting sbconfig registers */ -+void -+si_dumpregs(si_t *sih, struct bcmstrbuf *b) -+{ -+ si_info_t *sii; -+ uint origidx, intr_val = 0; -+ -+ sii = SI_INFO(sih); -+ origidx = sii->curidx; -+ -+ INTR_OFF(sii, intr_val); -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_dumpregs(sih, b); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_dumpregs(sih, b); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_dumpregs(sih, b); -+ } else { -+ ASSERT(0); -+ } -+ -+ si_setcoreidx(sih, origidx); -+ INTR_RESTORE(sii, intr_val); -+} -+#endif -+ -+#ifdef BCMDBG -+void -+si_view(si_t *sih, bool verbose) -+{ -+ if (CHIPTYPE(sih->socitype) == SOCI_SB) { -+ sb_view(sih, verbose); -+ } else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_view(sih, verbose); -+ } else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) { -+ ub_view(sih, verbose); -+ } else { -+ ASSERT(0); -+ } -+} -+ -+void -+si_viewall(si_t *sih, bool verbose) -+{ -+ si_info_t *sii; -+ uint curidx, i; -+ uint intr_val = 0; -+ -+ sii = SI_INFO(sih); -+ curidx = sii->curidx; -+ -+ INTR_OFF(sii, intr_val); -+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) { -+ ai_viewall(sih, verbose); -+ } else { -+ SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores)); -+ for (i = 0; i < sii->numcores; i++) { -+ si_setcoreidx(sih, i); -+ si_view(sih, verbose); -+ } -+ } -+ si_setcoreidx(sih, curidx); -+ INTR_RESTORE(sii, intr_val); -+} -+#endif /* BCMDBG */ -+ -+/* return the slow clock source - LPO, XTAL, or PCI */ -+static uint -+si_slowclk_src(si_info_t *sii) -+{ -+ chipcregs_t *cc; -+ -+ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); -+ -+ if (sii->pub.ccrev < 6) { -+ return (SCC_SS_XTAL); -+ } else if (sii->pub.ccrev < 10) { -+ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); -+ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); -+ } else { /* Insta-clock */ -+ return (SCC_SS_XTAL); -+ } -+} -+ -+/* return the ILP (slowclock) min or max frequency */ -+static uint -+si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) -+{ -+ uint32 slowclk; -+ uint div; -+ -+ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); -+ -+ /* shouldn't be here unless we've established the chip has dynamic clk control */ -+ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); -+ -+ slowclk = si_slowclk_src(sii); -+ if (sii->pub.ccrev < 6) { -+ if (slowclk == SCC_SS_PCI) { -+ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); -+ } else { -+ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); -+ } -+ } else if (sii->pub.ccrev < 10) { -+ div = 4 * -+ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); -+ if (slowclk == SCC_SS_LPO) { -+ return (max_freq ? LPOMAXFREQ : LPOMINFREQ); -+ } else if (slowclk == SCC_SS_XTAL) { -+ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); -+ } else if (slowclk == SCC_SS_PCI) { -+ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); -+ } else { -+ ASSERT(0); -+ } -+ } else { -+ /* Chipc rev 10 is InstaClock */ -+ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; -+ div = 4 * (div + 1); -+ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); -+ } -+ return (0); -+} -+ -+static void -+BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs) -+{ -+ chipcregs_t *cc = (chipcregs_t *)chipcregs; -+ uint slowmaxfreq, pll_delay, slowclk; -+ uint pll_on_delay, fref_sel_delay; -+ -+ pll_delay = PLL_DELAY; -+ -+ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay -+ * since the xtal will also be powered down by dynamic clk control logic. -+ */ -+ -+ slowclk = si_slowclk_src(sii); -+ if (slowclk != SCC_SS_XTAL) { -+ pll_delay += XTAL_ON_DELAY; -+ } -+ -+ /* Starting with 4318 it is ILP that is used for the delays */ -+ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); -+ -+ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; -+ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; -+ -+ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); -+ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); -+} -+ -+/* initialize power control delay registers */ -+void -+BCMINITFN(si_clkctl_init)(si_t *sih) -+{ -+ si_info_t *sii; -+ uint origidx = 0; -+ chipcregs_t *cc; -+ bool fast; -+ -+ if (!CCCTL_ENAB(sih)) { -+ return; -+ } -+ -+ sii = SI_INFO(sih); -+ fast = SI_FAST(sii); -+ if (!fast) { -+ origidx = sii->curidx; -+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { -+ return; -+ } -+ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) { -+ return; -+ } -+ ASSERT(cc != NULL); -+ -+ /* set all Instaclk chip ILP to 1 MHz */ -+ if (sih->ccrev >= 10) { -+ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, -+ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); -+ } -+ -+ si_clkctl_setdelay(sii, (void *)(uintptr)cc); -+ -+ if (!fast) { -+ si_setcoreidx(sih, origidx); -+ } -+} -+ -+/* turn primary xtal and/or pll off/on */ -+int -+si_clkctl_xtal(si_t *sih, uint what, bool on) -+{ -+ switch (BUSTYPE(sih->bustype)) { -+ -+ default: -+ return (-1); -+ } -+ -+} -+ -+/* -+ * clock control policy function throught chipcommon -+ * -+ * set dynamic clk control mode (forceslow, forcefast, dynamic) -+ * returns true if we are forcing fast clock -+ * this is a wrapper over the next internal function -+ * to allow flexible policy settings for outside caller -+ */ -+bool -+si_clkctl_cc(si_t *sih, uint mode) -+{ -+ si_info_t *sii; -+ -+ sii = SI_INFO(sih); -+ -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (sih->ccrev < 6) { -+ return FALSE; -+ } -+ -+ return _si_clkctl_cc(sii, mode); -+} -+ -+/* clk control mechanism through chipcommon, no policy checking */ -+static bool -+_si_clkctl_cc(si_info_t *sii, uint mode) -+{ -+ uint origidx = 0; -+ chipcregs_t *cc; -+ uint32 scc; -+ uint intr_val = 0; -+ bool fast = SI_FAST(sii); -+ -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (sii->pub.ccrev < 6) { -+ return (FALSE); -+ } -+ -+ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ -+ ASSERT(sii->pub.ccrev != 10); -+ -+ if (!fast) { -+ INTR_OFF(sii, intr_val); -+ origidx = sii->curidx; -+ -+ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && -+ si_setcore(&sii->pub, MIPS33_CORE_ID, 0) && -+ (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) { -+ goto done; -+ } -+ -+ cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0); -+ } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL) { -+ goto done; -+ } -+ -+ ASSERT(cc != NULL); -+ -+ if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20)) { -+ goto done; -+ } -+ -+ switch (mode) { -+ case CLK_FAST: /* FORCEHT, fast (pll) clock */ -+ if (sii->pub.ccrev < 10) { -+ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ -+ si_clkctl_xtal(&sii->pub, XTAL, ON); -+ SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); -+ } else if (sii->pub.ccrev < 20) { -+ OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR); -+ } else { -+ OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT); -+ } -+ -+ /* wait for the PLL */ -+ if (PMUCTL_ENAB(&sii->pub)) { -+ uint32 htavail = CCS_HTAVAIL; -+ -+ SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0), -+ PMU_MAX_TRANSITION_DLY); -+ ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail); -+ } else { -+ OSL_DELAY(PLL_DELAY); -+ } -+ break; -+ -+ case CLK_DYNAMIC: /* enable dynamic clock control */ -+ if (sii->pub.ccrev < 10) { -+ scc = R_REG(sii->osh, &cc->slow_clk_ctl); -+ scc &= ~(SCC_FS | SCC_IP | SCC_XC); -+ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) { -+ scc |= SCC_XC; -+ } -+ W_REG(sii->osh, &cc->slow_clk_ctl, scc); -+ -+ /* for dynamic control, we have to release our xtal_pu "force on" */ -+ if (scc & SCC_XC) { -+ si_clkctl_xtal(&sii->pub, XTAL, OFF); -+ } -+ } else if (sii->pub.ccrev < 20) { -+ /* Instaclock */ -+ AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR); -+ } else { -+ AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); -+ } -+ break; -+ -+ default: -+ ASSERT(0); -+ } -+ -+done: -+ if (!fast) { -+ si_setcoreidx(&sii->pub, origidx); -+ INTR_RESTORE(sii, intr_val); -+ } -+ return (mode == CLK_FAST); -+} -+ -+/* Build device path. Support SI, PCI, and JTAG for now. */ -+int -+BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size) -+{ -+ int slen; -+ -+ ASSERT(path != NULL); -+ ASSERT(size >= SI_DEVPATH_BUFSZ); -+ -+ if (!path || size <= 0) -+ return -1; -+ -+ switch (BUSTYPE(sih->bustype)) { -+ case SI_BUS: -+ slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih)); -+ break; -+ default: -+ slen = -1; -+ ASSERT(0); -+ break; -+ } -+ -+ if (slen < 0 || slen >= size) { -+ path[0] = '\0'; -+ return -1; -+ } -+ -+ return 0; -+} -+ -+char * -+BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name) -+{ -+ char pathname[SI_DEVPATH_BUFSZ + 32]; -+ char devpath[SI_DEVPATH_BUFSZ + 32]; -+ char *p; -+ int idx; -+ int len; -+ -+ /* try to get compact devpath if it exist */ -+ if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) { -+ len = strlen(devpath); -+ devpath[len - 1] = '\0'; -+ for (idx = 0; idx < SI_MAXCORES; idx++) { -+ snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx); -+ if ((p = getvar(NULL, pathname)) == NULL) { -+ continue; -+ } -+ -+ if (strncmp(p, devpath, len) == 0) { -+ snprintf(varname, var_len, "%d:%s", idx, name); -+ return varname; -+ } -+ } -+ } -+ -+ return NULL; -+} -+ -+/* Get a variable, but only if it has a devpath prefix */ -+int -+BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name) -+{ -+#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) -+ return (getintvar(NULL, name)); -+#else -+ char varname[SI_DEVPATH_BUFSZ + 32]; -+ int val; -+ -+ si_devpathvar(sih, varname, sizeof(varname), name); -+ -+ if ((val = getintvar(NULL, varname)) != 0) { -+ return val; -+ } -+ -+ /* try to get compact devpath if it exist */ -+ if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) { -+ return 0; -+ } -+ -+ return (getintvar(NULL, varname)); -+#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */ -+} -+ -+/* Concatenate the dev path with a varname into the given 'var' buffer -+ * and return the 'var' pointer. -+ * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. -+ * On overflow, the first char will be set to '\0'. -+ */ -+static char * -+BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name) -+{ -+ uint path_len; -+ -+ if (!var || len <= 0) { -+ return var; -+ } -+ -+ if (si_devpath(sih, var, len) == 0) { -+ path_len = strlen(var); -+ -+ if (strlen(name) + 1 > (uint)(len - path_len)) { -+ var[0] = '\0'; -+ } else { -+ strncpy(var + path_len, name, len - path_len - 1); -+ } -+ } -+ -+ return var; -+} -+ -+ -+#if defined(BCMDBG) -+#endif -+ -+/* mask&set gpio output enable bits */ -+uint32 -+si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) -+{ -+ uint regoff; -+ -+ regoff = 0; -+ -+ /* gpios could be shared on router platforms -+ * ignore reservation if it's high priority (e.g., test apps) -+ */ -+ if ((priority != GPIO_HI_PRIORITY) && -+ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { -+ mask = priority ? (si_gpioreservation & mask) : -+ ((si_gpioreservation | mask) & ~(si_gpioreservation)); -+ val &= mask; -+ } -+ -+ regoff = OFFSETOF(chipcregs_t, gpioouten); -+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -+} -+ -+/* mask&set gpio output bits */ -+uint32 -+si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) -+{ -+ uint regoff; -+ -+ regoff = 0; -+ -+ /* gpios could be shared on router platforms -+ * ignore reservation if it's high priority (e.g., test apps) -+ */ -+ if ((priority != GPIO_HI_PRIORITY) && -+ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { -+ mask = priority ? (si_gpioreservation & mask) : -+ ((si_gpioreservation | mask) & ~(si_gpioreservation)); -+ val &= mask; -+ } -+ -+ regoff = OFFSETOF(chipcregs_t, gpioout); -+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -+} -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/gmac/src/shared/siutils_priv.h b/drivers/net/ethernet/broadcom/gmac/src/shared/siutils_priv.h ---- a/drivers/net/ethernet/broadcom/gmac/src/shared/siutils_priv.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/gmac/src/shared/siutils_priv.h 2017-11-09 17:53:44.066299000 +0800 -@@ -0,0 +1,236 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 file private to the SOC Interconnect support files. -+ * -+ * $Id: siutils_priv.h 302333 2011-12-11 01:47:49Z $ -+ */ -+ -+#ifndef _siutils_priv_h_ -+#define _siutils_priv_h_ -+ -+#ifdef BCMDBG_ERR -+#define SI_ERROR(args) printf args -+#else -+#define SI_ERROR(args) -+#endif /* BCMDBG_ERR */ -+ -+#ifdef BCMDBG -+#define SI_MSG(args) printf args -+#else -+#define SI_MSG(args) -+#endif /* BCMDBG */ -+ -+#ifdef BCMDBG_SI -+#define SI_VMSG(args) printf args -+#else -+#define SI_VMSG(args) -+#endif -+ -+#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) -+ -+typedef uint32 (*si_intrsoff_t)(void *intr_arg); -+typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); -+typedef bool (*si_intrsenabled_t)(void *intr_arg); -+ -+typedef struct gpioh_item { -+ void *arg; -+ bool level; -+ gpio_handler_t handler; -+ uint32 event; -+ struct gpioh_item *next; -+} gpioh_item_t; -+ -+/* misc si info needed by some of the routines */ -+typedef struct si_info { -+ struct si_pub pub; /* back plane public state (must be first field) */ -+ -+ void *osh; /* osl os handle */ -+ void *sdh; /* bcmsdh handle */ -+ -+ uint dev_coreid; /* the core provides driver functions */ -+ void *intr_arg; /* interrupt callback function arg */ -+ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ -+ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ -+ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ -+ -+ void *pch; /* PCI/E core handle */ -+ gpioh_item_t *gpioh_head; /* GPIO event handlers list */ -+ bool memseg; /* flag to toggle MEM_SEG register */ -+ char *vars; -+ uint varsz; -+ -+ void *curmap; /* current regs va */ -+ void *regs[SI_MAXCORES]; /* other regs va */ -+ -+ uint curidx; /* current core index */ -+ uint numcores; /* # discovered cores */ -+ uint coreid[SI_MAXCORES]; /* id of each core */ -+ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ -+ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ -+ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ -+ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ -+ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ -+ -+ void *curwrap; /* current wrapper va */ -+ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ -+ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ -+ -+ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ -+ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ -+ uint32 oob_router; /* oob router registers for axi */ -+} si_info_t; -+ -+#define SI_INFO(sih) (si_info_t *)(uintptr)sih -+ -+#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ -+ ISALIGNED((x), SI_CORE_SIZE)) -+#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) -+#define BADCOREADDR 0 -+#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) -+#define NOREV -1 /* Invalid rev */ -+ -+#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ -+ ((si)->pub.buscoretype == PCI_CORE_ID)) -+ -+#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ -+ ((si)->pub.buscoretype == PCIE_CORE_ID)) -+ -+#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ -+ ((si)->pub.buscoretype == PCIE2_CORE_ID)) -+ -+#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si)) -+ -+#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) -+ -+/* Newer chips can access PCI/PCIE and CC core without requiring to change -+ * PCI BAR0 WIN -+ */ -+#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13))) -+ -+#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) -+#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) -+ -+/* -+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ -+ * after core switching to avoid invalid register accesss inside ISR. -+ */ -+#define INTR_OFF(si, intr_val) \ -+ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ -+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } -+#define INTR_RESTORE(si, intr_val) \ -+ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ -+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } -+ -+/* dynamic clock control defines */ -+#define LPOMINFREQ 25000 /* low power oscillator min */ -+#define LPOMAXFREQ 43000 /* low power oscillator max */ -+#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ -+#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ -+#define PCIMINFREQ 25000000 /* 25 MHz */ -+#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ -+ -+#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -+#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ -+ -+/* GPIO Based LED powersave defines */ -+#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ -+#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ -+#ifndef DEFAULT_GPIOTIMERVAL -+#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) -+#endif -+ -+#define sb_scan(a, b, c) do {} while (0) -+#define sb_coreid(a) (0) -+#define sb_intflag(a) (0) -+#define sb_flag(a) (0) -+#define sb_setint(a, b) do {} while (0) -+#define sb_corevendor(a) (0) -+#define sb_corerev(a) (0) -+#define sb_corereg(a, b, c, d, e) (0) -+#define sb_iscoreup(a) (false) -+#define sb_setcoreidx(a, b) (0) -+#define sb_core_cflags(a, b, c) (0) -+#define sb_core_cflags_wo(a, b, c) do {} while (0) -+#define sb_core_sflags(a, b, c) (0) -+#define sb_commit(a) do {} while (0) -+#define sb_base(a) (0) -+#define sb_size(a) (0) -+#define sb_core_reset(a, b, c) do {} while (0) -+#define sb_core_disable(a, b) do {} while (0) -+#define sb_addrspace(a, b) (0) -+#define sb_addrspacesize(a, b) (0) -+#define sb_numaddrspaces(a) (0) -+#define sb_set_initiator_to(a, b, c) (0) -+#define sb_taclear(a, b) (false) -+#define sb_view(a, b) do {} while (0) -+#define sb_viewall(a, b) do {} while (0) -+#define sb_dump(a, b) do {} while (0) -+#define sb_dumpregs(a, b) do {} while (0) -+ -+ -+/* AMBA Interconnect exported externs */ -+extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, -+ void *sdh, char **vars, uint *varsz); -+extern si_t *ai_kattach(osl_t *osh); -+extern void ai_scan(si_t *sih, void *regs, uint devid); -+extern uint ai_flag(si_t *sih); -+extern void ai_setint(si_t *sih, int siflag); -+extern uint ai_coreidx(si_t *sih); -+extern uint ai_corevendor(si_t *sih); -+extern uint ai_corerev(si_t *sih); -+extern bool ai_iscoreup(si_t *sih); -+extern void *ai_setcoreidx(si_t *sih, uint coreidx); -+extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); -+extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); -+extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); -+extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); -+extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -+extern void ai_core_disable(si_t *sih, uint32 bits); -+extern int ai_numaddrspaces(si_t *sih); -+extern uint32 ai_addrspace(si_t *sih, uint asidx); -+extern uint32 ai_addrspacesize(si_t *sih, uint asidx); -+extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); -+extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); -+#ifdef BCMDBG -+extern void ai_view(si_t *sih, bool verbose); -+extern void ai_viewall(si_t *sih, bool verbose); -+#endif /* BCMDBG */ -+#if defined(BCMDBG) -+extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b); -+#endif -+ -+ -+#define ub_scan(a, b, c) do {} while (0) -+#define ub_flag(a) (0) -+#define ub_setint(a, b) do {} while (0) -+#define ub_coreidx(a) (0) -+#define ub_corevendor(a) (0) -+#define ub_corerev(a) (0) -+#define ub_iscoreup(a) (0) -+#define ub_setcoreidx(a, b) (0) -+#define ub_core_cflags(a, b, c) (0) -+#define ub_core_cflags_wo(a, b, c) do {} while (0) -+#define ub_core_sflags(a, b, c) (0) -+#define ub_corereg(a, b, c, d, e) (0) -+#define ub_core_reset(a, b, c) do {} while (0) -+#define ub_core_disable(a, b) do {} while (0) -+#define ub_numaddrspaces(a) (0) -+#define ub_addrspace(a, b) (0) -+#define ub_addrspacesize(a, b) (0) -+#define ub_view(a, b) do {} while (0) -+#define ub_dumpregs(a, b) do {} while (0) -+ -+#endif /* _siutils_priv_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/Kconfig b/drivers/net/ethernet/broadcom/mdio/Kconfig ---- a/drivers/net/ethernet/broadcom/mdio/Kconfig 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/Kconfig 2017-11-09 17:53:44.076300000 +0800 -@@ -0,0 +1,23 @@ -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+config MDIO_XGS_IPROC -+ tristate "BRCM XGS iProc MDIO support" -+ depends on ARCH_XGS_IPROC -+ default n -+ help -+ MDIO support -+ -+ If unsure, say N. -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/Makefile b/drivers/net/ethernet/broadcom/mdio/Makefile ---- a/drivers/net/ethernet/broadcom/mdio/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/Makefile 2017-11-09 17:53:44.077310000 +0800 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. -+# -+obj-$(CONFIG_MDIO_XGS_IPROC) := iproc_mii.o -+iproc_mii-objs := ccb_mdio.o cmicd_mdio.o ccg_mdio.o iproc_mdio.o -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/ccb_mdio.c b/drivers/net/ethernet/broadcom/mdio/ccb_mdio.c ---- a/drivers/net/ethernet/broadcom/mdio/ccb_mdio.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/ccb_mdio.c 2017-11-09 17:53:44.079291000 +0800 -@@ -0,0 +1,873 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include "iproc_mdio.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "iproc_mdio_dev.h" -+ -+#ifdef CONFIG_OF_MDIO -+#include -+#include -+#include -+static struct iproc_mdiobus_data iproc_mdiobus_data; -+#define __devinit /* */ -+#define __devexit /* */ -+#endif /* CONFIG_OF_MDIO */ -+ -+#ifndef CONFIG_OF_MDIO -+#define CCB_MDIO_BASE_ADDRESS IPROC_MII_MGMT_CTL -+#endif -+ -+#define R_REG(reg) ioread32(ccb_mdio->base + (reg&0x0fff)) -+#define W_REG(reg, val) iowrite32(val, ccb_mdio->base + (reg&0x0fff)) -+ -+#define MII_ERR_VAL 0x0001 -+#define MII_MSG_VAL 0x0002 -+#define MII_DBG_VAL 0x0004 -+//static u32 mii_msg_level = MII_ERR_VAL; -+ -+#if defined(BCMDBG) || defined(BCMDBG_ERR) -+#define MII_ERR(args) do {if (mii_msg_level & MII_ERR_VAL) printk args;} while (0) -+#else -+#define MII_ERR(args) -+#endif -+ -+#ifdef BCMDBG -+#define MII_MSG(args) do {if (mii_msg_level & MII_MSG_VAL) printk args;} while (0) -+#define MII_DBG(args) do {if (mii_msg_level & MII_DBG_VAL) printk args;} while (0) -+#else -+#define MII_MSG(args) -+#define MII_DBG(args) -+#endif -+ -+#define MII_EN_CHK \ -+ {\ -+ if (!ccb_mdio->base) { \ -+ return MII_ERR_INIT; \ -+ } \ -+ if (!(R_REG(MII_MGMT) & 0x7f)) { \ -+ return MII_ERR_INTERNAL; \ -+ } \ -+ } -+ -+#define MII_TRIES 100000 -+#define MII_POLL_USEC 20 -+ -+struct mdio_device_data { -+ mdio_info_t *mdio; -+ int init; -+}; -+ -+static struct mdio_device_data mdio_devices={0}; -+static uint32_t ccb_mdio_clk_rate; -+ -+#define DRIVER_VERSION "0.01" -+#define DRIVER_NAME "iproc mdio" -+ -+static int mdio_major; -+static struct cdev mdio_cdev; -+ -+#define MDIO_IOC_OP_EXTERNAL_READ 0 -+#define MDIO_IOC_OP_EXTERNAL_WRITE 1 -+#define MDIO_IOC_OP_LOCAL_READ 2 -+#define MDIO_IOC_OP_LOCAL_WRITE 3 -+ -+ -+struct ccb_mdio_ctrl { -+ void __iomem *base; -+ int ref_cnt; -+}; -+ -+struct ccb_mdiobus_private { -+ /* iproc_mdiobus_data field have to be placed at the beginning of -+ * mdiobus private data */ -+ struct iproc_mdiobus_data bus_data; -+ struct ccb_mdio_ctrl *hw_ctrl; -+}; -+ -+static struct ccb_mdio_ctrl *ccb_mdio = NULL; -+ -+#ifndef CONFIG_OF_MDIO -+static struct resource ccb_mdio_mem = { -+ .name = "ccb_mdio", -+ .start = CCB_MDIO_BASE_ADDRESS, -+ .end = CCB_MDIO_BASE_ADDRESS + 0x1000 - 1, -+ .flags = IORESOURCE_MEM, -+}; -+#endif -+ -+/* Function : ccb_mii_read -+ * - Read operation. -+ * Return : -+ * Note : -+ */ -+int -+ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data) -+{ -+ int i; -+ uint32_t ctrl = 0; -+ unsigned long flags; -+ mdio_info_t *mdio = NULL; -+ -+ MII_EN_CHK; -+ -+ mdio = mdio_devices.mdio; -+ -+ spin_lock_irqsave(&mdio->lock, flags); -+ -+ ctrl = R_REG(MII_MGMT); -+ if (dev_type == MII_DEV_LOCAL) { -+ ctrl &= ~MII_MGMT_EXP_MASK; -+ } else { -+ ctrl |= MII_MGMT_EXP_MASK; -+ } -+ W_REG(MII_MGMT, ctrl); -+ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); -+ -+ for (i = 0; i < MII_TRIES; i++) { -+ ctrl = R_REG(MII_MGMT); -+ if (!(ctrl & MII_MGMT_BSY_MASK)) { -+ break; -+ } -+ udelay(MII_POLL_USEC); -+ } -+ if (i >= MII_TRIES) { -+ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ return -1; -+ } -+ -+ ctrl = (((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | -+ ((2 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | -+ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | -+ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | -+ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK)); -+ W_REG(MII_CMD_DATA, ctrl); -+ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); -+ -+ for (i = 0; i < MII_TRIES; i++) { -+ ctrl = R_REG(MII_MGMT); -+ if (!(ctrl & MII_MGMT_BSY_MASK)) { -+ break; -+ } -+ udelay(MII_POLL_USEC); -+ } -+ if (i >= MII_TRIES) { -+ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ return -1; -+ } -+ -+ ctrl = R_REG(MII_CMD_DATA); -+ -+ MII_DBG(("MDIO READ: addr=%x off=%x value=%x\n", phy_addr, reg_off, ctrl)); -+ -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ -+ *data = (ctrl & 0xffff); -+ return 0; -+} -+ -+/* Function : ccb_mii_write -+ * - Write operation. -+ * Return : -+ * Note : -+ */ -+int -+ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data) -+{ -+ int i; -+ uint32_t ctrl = 0; -+ unsigned long flags; -+ mdio_info_t *mdio = NULL; -+ -+ MII_DBG(("MDIO WRITE: addr=%x off=%x\n", phy_addr, reg_off)); -+ -+ MII_EN_CHK; -+ -+ mdio = mdio_devices.mdio; -+ -+ spin_lock_irqsave(&mdio->lock, flags); -+ -+ ctrl = R_REG(MII_MGMT); -+ if (dev_type == MII_DEV_LOCAL) { -+ ctrl &= ~MII_MGMT_EXP_MASK; -+ } else { -+ ctrl |= MII_MGMT_EXP_MASK; -+ } -+ W_REG(MII_MGMT, ctrl); -+ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); -+ -+ for (i = 0; i < MII_TRIES; i++) { -+ ctrl = R_REG(MII_MGMT); -+ if (!(ctrl & MII_MGMT_BSY_MASK)) { -+ break; -+ } -+ udelay(MII_POLL_USEC); -+ } -+ if (i >= MII_TRIES) { -+ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ return -1; -+ } -+ -+ ctrl = (((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | -+ ((1 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | -+ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | -+ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | -+ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK) | -+ ((data << MII_CMD_DATA_DATA_SHIFT) & MII_CMD_DATA_DATA_MASK)); -+ W_REG(MII_CMD_DATA, ctrl); -+ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); -+ -+ -+ for (i = 0; i < MII_TRIES; i++) { -+ ctrl = R_REG(MII_MGMT); -+ if (!(ctrl & MII_MGMT_BSY_MASK)) { -+ break; -+ } -+ udelay(MII_POLL_USEC); -+ } -+ if (i >= MII_TRIES) { -+ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ return -1; -+ } -+ -+ spin_unlock_irqrestore(&mdio->lock, flags); -+ -+ return MII_ERR_NONE; -+} -+ -+/* Function : ccb_mii_freq_set -+ * - Set MII management interface frequency. -+ * Return : -+ * Note : -+ * -+ */ -+int -+ccb_mii_freq_set(int speed_khz) -+{ -+ int rv = MII_ERR_NONE; -+ uint32_t divider = 0; -+ uint32_t mgmt = 0; -+ -+ MII_DBG(("MDIO FREQ SET: %d KHz\n", speed_khz)); -+ -+ /* host clock 66MHz device value the MDCDIV field */ -+ /* resultant MDIO clock should not exceed 2.5MHz */ -+ -+ if (speed_khz > 2500) { -+ MII_ERR(("\n%s: Maximum MDIO frequency is 2.5MHz\n", __FUNCTION__)); -+ return MII_ERR_PARAM; -+ } -+ -+ divider = ccb_mdio_clk_rate / (1000*speed_khz); -+ divider = (divider & MII_MGMT_MDCDIV_MASK); -+ if (divider > 0x7f) { -+ /* make sure the minimum configurable frequency */ -+ divider = 0x7f; -+ } -+ mgmt = R_REG(MII_MGMT); -+ mgmt &= ~MII_MGMT_MDCDIV_MASK; -+ mgmt |= divider; -+ -+ W_REG(MII_MGMT, mgmt); -+ MII_DBG(("MII FREQ(%d KHz): write(0x%x)=0x%x\n",speed_khz, MII_MGMT, mgmt)); -+ -+ return rv; -+} -+ -+static int -+mdio_open(struct inode *inode, struct file *filp) -+{ -+ filp->private_data = mdio_devices.mdio; -+ return 0; -+} -+ -+static int -+mdio_release(struct inode *inode, struct file *filp) -+{ -+ return 0; -+} -+ -+static int mdio_message(mdio_info_t *mdio, -+ struct mdio_ioc_transfer *u_xfers, unsigned n_xfers, int op) -+{ -+ -+ uint8_t pa, ra; -+ uint16_t regval; -+ -+ pa = u_xfers->pa; -+ ra = u_xfers->ra; -+ -+ MII_DBG(("mdio_message: op = %d\n", op)); -+ -+ if (op == MDIO_IOC_OP_LOCAL_READ) { -+ iproc_mii_read(MII_DEV_LOCAL, pa, ra, ®val); -+ u_xfers->rx_buf = regval; -+ } -+ -+ if (op == MDIO_IOC_OP_LOCAL_WRITE) { -+ iproc_mii_write(MII_DEV_LOCAL, pa, ra, u_xfers->tx_buf); -+ } -+ -+ if (op == MDIO_IOC_OP_EXTERNAL_READ) { -+ iproc_mii_read(MII_DEV_EXT, pa, ra, ®val); -+ u_xfers->rx_buf = regval; -+ } -+ -+ if (op == MDIO_IOC_OP_EXTERNAL_WRITE) { -+ iproc_mii_write(MII_DEV_EXT, pa, ra, u_xfers->tx_buf); -+ } -+ return 0; -+} -+ -+static long -+mdio_ioctl(struct file *filp, -+ unsigned int cmd, unsigned long arg) -+{ -+ int err = 0; -+ int retval = 0; -+ int ioc_op = 0; -+ uint32_t tmp; -+ unsigned n_ioc; -+ struct mdio_ioc_transfer *ioc, *uf; -+ mdio_info_t *mdio; -+ -+ MII_DBG(("mdio_ioctl: cmd = %d\n", cmd)); -+ -+ /* Check type and command number */ -+ if (_IOC_TYPE(cmd) != MDIO_IOC_MAGIC){ -+ return -ENOTTY; -+ } -+ -+ /* Check access direction once here; don't repeat below. -+ * IOC_DIR is from the user perspective, while access_ok is -+ * from the kernel perspective; so they look reversed. -+ */ -+ if (_IOC_DIR(cmd) & _IOC_READ) { -+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); -+ } -+ if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) { -+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); -+ } -+ if (err) { -+ return -EFAULT; -+ } -+ -+ mdio = (mdio_info_t *)filp->private_data; -+ -+ switch (cmd) { -+ case MDIO_IOC_EXTERNAL_R_REG: -+ ioc_op = MDIO_IOC_OP_EXTERNAL_READ; -+ break; -+ case MDIO_IOC_EXTERNAL_W_REG: -+ ioc_op = MDIO_IOC_OP_EXTERNAL_WRITE; -+ break; -+ case MDIO_IOC_LOCAL_R_REG: -+ ioc_op = MDIO_IOC_OP_LOCAL_READ; -+ break; -+ case MDIO_IOC_LOCAL_W_REG: -+ ioc_op = MDIO_IOC_OP_LOCAL_WRITE; -+ break; -+ } -+ -+ tmp = _IOC_SIZE(cmd); -+ if ((tmp % sizeof(struct mdio_ioc_transfer)) != 0) { -+ retval = -EINVAL; -+ return retval; -+ } -+ n_ioc = tmp / sizeof(struct mdio_ioc_transfer); -+ if (n_ioc == 0) { -+ return 0; -+ } -+ -+ /* copy into scratch area */ -+ ioc = kmalloc(tmp, GFP_KERNEL); -+ if (!ioc) { -+ retval = -ENOMEM; -+ return retval; -+ } -+ if (__copy_from_user(ioc, (void __user *)arg, tmp)) { -+ kfree(ioc); -+ retval = -EFAULT; -+ return retval; -+ } -+ /* translate to mdio_message, execute */ -+ retval = mdio_message(mdio, ioc, n_ioc, ioc_op); -+ -+ if ((ioc_op == MDIO_IOC_OP_EXTERNAL_READ) || (ioc_op == MDIO_IOC_OP_LOCAL_READ)) { -+ uf = (struct mdio_ioc_transfer *)arg; -+ if (__copy_to_user((u8 __user *)&uf->rx_buf, (uint8_t *)&ioc->rx_buf, 2)) { -+ kfree(ioc); -+ retval = -EFAULT; -+ return retval; -+ } -+ } -+ kfree(ioc); -+ -+ return 0; -+} -+ -+static const struct file_operations mdio_fops = { -+ .open = mdio_open, -+ .release = mdio_release, -+ .unlocked_ioctl = mdio_ioctl, -+ .owner = THIS_MODULE, -+}; -+ -+static int _mdio_handler_init(void) -+{ -+ mdio_info_t *mdio = NULL; -+ -+ mdio = kmalloc(sizeof(mdio_info_t), GFP_KERNEL); -+ if (mdio == NULL) { -+ MII_ERR(("mdio_init: out of memory\n")); -+ return -ENOMEM; -+ } -+ memset(mdio, 0, sizeof(mdio_info_t)); -+ -+ /* Initialize lock */ -+ spin_lock_init(&mdio->lock); -+ -+ mdio_devices.mdio = mdio; -+ mdio_devices.init = 1; -+ -+ return 0; -+} -+ -+ -+static int ccb_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) -+{ -+ struct ccb_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ uint16_t data; -+ int dev_type = 0; -+ int err; -+ -+ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) { -+ dev_type = MII_DEV_LOCAL; -+ } else if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) { -+ dev_type = MII_DEV_EXT; -+ } else { -+ return -EINVAL; -+ } -+ err = ccb_mii_read(dev_type, phy_id, regnum, &data); -+ if (err < 0) { -+ return err; -+ } else { -+ return data; -+ } -+} -+ -+static int ccb_mdiobus_write(struct mii_bus *bus, int phy_id, -+ int regnum, u16 val) -+{ -+ struct ccb_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ int dev_type = 0; -+ -+ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) { -+ dev_type = MII_DEV_LOCAL; -+ } else if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) { -+ dev_type = MII_DEV_EXT; -+ } else { -+ return -EINVAL; -+ } -+ -+ return ccb_mii_write(dev_type, phy_id, regnum, val); -+} -+ -+static void __maybe_unused ccb_mdiobus_test(struct mii_bus *mii_bus) -+{ -+ int i, nRet1, nRet2; -+ u16 data1 = 0, data2 = 0; -+ struct phy_device *phy_dev; -+ struct ccb_mdiobus_private *bus_priv = mii_bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ -+ dev_info(mii_bus->parent, "%s : %s phy bus num[%d], type[%d]\n", -+ __func__, mii_bus->id, bus_data->phybus_num, bus_data->phybus_type); -+ -+ /* Check if mdiobus_read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ phy_dev = mii_bus->phy_map[i]; -+ if (phy_dev) { -+ dev_info(mii_bus->parent, "phy[%d] id=0x%08x, addr = %d\n", -+ i, phy_dev->phy_id, phy_dev->addr); -+ nRet1 = phy_read(phy_dev, 2); -+ nRet2 = phy_read(phy_dev, 3); -+ if ((nRet1 < 0) || (nRet2 < 0)) { -+ dev_info(mii_bus->parent, -+ "phy_read failed!, %s, nRet1 = %d, nRet2 = %d\n", -+ dev_name(&phy_dev->dev), nRet1, nRet2); -+ } else { -+ dev_info(mii_bus->parent, -+ "%s: reg2 = 0x%x, reg3 = 0x%x\n", -+ dev_name(&phy_dev->dev), nRet1, nRet2); -+ } -+ } -+ } -+ -+ /* Check if general interface function for mdiobus read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ data1 = mii_bus->read(mii_bus, i, 2); -+ data2 = mii_bus->read(mii_bus, i, 3); -+ if ((data1 < 0) || (data2 < 0)) { -+ dev_info(mii_bus->parent, -+ "iproc_mdiobus_read failed!, %s phy bus num[%d], type[%d], phyaddr = %d, nRet1 = %d, nRet2 = %d\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } else { -+ dev_info(mii_bus->parent, -+ "read %s phy bus num[%d] type[%d] phyaddr[%d], reg2 = 0x%x, reg3 = 0x%x\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } -+ } -+} -+ -+static struct ccb_mdio_ctrl *ccb_mdio_res_alloc(void) -+{ -+ if (!ccb_mdio) { -+ ccb_mdio = kzalloc(sizeof(*ccb_mdio), GFP_KERNEL); -+ if (!ccb_mdio) { -+ return NULL; -+ } -+ ccb_mdio->ref_cnt = 1; -+ } else { -+ ccb_mdio->ref_cnt++; -+ } -+ -+ return ccb_mdio; -+} -+ -+static void ccb_mdio_res_free(struct ccb_mdio_ctrl *ctrl) -+{ -+ if (ctrl) { -+ ctrl->ref_cnt --; -+ if (ctrl->ref_cnt == 0) { -+ iounmap(ctrl->base); -+ kfree(ctrl); -+ ccb_mdio = NULL; -+ } -+ } -+} -+ -+void -+ccb_mii_init(struct ccb_mdio_ctrl *ccb_mii) -+{ -+ if (ccb_mii->ref_cnt == 1) { -+ /* Set preamble */ -+ W_REG(MII_MGMT, MII_MGMT_PRE_MASK); -+ -+ /* Set the MII default clock 1MHz */ -+ ccb_mii_freq_set(1000); /* KHZ */ -+ } -+} -+ -+#ifdef CONFIG_OF_MDIO -+static int __devinit ccb_mii_probe(struct platform_device *pdev) -+{ -+ int ret = -ENODEV; -+ struct device_node *dn = pdev->dev.of_node; -+ struct mii_bus *mii_bus; -+ struct ccb_mdiobus_private *bus_priv; -+ struct iproc_mdiobus_data *bus_data; -+ u32 mdio_bus_id; -+ const char *mdio_bus_type; -+ struct ccb_mdio_ctrl *ccb_ctrl; -+ struct clk *clk=NULL; -+ -+ if (!of_device_is_available(dn)) -+ return -ENODEV; -+ -+ ccb_ctrl = ccb_mdio_res_alloc(); -+ if (!ccb_ctrl) { -+ printk(KERN_ERR "ccb mdio res alloc failed\n"); -+ return -ENOMEM; -+ -+ } -+ -+ /* Get register base address */ -+ ccb_ctrl->base = (void *)of_iomap(dn, 0); -+ MII_DBG(("MDIO INIT: Base Addr %x\n", ccb_ctrl->base)); -+ -+ clk = of_clk_get (dn, 0); -+ if (clk) -+ ccb_mdio_clk_rate = clk_get_rate(clk)/2; /* used by ccb_mii_freq_set() */ -+ else { -+ printk("No CCB MDIO Clock available from DT, use default clock rate: 62.5MHz\n"); -+ ccb_mdio_clk_rate = 62500000; -+ } -+ -+ ccb_mii_init(ccb_ctrl); -+ -+ if (of_property_read_u32(dn, "#bus-id", &mdio_bus_id)) { -+ mdio_bus_id = 0; /* no property available, use default: 0 */ -+ } -+ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) { -+ mdio_bus_type = "internal"; /* no property available, use default: "internal" */ -+ } -+ iproc_mdiobus_data.phybus_num = (u8) mdio_bus_id; -+ if (!strcmp(mdio_bus_type, "internal")) -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; -+ else -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; -+ /* Note: this applies to CCB/CCG MDIO, but not for CMICD MDIO */ -+ iproc_mdiobus_data.logbus_num = iproc_mdiobus_data.phybus_num; -+ iproc_mdiobus_data.logbus_type = iproc_mdiobus_data.phybus_type; -+ -+ bus_data = &iproc_mdiobus_data; -+ -+ mii_bus = mdiobus_alloc_size(sizeof(*bus_priv)); -+ if (!mii_bus) -+ return -ENOMEM; -+ -+ mii_bus->name = "iproc_ccb_mdiobus"; -+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, IPROC_MDIO_ID_FMT, -+ bus_data->logbus_num, bus_data->logbus_type); -+ mii_bus->parent = &pdev->dev; -+ mii_bus->read = ccb_mdiobus_read; -+ mii_bus->write = ccb_mdiobus_write; -+ -+ bus_priv = mii_bus->priv; -+ memcpy(&bus_priv->bus_data, bus_data, sizeof(struct iproc_mdiobus_data)); -+ bus_priv->hw_ctrl = ccb_ctrl; -+ -+ ret = mdiobus_register(mii_bus); -+ if (ret) { -+ dev_err(&pdev->dev, "mdiobus_register failed\n"); -+ goto err_exit; -+ } -+ -+ platform_set_drvdata(pdev, mii_bus); -+ -+ /* ccb_mdiobus_test(mii_bus); */ -+ -+ return 0; -+ -+err_exit: -+ kfree(mii_bus); -+ return ret; -+} -+ -+int ccb_mii_remove(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus = platform_get_drvdata(pdev); -+ struct ccb_mdiobus_private *bus_priv; -+ -+ if (mii_bus) { -+ bus_priv = mii_bus->priv; -+ -+ mdiobus_unregister(mii_bus); -+ if (bus_priv) { -+ ccb_mdio_res_free(bus_priv->hw_ctrl); -+ } -+ mdiobus_free(mii_bus); -+ } -+ -+ return 0; -+} -+ -+ -+static const struct of_device_id bcm_iproc_dt_ids[] = { -+ { .compatible = "brcm,iproc-ccb-mdio"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_dt_ids); -+ -+static struct platform_driver iproc_ccb_mdiobus_driver = { -+ .probe = ccb_mii_probe, -+ .remove = ccb_mii_remove, -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(bcm_iproc_dt_ids), -+ }, -+}; -+/*module_platform_driver(iproc_ccb_mdiobus_driver);*/ -+ -+#else /* CONFIG_OF_MDIO */ -+ -+static int __devinit ccb_mdiobus_probe(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus; -+ struct ccb_mdiobus_private *bus_priv; -+ struct iproc_mdiobus_data *bus_data = pdev->dev.platform_data; -+ struct ccb_mdio_ctrl *ccb_ctrl; -+ int ret; -+ -+ /* Get register base address */ -+ ccb_ctrl = ccb_mdio_res_alloc(); -+ if (!ccb_ctrl) { -+ printk(KERN_ERR "ccb mdio res alloc failed\n"); -+ ret = -ENOMEM; -+ goto error_exit; -+ } -+ -+ ccb_mii_init(ccb_ctrl); -+ -+ mii_bus = mdiobus_alloc_size(sizeof(*bus_priv)); -+ if (!mii_bus) { -+ dev_err(&pdev->dev, "mdiobus alloc filed\n"); -+ ret = -ENOMEM; -+ goto error_free_ctrl; -+ } -+ -+ mii_bus->name = "iproc_ccb_mdiobus"; -+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, IPROC_MDIO_ID_FMT, -+ bus_data->logbus_num, bus_data->logbus_type); -+ mii_bus->parent = &pdev->dev; -+ mii_bus->read = ccb_mdiobus_read; -+ mii_bus->write = ccb_mdiobus_write; -+ -+ bus_priv = mii_bus->priv; -+ memcpy(&bus_priv->bus_data, bus_data, sizeof(struct iproc_mdiobus_data)); -+ bus_priv->hw_ctrl = ccb_ctrl; -+ -+ ret = mdiobus_register(mii_bus); -+ if (ret) { -+ dev_err(&pdev->dev, "mdiobus_register failed\n"); -+ goto error_free_bus; -+ } -+ -+ platform_set_drvdata(pdev, mii_bus); -+ -+ return 0; -+ -+error_free_bus: -+ kfree(mii_bus); -+error_free_ctrl: -+ ccb_mdio_res_free(ccb_ctrl); -+error_exit: -+ return ret; -+} -+ -+static int __devexit ccb_mdiobus_remove(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus = platform_get_drvdata(pdev); -+ struct ccb_mdiobus_private *bus_priv; -+ -+ if (mii_bus) { -+ bus_priv = mii_bus->priv; -+ -+ mdiobus_unregister(mii_bus); -+ if (bus_priv) { -+ ccb_mdio_res_free(bus_priv->hw_ctrl); -+ } -+ mdiobus_free(mii_bus); -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver iproc_ccb_mdiobus_driver = -+{ -+ .driver = { -+ .name = "iproc_ccb_mdio", -+ .owner = THIS_MODULE, -+ }, -+ .probe = ccb_mdiobus_probe, -+ .remove = ccb_mdiobus_remove, -+}; -+#endif /* CONFIG_OF_MDIO */ -+ -+int -+ccb_mdio_init(void) -+{ -+ int ret = -ENODEV; -+ dev_t mdio_dev; -+ mdio_info_t *mdio = NULL; -+ -+ ret = _mdio_handler_init(); -+ if(ret != 0) { -+ ret = -ENOMEM; -+ goto error_exit; -+ } -+ -+ mdio = mdio_devices.mdio; -+ -+ if (mdio_major) { -+ mdio_dev = MKDEV(mdio_major, 0); -+ ret = register_chrdev_region(mdio_dev, 1, "mdio"); -+ } else { -+ ret = alloc_chrdev_region(&mdio_dev, 0, 1, "mdio"); -+ mdio_major = MAJOR(mdio_dev); -+ } -+ if (ret) { -+ goto error_exit; -+ } -+ -+ cdev_init(&mdio_cdev, &mdio_fops); -+ ret = cdev_add(&mdio_cdev, mdio_dev, 1); -+ if (ret) { -+ printk(KERN_ERR "Fail to add mdio char dev!\n"); -+ goto error_region; -+ } -+ -+ platform_driver_register(&iproc_ccb_mdiobus_driver); -+ -+ return 0; -+ -+error_region: -+ unregister_chrdev_region(mdio_dev, 1); -+error_exit: -+ kfree(mdio); -+ return ret; -+} -+ -+void -+ccb_mdio_exit(void) -+{ -+ mdio_info_t *mdio = NULL; -+ -+ mdio = mdio_devices.mdio; -+ kfree(mdio); -+ -+ mdio_devices.mdio = NULL; -+ mdio_devices.init = 0; -+ unregister_chrdev_region(MKDEV(mdio_major, 0), 1); -+ -+ platform_driver_unregister(&iproc_ccb_mdiobus_driver); -+} -+ -+ -+//module_init(ccb_mdio_init); -+subsys_initcall(ccb_mdio_init); -+module_exit(ccb_mdio_exit); -+ -+ -+EXPORT_SYMBOL(ccb_mii_init); -+EXPORT_SYMBOL(ccb_mii_freq_set); -+EXPORT_SYMBOL(ccb_mii_read); -+EXPORT_SYMBOL(ccb_mii_write); -+ -+MODULE_AUTHOR("Broadcom"); -+MODULE_DESCRIPTION("BCM5301X MDIO Device Driver"); -+MODULE_LICENSE("GPL"); -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/ccg_mdio.c b/drivers/net/ethernet/broadcom/mdio/ccg_mdio.c ---- a/drivers/net/ethernet/broadcom/mdio/ccg_mdio.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/ccg_mdio.c 2017-11-09 17:53:44.080295000 +0800 -@@ -0,0 +1,488 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iproc_mdio.h" -+ -+#include -+#include -+#include -+#include -+ -+static struct iproc_mdiobus_data iproc_mdiobus_data; -+/*#define CCG_MDIO_BASE_ADDRESS IPROC_MII_MGMT_CTL*/ -+ -+#define MGMT_CTL_REG 0x000 -+#define MGMT_CTL__BYP_SHIFT 10 -+#define MGMT_CTL__BYP_WIDTH 1 -+#define MGMT_CTL__BYP_MASK ((1 << MGMT_CTL__BYP_WIDTH) - 1) -+#define MGMT_CTL__EXT_SHIFT 9 -+#define MGMT_CTL__EXT_WIDTH 1 -+#define MGMT_CTL__EXT_MASK ((1 << MGMT_CTL__EXT_WIDTH) - 1) -+#define MGMT_CTL__BSY_SHIFT 8 -+#define MGMT_CTL__BSY_WIDTH 1 -+#define MGMT_CTL__BSY_MASK ((1 << MGMT_CTL__BSY_WIDTH) - 1) -+#define MGMT_CTL__PRE_SHIFT 7 -+#define MGMT_CTL__PRE_WIDTH 1 -+#define MGMT_CTL__PRE_MASK ((1 << MGMT_CTL__BSY_WIDTH) - 1) -+#define MGMT_CTL__MDCDIV_SHIFT 0 -+#define MGMT_CTL__MDCDIV_WIDTH 7 -+#define MGMT_CTL__MDCDIV_MASK ((1 << MGMT_CTL__MDCDIV_WIDTH) - 1) -+ -+#define MGMT_CMD_DATA_REG 0x004 -+#define MGMT_CMD_DATA__SB_SHIFT 30 -+#define MGMT_CMD_DATA__SB_WIDTH 2 -+#define MGMT_CMD_DATA__SB_MASK ((1 << MGMT_CMD_DATA__SB_WIDTH) - 1) -+#define MGMT_CMD_DATA__OP_SHIFT 28 -+#define MGMT_CMD_DATA__OP_WIDTH 2 -+#define MGMT_CMD_DATA__OP_MASK ((1 << MGMT_CMD_DATA__OP_WIDTH) - 1) -+#define MGMT_CMD_DATA__PA_SHIFT 23 -+#define MGMT_CMD_DATA__PA_WIDTH 5 -+#define MGMT_CMD_DATA__PA_MASK ((1 << MGMT_CMD_DATA__PA_WIDTH) - 1) -+#define MGMT_CMD_DATA__RA_SHIFT 18 -+#define MGMT_CMD_DATA__RA_WIDTH 5 -+#define MGMT_CMD_DATA__RA_MASK ((1 << MGMT_CMD_DATA__RA_WIDTH) - 1) -+#define MGMT_CMD_DATA__TA_SHIFT 16 -+#define MGMT_CMD_DATA__TA_WIDTH 2 -+#define MGMT_CMD_DATA__TA_MASK ((1 << MGMT_CMD_DATA__TA_WIDTH) - 1) -+#define MGMT_CMD_DATA__DATA_SHIFT 0 -+#define MGMT_CMD_DATA__DATA_WIDTH 16 -+#define MGMT_CMD_DATA__DATA_MASK ((1 << MGMT_CMD_DATA__DATA_WIDTH) - 1) -+ -+ -+#define SET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ -+ (reg_value) = ((reg_value) & ~((fmask) << (fshift))) | \ -+ (((fvalue) & (fmask)) << (fshift)) -+#define ISET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ -+ (reg_value) = (reg_value) | (((fvalue) & (fmask)) << (fshift)) -+#define GET_REG_FIELD(reg_value, fshift, fmask) \ -+ (((reg_value) & ((fmask) << (fshift))) >> (fshift)) -+ -+#define MII_OP_MAX_HALT_USEC 500 -+#define MII_OP_HALT_USEC 10 -+ -+enum { -+ MII_OP_MODE_READ, -+ MII_OP_MODE_WRITE, -+ MII_OP_MODE_MAX -+}; -+ -+/** -+ * struct cmicd_mdio: cmicd mdio structure -+ * @resource: resource of cmicd cmc2 -+ * @base: base address of cmicd cmc2 -+ * @lock: spin lock protecting io access -+ */ -+struct ccg_mdio_ctrl { -+ void __iomem *base; -+ /* Use spinlock to co-operate that the caller might be in interrupt context */ -+ /* struct mutex lock; */ -+ spinlock_t lock; -+ int ref_cnt; -+}; -+ -+struct ccg_mdiobus_private { -+ /* iproc_mdiobus_data field have to be placed at the beginning of -+ * mdiobus private data */ -+ struct iproc_mdiobus_data bus_data; -+ struct ccg_mdio_ctrl *hw_ctrl; -+}; -+ -+struct ccg_mii_cmd { -+ int bus_id; -+ int ext_sel; -+ int phy_id; -+ int regnum; -+ u16 op_mode; -+ u16 val; -+}; -+ -+static struct ccg_mdio_ctrl *ccg_mdio = NULL; -+static uint32_t ccg_mdio_clk_rate; -+ -+ -+static void __maybe_unused ccg_mdiobus_test(struct mii_bus *mii_bus) -+{ -+ int i; -+ u16 data1 = 0, data2 = 0; -+ struct phy_device *phy_dev; -+ struct ccg_mdiobus_private *bus_priv = mii_bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ -+ dev_info(mii_bus->parent, "%s : %s phy bus num[%d], type[%d]\n", -+ __func__, mii_bus->id, bus_data->phybus_num, bus_data->phybus_type); -+ -+ /* Check if mdiobus_read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ phy_dev = mii_bus->phy_map[i]; -+ if (phy_dev) -+ dev_info(mii_bus->parent, "phy[%d] id=0x%08x, addr = %d\n", -+ i, phy_dev->phy_id, phy_dev->addr); -+ } -+ -+ /* Check if general interface function for mdiobus read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ data1 = mii_bus->read(mii_bus, i, 2); -+ data2 = mii_bus->read(mii_bus, i, 3); -+ if ((data1 < 0) || (data2 < 0)) { -+ dev_info(mii_bus->parent, -+ "iproc_mdiobus_read failed!, %s phy bus num[%d], type[%d], phyaddr = %d, nRet1 = %d, nRet2 = %d\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } else { -+ dev_info(mii_bus->parent, -+ "read %s phy bus num[%d] type[%d] phyaddr[%d], reg2 = 0x%x, reg3 = 0x%x\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } -+ } -+ -+} -+ -+static inline u32 ccg_mii_reg_read(struct ccg_mdio_ctrl *ccg_mii, u32 reg) -+{ -+ return readl(ccg_mii->base + reg); -+} -+ -+static inline void ccg_mii_reg_write(struct ccg_mdio_ctrl *ccg_mii, u32 reg, u32 data) -+{ -+ writel(data, ccg_mii->base + reg); -+} -+ -+static inline int ccg_mii_busy(struct ccg_mdio_ctrl *ccg_mii, int to_usec) -+{ -+ do { -+ if(!GET_REG_FIELD(ccg_mii_reg_read(ccg_mii, MGMT_CTL_REG), -+ MGMT_CTL__BSY_SHIFT, MGMT_CTL__BSY_MASK)) -+ return 0; -+ udelay(MII_OP_HALT_USEC); -+ to_usec -= MII_OP_HALT_USEC; -+ } while (to_usec > 0); -+ -+ return 1; -+} -+ -+static int do_ccg_mii_op(struct ccg_mdio_ctrl *ccg_mii, struct ccg_mii_cmd *cmd) -+{ -+ u32 cmd_data = 0, mgt_ctrl; -+ unsigned long flags; -+ int ret = 0; -+ -+ if (MII_OP_MODE_WRITE == cmd->op_mode) { -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__OP_SHIFT, -+ MGMT_CMD_DATA__OP_MASK, 1); -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__DATA_SHIFT, -+ MGMT_CMD_DATA__DATA_MASK, cmd->val); -+ } -+ else if (MII_OP_MODE_READ == cmd->op_mode) { -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__OP_SHIFT, -+ MGMT_CMD_DATA__OP_MASK, 2); -+ } -+ else { -+ printk(KERN_ERR "%s : invald operation %d\n", __func__, cmd->op_mode); -+ return -EINVAL; -+ } -+ -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__PA_SHIFT, -+ MGMT_CMD_DATA__PA_MASK, cmd->phy_id); -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__RA_SHIFT, -+ MGMT_CMD_DATA__RA_MASK, cmd->regnum); -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__TA_SHIFT, -+ MGMT_CMD_DATA__TA_MASK, 2); -+ ISET_REG_FIELD(cmd_data, MGMT_CMD_DATA__SB_SHIFT, -+ MGMT_CMD_DATA__SB_MASK, 1); -+ -+ /* mutex_lock(&ccg_mii->lock); */ -+ spin_lock_irqsave(&ccg_mii->lock, flags); -+ -+ if (ccg_mii_busy(ccg_mii, MII_OP_MAX_HALT_USEC)) { -+ ret = -EBUSY; -+ printk(KERN_ERR "%s : bus busy (1)\n", __func__); -+ goto err_exit_unlock; -+ } -+ -+ mgt_ctrl = ccg_mii_reg_read(ccg_mii, MGMT_CTL_REG); -+ if (cmd->ext_sel != GET_REG_FIELD(mgt_ctrl, MGMT_CTL__EXT_SHIFT, -+ MGMT_CTL__EXT_MASK)) { -+ SET_REG_FIELD(mgt_ctrl, MGMT_CTL__EXT_SHIFT, MGMT_CTL__EXT_MASK, cmd->ext_sel); -+ ccg_mii_reg_write(ccg_mii, MGMT_CTL_REG, mgt_ctrl); -+ } -+ -+ ccg_mii_reg_write(ccg_mii, MGMT_CMD_DATA_REG, cmd_data); -+ -+ if (ccg_mii_busy(ccg_mii, MII_OP_MAX_HALT_USEC)) { -+ ret = -EBUSY; -+ printk(KERN_ERR "%s : bus busy (2)\n", __func__); -+ goto err_exit_unlock; -+ } -+ -+ if (MII_OP_MODE_READ == cmd->op_mode) { -+ ret = GET_REG_FIELD(ccg_mii_reg_read(ccg_mii, MGMT_CMD_DATA_REG), -+ MGMT_CMD_DATA__DATA_SHIFT, MGMT_CMD_DATA__DATA_MASK); -+ } -+ -+ /* mutex_unlock(&ccg_mii->lock); */ -+ spin_unlock_irqrestore(&ccg_mii->lock, flags); -+ -+ return ret; -+ -+err_exit_unlock: -+ /* mutex_unlock(&ccg_mii->lock); */ -+ spin_unlock_irqrestore(&ccg_mii->lock, flags); -+ return ret; -+} -+ -+static int ccg_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) -+{ -+ struct ccg_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ struct ccg_mii_cmd cmd = {0}; -+ -+ cmd.bus_id = bus_data->phybus_num; -+ if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) -+ cmd.ext_sel = 1; -+ cmd.phy_id = phy_id; -+ cmd.regnum = regnum; -+ cmd.op_mode = MII_OP_MODE_READ; -+ -+ return do_ccg_mii_op(bus_priv->hw_ctrl, &cmd); -+} -+ -+static int ccg_mdiobus_write(struct mii_bus *bus, int phy_id, -+ int regnum, u16 val) -+{ -+ struct ccg_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ struct ccg_mii_cmd cmd = {0}; -+ -+ cmd.bus_id = bus_data->phybus_num; -+ if (IPROC_MDIOBUS_TYPE_EXTERNAL == bus_data->phybus_type) -+ cmd.ext_sel = 1; -+ cmd.phy_id = phy_id; -+ cmd.regnum = regnum; -+ cmd.op_mode = MII_OP_MODE_WRITE; -+ cmd.val = val; -+ -+ return do_ccg_mii_op(bus_priv->hw_ctrl, &cmd); -+} -+ -+static struct ccg_mdio_ctrl * ccg_mdio_res_alloc(void) -+{ -+ if (!ccg_mdio) { -+ ccg_mdio = kzalloc(sizeof(*ccg_mdio), GFP_KERNEL); -+ if (!ccg_mdio) -+ return NULL; -+ -+ /* mutex_init(&ccg_mdio->lock); */ -+ spin_lock_init(&ccg_mdio->lock); -+ ccg_mdio->ref_cnt = 1; -+ } -+ else -+ ccg_mdio->ref_cnt ++; -+ -+ return ccg_mdio; -+} -+ -+static void ccg_mdio_res_free(struct ccg_mdio_ctrl *ctrl) -+{ -+ if (ctrl) { -+ ctrl->ref_cnt --; -+ if (ctrl->ref_cnt == 0) { -+ iounmap(ctrl->base); -+ kfree(ctrl); -+ ccg_mdio = NULL; -+ } -+ } -+} -+ -+static void ccg_mii_init(struct ccg_mdio_ctrl *ccg_mii) -+{ -+ u32 clk_rate, val = 0; -+ -+ if(ccg_mii->ref_cnt == 1) { -+ /* Set preamble enabled */ -+ ISET_REG_FIELD(val, MGMT_CTL__PRE_SHIFT, MGMT_CTL__PRE_MASK, 1); -+ -+ clk_rate = ccg_mdio_clk_rate; -+ -+ /* -+ * MII Mgt Clock (MDC) Divisor. 0x0: Disable output of the MDC -+ * Non-zero: Output the MDC with a frequency that is -+ * PCLK/(2* the value of this field). -+ */ -+ ISET_REG_FIELD(val, MGMT_CTL__MDCDIV_SHIFT, MGMT_CTL__MDCDIV_MASK, -+ clk_rate/(1000000)); /* Set the MII default clock to 1MHz: */ -+ -+ ccg_mii_reg_write(ccg_mii, MGMT_CTL_REG, val); -+ } -+} -+ -+static int ccg_mdiobus_probe(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus; -+ struct device_node *dn = pdev->dev.of_node; -+ struct ccg_mdiobus_private *bus_priv; -+ struct iproc_mdiobus_data *bus_data; -+ struct ccg_mdio_ctrl *ccg_ctrl; -+ u32 mdio_bus_id; -+ const char *mdio_bus_type; -+ struct clk *clk=NULL; -+ int ret; -+ -+ if (!of_device_is_available(dn)) -+ return -ENODEV; -+ -+ ccg_ctrl = ccg_mdio_res_alloc(); -+ if (!ccg_ctrl) { -+ dev_err(&pdev->dev, "ccg mdio res alloc failed\n"); -+ ret = -ENOMEM; -+ goto err_exit; -+ } -+ -+ /* Get register base address */ -+ ccg_ctrl->base = (void *)of_iomap(dn, 0); -+ -+ clk = of_clk_get (dn, 0); -+ if (clk) -+ ccg_mdio_clk_rate = clk_get_rate(clk)/2; /* used by ccg_mii_init */ -+ else { -+ printk("No CCG MDIO Clock available from DT, use default clock rate: 50MHz\n"); -+ ccg_mdio_clk_rate = 50000000; -+ } -+ -+ ccg_mii_init(ccg_ctrl); -+ -+ if (of_property_read_u32(dn, "#bus-id", &mdio_bus_id)) -+ mdio_bus_id = 0; /* default: 0 */ -+ -+ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) -+ mdio_bus_type = "internal"; /* default: "internal" */ -+ -+ iproc_mdiobus_data.phybus_num = (u8) mdio_bus_id; -+ if (!strcmp(mdio_bus_type, "internal")) -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; -+ else -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; -+ -+ /* Note: this applies to CCB/CCG MDIO, but not for CMICD MDIO */ -+ iproc_mdiobus_data.logbus_num = iproc_mdiobus_data.phybus_num; -+ iproc_mdiobus_data.logbus_type = iproc_mdiobus_data.phybus_type; -+ -+ bus_data = &iproc_mdiobus_data; -+ -+ mii_bus = mdiobus_alloc_size(sizeof(*bus_priv)); -+ if (!mii_bus) { -+ dev_err(&pdev->dev, "mdiobus alloc filed\n"); -+ ret = -ENOMEM; -+ goto err_free_ctrl; -+ } -+ -+ mii_bus->name = "iproc_ccg_mdiobus"; -+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, IPROC_MDIO_ID_FMT, -+ bus_data->logbus_num, bus_data->logbus_type); -+ mii_bus->parent = &pdev->dev; -+ mii_bus->read = ccg_mdiobus_read; -+ mii_bus->write = ccg_mdiobus_write; -+ -+ bus_priv = mii_bus->priv; -+ memcpy(&bus_priv->bus_data, bus_data, sizeof(struct iproc_mdiobus_data)); -+ bus_priv->hw_ctrl = ccg_ctrl; -+ -+ if (IS_ENABLED(CONFIG_MACH_GH2) || IS_ENABLED(CONFIG_MACH_WH2)) -+ ret = of_mdiobus_register(mii_bus, dn); -+ else -+ ret = mdiobus_register(mii_bus); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "mdiobus_register failed\n"); -+ goto err_free_bus; -+ } -+ -+ platform_set_drvdata(pdev, mii_bus); -+ -+#if 0 -+ ccg_mdiobus_test(mii_bus); -+#endif -+ -+ return 0; -+ -+err_free_bus: -+ kfree(mii_bus); -+err_free_ctrl: -+ ccg_mdio_res_free(ccg_ctrl); -+err_exit: -+ return ret; -+} -+ -+static int ccg_mdiobus_remove(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus = platform_get_drvdata(pdev); -+ struct ccg_mdiobus_private *bus_priv; -+ -+ if (mii_bus) { -+ bus_priv = mii_bus->priv; -+ -+ mdiobus_unregister(mii_bus); -+ if (bus_priv) -+ ccg_mdio_res_free(bus_priv->hw_ctrl); -+ mdiobus_free(mii_bus); -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm_iproc_dt_ids[] = { -+ { .compatible = "brcm,iproc-ccg-mdio"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_dt_ids); -+ -+ -+static struct platform_driver iproc_ccg_mdiobus_driver = -+{ -+ .driver = { -+ .name = "iproc_ccg_mdio", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(bcm_iproc_dt_ids), -+ }, -+ .probe = ccg_mdiobus_probe, -+ .remove = ccg_mdiobus_remove, -+}; -+ -+static int __init ccg_mdio_init(void) -+{ -+ return platform_driver_register(&iproc_ccg_mdiobus_driver); -+} -+ -+static void __exit ccg_mdio_exit(void) -+{ -+ platform_driver_unregister(&iproc_ccg_mdiobus_driver); -+} -+ -+//module_init(ccg_mdio_init); -+subsys_initcall(ccg_mdio_init); -+module_exit(ccg_mdio_exit); -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("iProc CCG mdio driver"); -+MODULE_LICENSE("GPL"); -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/cmicd_mdio.c b/drivers/net/ethernet/broadcom/mdio/cmicd_mdio.c ---- a/drivers/net/ethernet/broadcom/mdio/cmicd_mdio.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/cmicd_mdio.c 2017-11-09 17:53:44.081297000 +0800 -@@ -0,0 +1,606 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iproc_mdio.h" -+ -+#include -+#include -+#include -+#include -+ -+static struct iproc_mdiobus_data iproc_mdiobus_data; -+ -+/* CMICD MDIO */ -+#define CMIC_COMMON_MIIM_PARAM_OFFSET 0x080 -+#define CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_L 31 -+#define CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_R 29 -+#define CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_WIDTH 3 -+#define CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_PARAM__INTERNAL_SEL 25 -+#define CMIC_COMMON_MIIM_PARAM__INTERNAL_SEL_WIDTH 1 -+#define CMIC_COMMON_MIIM_PARAM__INTERNAL_SEL_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_PARAM__BUS_ID_L 24 -+#define CMIC_COMMON_MIIM_PARAM__BUS_ID_R 22 -+#define CMIC_COMMON_MIIM_PARAM__BUS_ID_WIDTH 3 -+#define CMIC_COMMON_MIIM_PARAM__BUS_ID_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_PARAM__C45_SEL 21 -+#define CMIC_COMMON_MIIM_PARAM__C45_SEL_WIDTH 1 -+#define CMIC_COMMON_MIIM_PARAM__C45_SEL_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_PARAM__PHY_ID_L 20 -+#define CMIC_COMMON_MIIM_PARAM__PHY_ID_R 16 -+#define CMIC_COMMON_MIIM_PARAM__PHY_ID_WIDTH 5 -+#define CMIC_COMMON_MIIM_PARAM__PHY_ID_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_PARAM__PHY_DATA_L 15 -+#define CMIC_COMMON_MIIM_PARAM__PHY_DATA_R 0 -+#define CMIC_COMMON_MIIM_PARAM__PHY_DATA_WIDTH 16 -+#define CMIC_COMMON_MIIM_PARAM__PHY_DATA_RESETVALUE 0x0000 -+#define CMIC_COMMON_MIIM_PARAM__RESERVED_L 28 -+#define CMIC_COMMON_MIIM_PARAM__RESERVED_R 26 -+#define CMIC_COMMON_MIIM_PARAM_WIDTH 32 -+#define CMIC_COMMON_MIIM_PARAM__WIDTH 32 -+#define CMIC_COMMON_MIIM_PARAM_ALL_L 31 -+#define CMIC_COMMON_MIIM_PARAM_ALL_R 0 -+#define CMIC_COMMON_MIIM_PARAM__ALL_L 31 -+#define CMIC_COMMON_MIIM_PARAM__ALL_R 0 -+#define CMIC_COMMON_MIIM_PARAM_DATAMASK 0xe3ffffff -+#define CMIC_COMMON_MIIM_PARAM_RDWRMASK 0x1c000000 -+#define CMIC_COMMON_MIIM_PARAM_RESETVALUE 0x0 -+ -+#define CMIC_COMMON_MIIM_READ_DATA_OFFSET 0x084 -+#define CMIC_COMMON_MIIM_READ_DATA__DATA_L 15 -+#define CMIC_COMMON_MIIM_READ_DATA__DATA_R 0 -+#define CMIC_COMMON_MIIM_READ_DATA__DATA_WIDTH 16 -+#define CMIC_COMMON_MIIM_READ_DATA__DATA_RESETVALUE 0x0000 -+#define CMIC_COMMON_MIIM_READ_DATA__RESERVED_L 31 -+#define CMIC_COMMON_MIIM_READ_DATA__RESERVED_R 16 -+#define CMIC_COMMON_MIIM_READ_DATA_WIDTH 16 -+#define CMIC_COMMON_MIIM_READ_DATA__WIDTH 16 -+#define CMIC_COMMON_MIIM_READ_DATA_ALL_L 15 -+#define CMIC_COMMON_MIIM_READ_DATA_ALL_R 0 -+#define CMIC_COMMON_MIIM_READ_DATA__ALL_L 15 -+#define CMIC_COMMON_MIIM_READ_DATA__ALL_R 0 -+#define CMIC_COMMON_MIIM_READ_DATA_DATAMASK 0x0000ffff -+#define CMIC_COMMON_MIIM_READ_DATA_RDWRMASK 0xffff0000 -+#define CMIC_COMMON_MIIM_READ_DATA_RESETVALUE 0x0 -+ -+#define CMIC_COMMON_MIIM_ADDRESS_OFFSET 0x088 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_L 20 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_R 16 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_WIDTH 5 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_L 15 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_R 0 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_WIDTH 16 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_RESETVALUE 0x0000 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_L 4 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_R 0 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_WIDTH 5 -+#define CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_ADDRESS__RESERVED_L 31 -+#define CMIC_COMMON_MIIM_ADDRESS__RESERVED_R 21 -+#define CMIC_COMMON_MIIM_ADDRESS_WIDTH 21 -+#define CMIC_COMMON_MIIM_ADDRESS__WIDTH 21 -+#define CMIC_COMMON_MIIM_ADDRESS_ALL_L 20 -+#define CMIC_COMMON_MIIM_ADDRESS_ALL_R 0 -+#define CMIC_COMMON_MIIM_ADDRESS__ALL_L 20 -+#define CMIC_COMMON_MIIM_ADDRESS__ALL_R 0 -+#define CMIC_COMMON_MIIM_ADDRESS_DATAMASK 0x001fffff -+#define CMIC_COMMON_MIIM_ADDRESS_RDWRMASK 0xffe00000 -+#define CMIC_COMMON_MIIM_ADDRESS_RESETVALUE 0x0 -+ -+#define CMIC_COMMON_MIIM_CTRL_OFFSET 0x08c -+#define CMIC_COMMON_MIIM_CTRL__MIIM_RD_START 1 -+#define CMIC_COMMON_MIIM_CTRL__MIIM_RD_START_WIDTH 1 -+#define CMIC_COMMON_MIIM_CTRL__MIIM_RD_START_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_CTRL__MIIM_WR_START 0 -+#define CMIC_COMMON_MIIM_CTRL__MIIM_WR_START_WIDTH 1 -+#define CMIC_COMMON_MIIM_CTRL__MIIM_WR_START_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_CTRL__RESERVED_L 31 -+#define CMIC_COMMON_MIIM_CTRL__RESERVED_R 2 -+#define CMIC_COMMON_MIIM_CTRL_WIDTH 2 -+#define CMIC_COMMON_MIIM_CTRL__WIDTH 2 -+#define CMIC_COMMON_MIIM_CTRL_ALL_L 1 -+#define CMIC_COMMON_MIIM_CTRL_ALL_R 0 -+#define CMIC_COMMON_MIIM_CTRL__ALL_L 1 -+#define CMIC_COMMON_MIIM_CTRL__ALL_R 0 -+#define CMIC_COMMON_MIIM_CTRL_DATAMASK 0x00000003 -+#define CMIC_COMMON_MIIM_CTRL_RDWRMASK 0xfffffffc -+#define CMIC_COMMON_MIIM_CTRL_RESETVALUE 0x0 -+ -+#define CMIC_COMMON_MIIM_STAT_OFFSET 0x090 -+#define CMIC_COMMON_MIIM_STAT__MIIM_OPN_DONE 0 -+#define CMIC_COMMON_MIIM_STAT__MIIM_OPN_DONE_WIDTH 1 -+#define CMIC_COMMON_MIIM_STAT__MIIM_OPN_DONE_RESETVALUE 0x0 -+#define CMIC_COMMON_MIIM_STAT__RESERVED_L 31 -+#define CMIC_COMMON_MIIM_STAT__RESERVED_R 1 -+#define CMIC_COMMON_MIIM_STAT_WIDTH 1 -+#define CMIC_COMMON_MIIM_STAT__WIDTH 1 -+#define CMIC_COMMON_MIIM_STAT_ALL_L 0 -+#define CMIC_COMMON_MIIM_STAT_ALL_R 0 -+#define CMIC_COMMON_MIIM_STAT__ALL_L 0 -+#define CMIC_COMMON_MIIM_STAT__ALL_R 0 -+#define CMIC_COMMON_MIIM_STAT_DATAMASK 0x00000001 -+#define CMIC_COMMON_MIIM_STAT_RDWRMASK 0xfffffffe -+#define CMIC_COMMON_MIIM_STAT_RESETVALUE 0x0 -+ -+#define CMIC_COMMON_UC0_PIO_ENDIANESS 0x1F0 -+ -+#define MIIM_PARAM_REG CMIC_COMMON_MIIM_PARAM_OFFSET -+#define MIIM_PARAM__MIIM_CYCLE_SHIFT CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_R -+#define MIIM_PARAM__MIIM_CYCLE_MASK ((1 << CMIC_COMMON_MIIM_PARAM__MIIM_CYCLE_WIDTH) - 1) -+#define MIIM_PARAM__INTERNAL_SEL_SHIFT CMIC_COMMON_MIIM_PARAM__INTERNAL_SEL -+#define MIIM_PARAM__INTERNAL_SEL_MASK ((1 << CMIC_COMMON_MIIM_PARAM__INTERNAL_SEL_WIDTH) - 1) -+#define MIIM_PARAM__BUS_ID_SHIFT CMIC_COMMON_MIIM_PARAM__BUS_ID_R -+#define MIIM_PARAM__BUS_ID_MASK ((1 << CMIC_COMMON_MIIM_PARAM__BUS_ID_WIDTH) - 1) -+#define MIIM_PARAM__C45_SEL_SHIFT CMIC_COMMON_MIIM_PARAM__C45_SEL -+#define MIIM_PARAM__C45_SEL_MASK ((1 << CMIC_COMMON_MIIM_PARAM__C45_SEL_WIDTH) - 1) -+#define MIIM_PARAM__PHY_ID_SHIFT CMIC_COMMON_MIIM_PARAM__PHY_ID_R -+#define MIIM_PARAM__PHY_ID_MASK ((1 << CMIC_COMMON_MIIM_PARAM__PHY_ID_WIDTH) - 1) -+#define MIIM_PARAM__PHY_DATA_SHIFT CMIC_COMMON_MIIM_PARAM__PHY_DATA_R -+#define MIIM_PARAM__PHY_DATA_MASK ((1 << CMIC_COMMON_MIIM_PARAM__PHY_DATA_WIDTH) - 1) -+ -+#define MIIM_READ_DATA_REG CMIC_COMMON_MIIM_READ_DATA_OFFSET -+#define MIIM_READ_DATA__DATA_SHIFT CMIC_COMMON_MIIM_READ_DATA__DATA_R -+#define MIIM_READ_DATA__DATA_MASK ((1 << CMIC_COMMON_MIIM_READ_DATA__DATA_WIDTH) - 1) -+ -+#define MIIM_ADDRESS_REG CMIC_COMMON_MIIM_ADDRESS_OFFSET -+#define MIIM_ADDRESS__CLAUSE_45_DTYPE_SHIFT CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_R -+#define MIIM_ADDRESS__CLAUSE_45_DTYPE_MASK ((1 << CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_DTYPE_WIDTH) - 1) -+#define MIIM_ADDRESS__CLAUSE_45_REGADR_SHIFT CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_R -+#define MIIM_ADDRESS__CLAUSE_45_REGADR_MASK ((1 << CMIC_COMMON_MIIM_ADDRESS__CLAUSE_45_REGADR_WIDTH) - 1) -+#define MIIM_ADDRESS__CLAUSE_22_REGADR_SHIFT CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_R -+#define MIIM_ADDRESS__CLAUSE_22_REGADR_MASK ((1 << CMIC_COMMON_MIIM_ADDRESS__CLAUSE_22_REGADR_WIDTH) - 1) -+ -+#define MIIM_CTRL_REG CMIC_COMMON_MIIM_CTRL_OFFSET -+#define MIIM_CTRL__MIIM_RD_START_SHIFT CMIC_COMMON_MIIM_CTRL__MIIM_RD_START -+#define MIIM_CTRL__MIIM_RD_START_MASK ((1 << CMIC_COMMON_MIIM_CTRL__MIIM_RD_START_WIDTH) - 1) -+#define MIIM_CTRL__MIIM_WR_START_SHIFT CMIC_COMMON_MIIM_CTRL__MIIM_WR_START -+#define MIIM_CTRL__MIIM_WR_START_MASK ((1 << CMIC_COMMON_MIIM_CTRL__MIIM_WR_START_WIDTH) - 1) -+ -+#define MIIM_STAT_REG CMIC_COMMON_MIIM_STAT_OFFSET -+#define MIIM_STAT__MIIM_OPN_DONE_SHIFT CMIC_COMMON_MIIM_STAT__MIIM_OPN_DONE -+#define MIIM_STAT__MIIM_OPN_DONE_MASK ((1 << CMIC_COMMON_MIIM_STAT__MIIM_OPN_DONE_WIDTH) - 1) -+ -+#define SET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ -+ (reg_value) = ((reg_value) & ~((fmask) << (fshift))) | \ -+ (((fvalue) & (fmask)) << (fshift)) -+#define ISET_REG_FIELD(reg_value, fshift, fmask, fvalue) \ -+ (reg_value) = (reg_value) | (((fvalue) & (fmask)) << (fshift)) -+#define GET_REG_FIELD(reg_value, fshift, fmask) \ -+ (((reg_value) & ((fmask) << (fshift))) >> (fshift)) -+ -+#define MIIM_OP_MAX_HALT_USEC 500 -+ -+enum { -+ MIIM_OP_MODE_READ, -+ MIIM_OP_MODE_WRITE, -+ MIIM_OP_MODE_MAX -+}; -+ -+/** -+ * struct cmicd_mdio: cmicd mdio structure -+ * @base: base address of cmic_common -+ * @lock: spin lock protecting io access -+ */ -+struct cmicd_mdio_ctrl { -+ void __iomem *base; -+ /* Use spinlock to co-operate that the caller might be in interrupt context */ -+ /* struct mutex lock; */ -+ spinlock_t lock; -+ int ref_cnt; -+}; -+ -+struct cmicd_mdiobus_private { -+ /* iproc_mdiobus_data field have to be placed at the beginning of -+ * mdiobus private data */ -+ struct iproc_mdiobus_data bus_data; -+ struct cmicd_mdio_ctrl *hw_ctrl; -+}; -+ -+struct cmicd_miim_cmd { -+ int bus_id; -+ int int_sel; -+ int phy_id; -+ int regnum; -+ int c45_sel; -+ u16 op_mode; -+ u16 val; -+}; -+ -+static struct cmicd_mdio_ctrl *cmic_common = NULL; -+ -+ -+static void __maybe_unused cmicd_mdiobus_test(struct mii_bus *mii_bus) -+{ -+ int i; -+ u16 data1 = 0, data2 = 0; -+ struct phy_device *phy_dev; -+ struct cmicd_mdiobus_private *bus_priv = mii_bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ -+ dev_info(mii_bus->parent, "%s : %s phy bus num[%d], type[%d]\n", -+ __func__, mii_bus->id, bus_data->phybus_num, bus_data->phybus_type); -+ -+ /* Check if mdiobus_read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ phy_dev = mii_bus->phy_map[i]; -+ if (phy_dev) -+ dev_info(mii_bus->parent, "phy[%d] id=0x%08x, addr = %d\n", -+ i, phy_dev->phy_id, phy_dev->addr); -+ } -+ -+ /* Check if general interface function for mdiobus read works fine */ -+ for (i = 0; i < PHY_MAX_ADDR; i++) { -+ data1 = mii_bus->read(mii_bus, i, 2); -+ data2 = mii_bus->read(mii_bus, i, 3); -+ if ((data1 < 0) || (data2 < 0)) { -+ dev_info(mii_bus->parent, -+ "iproc_mdiobus_read failed!, %s phy bus num[%d], type[%d], phyaddr = %d, nRet1 = %d, nRet2 = %d\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } else { -+ dev_info(mii_bus->parent, -+ "read %s phy bus num[%d] type[%d] phyaddr[%d], reg2 = 0x%x, reg3 = 0x%x\n", -+ mii_bus->id, bus_data->phybus_num, bus_data->phybus_type, i, data1, data2); -+ } -+ } -+} -+ -+static inline u32 cmicd_miim_reg_read(struct cmicd_mdio_ctrl *cmic_mdio, u32 reg) -+{ -+ u32 value = readl(cmic_mdio->base + reg); -+#ifdef __BIG_ENDIAN -+ if (readl(cmic_mdio->base + CMIC_COMMON_UC0_PIO_ENDIANESS) != 0) -+ { -+ /* CMICD is in big-endian mode */ -+ value = swab32(value); -+ } -+#endif -+ return value; -+} -+ -+static inline void cmicd_miim_reg_write(struct cmicd_mdio_ctrl *cmic_mdio, u32 reg, u32 data) -+{ -+#ifdef __BIG_ENDIAN -+ if (readl(cmic_mdio->base + CMIC_COMMON_UC0_PIO_ENDIANESS) != 0) -+ { -+ /* CMICD is in big-endian mode */ -+ writel(swab32(data), cmic_mdio->base + reg); -+ return; -+ } -+#endif -+ writel(data, cmic_mdio->base + reg); -+} -+ -+static inline void cmicd_miim_set_op_read(u32 *data, u32 set) -+{ -+ SET_REG_FIELD(*data, MIIM_CTRL__MIIM_RD_START_SHIFT, -+ MIIM_CTRL__MIIM_RD_START_MASK, set); -+} -+ -+static inline void cmicd_miim_set_op_write(u32 *data, u32 set) -+{ -+ SET_REG_FIELD(*data, MIIM_CTRL__MIIM_WR_START_SHIFT, -+ MIIM_CTRL__MIIM_WR_START_MASK, set); -+} -+ -+static inline int do_cmicd_miim_op(struct cmicd_mdio_ctrl *cmic_mdio, u32 op, u32 param, u32 addr) -+{ -+ u32 val, op_done; -+ unsigned long flags; -+ int ret = 0; -+ int usec = MIIM_OP_MAX_HALT_USEC; -+ -+ if (op >= MIIM_OP_MODE_MAX) { -+ printk(KERN_ERR "%s : invalid op code %d\n", __func__, op); -+ return -EINVAL; -+ } -+ -+ /* mutex_lock(&cmic_mdio->lock); */ -+ spin_lock_irqsave(&cmic_mdio->lock, flags); -+ -+ cmicd_miim_reg_write(cmic_mdio, MIIM_PARAM_REG, param); -+ cmicd_miim_reg_write(cmic_mdio, MIIM_ADDRESS_REG, addr); -+ val = cmicd_miim_reg_read(cmic_mdio, MIIM_CTRL_REG); -+ if(op == MIIM_OP_MODE_READ) -+ cmicd_miim_set_op_read(&val, 1); -+ else -+ cmicd_miim_set_op_write(&val, 1); -+ cmicd_miim_reg_write(cmic_mdio, MIIM_CTRL_REG, val); -+ -+ do { -+ op_done = GET_REG_FIELD(cmicd_miim_reg_read(cmic_mdio, MIIM_STAT_REG), -+ MIIM_STAT__MIIM_OPN_DONE_SHIFT, MIIM_STAT__MIIM_OPN_DONE_MASK); -+ if (op_done) -+ break; -+ -+ udelay(1); -+ usec--; -+ } while (usec > 0); -+ -+ if (op_done) { -+ if(op == MIIM_OP_MODE_READ) -+ ret = cmicd_miim_reg_read(cmic_mdio, MIIM_READ_DATA_REG); -+ } -+ else -+ ret = -ETIME; -+ -+ val = cmicd_miim_reg_read(cmic_mdio, MIIM_CTRL_REG); -+ if(op == MIIM_OP_MODE_READ) -+ cmicd_miim_set_op_read(&val, 0); -+ else -+ cmicd_miim_set_op_write(&val, 0); -+ cmicd_miim_reg_write(cmic_mdio, MIIM_CTRL_REG, val); -+ -+ /* mutex_unlock(&cmic_mdio->lock); */ -+ spin_unlock_irqrestore(&cmic_mdio->lock, flags); -+ -+ return ret; -+} -+ -+ -+static int cmicd_miim_op(struct cmicd_mdio_ctrl *cmic_mdio, struct cmicd_miim_cmd *cmd) -+{ -+ u32 miim_param =0, miim_addr = 0; -+ -+ ISET_REG_FIELD(miim_param, MIIM_PARAM__BUS_ID_SHIFT, -+ MIIM_PARAM__BUS_ID_MASK, cmd->bus_id); -+ -+ if (cmd->int_sel) -+ ISET_REG_FIELD(miim_param, MIIM_PARAM__INTERNAL_SEL_SHIFT, -+ MIIM_PARAM__INTERNAL_SEL_MASK, 1); -+ -+ ISET_REG_FIELD(miim_param, MIIM_PARAM__PHY_ID_SHIFT, -+ MIIM_PARAM__PHY_ID_MASK, cmd->phy_id); -+ -+ if (cmd->op_mode == MIIM_OP_MODE_WRITE) -+ ISET_REG_FIELD(miim_param, MIIM_PARAM__PHY_DATA_SHIFT, -+ MIIM_PARAM__PHY_DATA_MASK, cmd->val); -+ -+ if (cmd->c45_sel) { -+ ISET_REG_FIELD(miim_param, MIIM_PARAM__C45_SEL_SHIFT, -+ MIIM_PARAM__C45_SEL_MASK, 1); -+ -+ ISET_REG_FIELD(miim_addr, MIIM_ADDRESS__CLAUSE_45_REGADR_SHIFT, -+ MIIM_ADDRESS__CLAUSE_45_REGADR_MASK, cmd->regnum); -+ ISET_REG_FIELD(miim_addr, MIIM_ADDRESS__CLAUSE_45_DTYPE_SHIFT, -+ MIIM_ADDRESS__CLAUSE_45_REGADR_MASK, cmd->regnum >> 16); -+ } -+ else { -+ ISET_REG_FIELD(miim_addr, MIIM_ADDRESS__CLAUSE_22_REGADR_SHIFT, -+ MIIM_ADDRESS__CLAUSE_22_REGADR_MASK, cmd->regnum); -+ } -+ -+ return do_cmicd_miim_op(cmic_mdio, cmd->op_mode, miim_param, miim_addr); -+} -+ -+ -+static int cmicd_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) -+{ -+ struct cmicd_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ struct cmicd_miim_cmd cmd = {0}; -+ -+ cmd.bus_id = bus_data->phybus_num; -+ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) -+ cmd.int_sel = 1; -+ -+ cmd.phy_id = phy_id; -+ cmd.regnum = regnum; -+ -+ if (regnum & MII_ADDR_C45) -+ cmd.c45_sel = 1; -+ -+ cmd.op_mode = MIIM_OP_MODE_READ; -+ -+ return cmicd_miim_op(bus_priv->hw_ctrl, &cmd); -+} -+ -+static int cmicd_mdiobus_write(struct mii_bus *bus, int phy_id, -+ int regnum, u16 val) -+{ -+ struct cmicd_mdiobus_private *bus_priv = bus->priv; -+ struct iproc_mdiobus_data *bus_data = &bus_priv->bus_data; -+ struct cmicd_miim_cmd cmd = {0}; -+ -+ cmd.bus_id = bus_data->phybus_num; -+ if (IPROC_MDIOBUS_TYPE_INTERNAL == bus_data->phybus_type) -+ cmd.int_sel = 1; -+ -+ cmd.phy_id = phy_id; -+ cmd.regnum = regnum; -+ cmd.val = val; -+ -+ if (regnum & MII_ADDR_C45) -+ cmd.c45_sel = 1; -+ -+ cmd.op_mode = MIIM_OP_MODE_WRITE; -+ -+ return cmicd_miim_op(bus_priv->hw_ctrl, &cmd); -+} -+ -+static struct cmicd_mdio_ctrl * cmicd_mdio_res_alloc(void) -+{ -+ if (!cmic_common) { -+ cmic_common = kzalloc(sizeof(*cmic_common), GFP_KERNEL); -+ if (!cmic_common) -+ return NULL; -+ /* mutex_init(&cmic_common->lock); */ -+ spin_lock_init(&cmic_common->lock); -+ cmic_common->ref_cnt = 1; -+ } -+ else -+ cmic_common->ref_cnt ++; -+ -+ return cmic_common; -+} -+ -+static void cmicd_mdio_res_free(struct cmicd_mdio_ctrl *ctrl) -+{ -+ if (ctrl) { -+ ctrl->ref_cnt --; -+ if (ctrl->ref_cnt == 0) { -+ iounmap(ctrl->base); -+ kfree(ctrl); -+ cmic_common = NULL; -+ } -+ } -+} -+ -+static int cmicd_mdiobus_probe(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus; -+ struct device_node *dn = pdev->dev.of_node; -+ struct cmicd_mdiobus_private *bus_priv; -+ struct iproc_mdiobus_data *bus_data; -+ struct cmicd_mdio_ctrl *cmicd_ctrl; -+ u32 mdio_bus_id; -+ u32 logical_mdio_bus_id; -+ const char *mdio_bus_type; -+ int ret; -+ -+ if (!of_device_is_available(dn)) -+ return -ENODEV; -+ -+ cmicd_ctrl = cmicd_mdio_res_alloc(); -+ if (!cmicd_ctrl) { -+ dev_err(&pdev->dev, "cmicd mdio rese alloc failed\n"); -+ ret = -ENOMEM; -+ goto err_exit; -+ } -+ -+ /* Get register base address */ -+ cmicd_ctrl->base = (void *)of_iomap(dn, 0); /*cmic_common: 0x03210000*/ -+ -+ if (of_property_read_u32(dn, "#bus-id", &mdio_bus_id)) { -+ mdio_bus_id = 2; /* no property available, use default: 2 */ -+ } -+ if (of_property_read_u32(dn, "#logical-bus-id", &logical_mdio_bus_id)) { -+ logical_mdio_bus_id = 0; /*use default:0 */ -+ } -+ if (of_property_read_string(dn, "bus-type", &mdio_bus_type)) { -+ mdio_bus_type = "external"; /* use default: "external" */ -+ } -+ -+ iproc_mdiobus_data.phybus_num = (u8) mdio_bus_id; -+ iproc_mdiobus_data.logbus_num = (u8) logical_mdio_bus_id; -+ if (!strcmp(mdio_bus_type, "internal")) -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_INTERNAL; -+ else -+ iproc_mdiobus_data.phybus_type = IPROC_MDIOBUS_TYPE_EXTERNAL; -+ iproc_mdiobus_data.logbus_type = iproc_mdiobus_data.phybus_type; -+ bus_data = &iproc_mdiobus_data; -+ -+ mii_bus = mdiobus_alloc_size(sizeof(*bus_priv)); -+ if (!mii_bus) { -+ dev_err(&pdev->dev, "mdiobus_alloc failed\n"); -+ ret = -ENOMEM; -+ goto err_ctrl_free; -+ } -+ -+ mii_bus->name = "iproc_cmicd_mdiobus"; -+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, IPROC_MDIO_ID_FMT, -+ bus_data->logbus_num, bus_data->logbus_type); -+ mii_bus->parent = &pdev->dev; -+ mii_bus->read = cmicd_mdiobus_read; -+ mii_bus->write = cmicd_mdiobus_write; -+ -+ bus_priv = mii_bus->priv; -+ memcpy(&bus_priv->bus_data, bus_data, sizeof(struct iproc_mdiobus_data)); -+ bus_priv->hw_ctrl = cmicd_ctrl; -+ -+ if (IS_ENABLED(CONFIG_MACH_GH2) || IS_ENABLED(CONFIG_MACH_WH2)) -+ ret = of_mdiobus_register(mii_bus, dn); -+ else -+ ret = mdiobus_register(mii_bus); -+ if (ret) { -+ dev_err(&pdev->dev, "mdiobus_register failed\n"); -+ goto err_bus_free; -+ } -+ -+ platform_set_drvdata(pdev, mii_bus); -+ -+#if 0 -+ cmicd_mdiobus_test(mii_bus); -+#endif -+ -+ return 0; -+ -+err_bus_free: -+ kfree(mii_bus); -+err_ctrl_free: -+ cmicd_mdio_res_free(cmicd_ctrl); -+err_exit: -+ return ret; -+} -+ -+static int cmicd_mdiobus_remove(struct platform_device *pdev) -+{ -+ struct mii_bus *mii_bus = platform_get_drvdata(pdev); -+ struct cmicd_mdiobus_private *bus_priv; -+ -+ if (mii_bus) { -+ bus_priv = mii_bus->priv; -+ -+ mdiobus_unregister(mii_bus); -+ if (bus_priv) -+ cmicd_mdio_res_free(bus_priv->hw_ctrl); -+ mdiobus_free(mii_bus); -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm_iproc_dt_ids[] = { -+ { .compatible = "brcm,iproc-cmicd-mdio"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_dt_ids); -+ -+static struct platform_driver iproc_cmicd_mdiobus_driver = -+{ -+ .driver = { -+ .name = "iproc_cmicd_mdio", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(bcm_iproc_dt_ids), -+ }, -+ .probe = cmicd_mdiobus_probe, -+ .remove = cmicd_mdiobus_remove, -+}; -+ -+static int __init cmicd_mdio_init(void) -+{ -+ return platform_driver_register(&iproc_cmicd_mdiobus_driver); -+} -+ -+static void __exit cmicd_mdio_exit(void) -+{ -+ platform_driver_unregister(&iproc_cmicd_mdiobus_driver); -+} -+ -+//module_init(cmicd_mdio_init); -+subsys_initcall(cmicd_mdio_init); -+module_exit(cmicd_mdio_exit); -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("iProc CMICd mdio driver"); -+MODULE_LICENSE("GPL"); -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/iproc_mdio.c b/drivers/net/ethernet/broadcom/mdio/iproc_mdio.c ---- a/drivers/net/ethernet/broadcom/mdio/iproc_mdio.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/iproc_mdio.c 2017-11-09 17:53:44.082291000 +0800 -@@ -0,0 +1,141 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iproc_mdio.h" -+ -+/* Only one MDIO bus has been supported for each type */ -+static struct mii_bus *iproc_mdiobus[IPROC_MDIOBUS_TYPE_MAX] = {0}; -+ -+static struct mii_bus* -+get_iproc_mdiobus(int bustype, int phy_addr) -+{ -+ struct device *d; -+ char bus_id[MII_BUS_ID_SIZE]; -+ char phy_id[20]; -+ struct phy_device *phy_dev; -+ int idx; -+ -+ if (bustype < 0 || bustype >= IPROC_MDIOBUS_TYPE_MAX) { -+ return NULL; -+ } -+ -+ /* -+ * To support more than one bus for internal bus type on GH2, the following -+ * "if (NULL == iproc_mdiobus[bustype])" should be commented out. -+ * Note: The multi-bus support is based on the assumption that the phy_dev -+ * addresses are different for the internal bus_type bus. -+ */ -+#if !(defined(CONFIG_MACH_GH2) || (defined(CONFIG_MACH_HR3) && defined(CONFIG_MACH_WH2))) -+ if (NULL == iproc_mdiobus[bustype]) { -+#endif -+ for (idx = 0; idx < IPROC_MDIOBUS_NUM_MAX; idx++) { -+ snprintf(bus_id, MII_BUS_ID_SIZE, IPROC_MDIO_ID_FMT, idx, bustype); -+ snprintf(phy_id, 20, PHY_ID_FMT, bus_id, phy_addr); -+ d = bus_find_device_by_name(&mdio_bus_type, NULL, phy_id); -+ if (d) { -+ phy_dev = to_phy_device(d); -+ iproc_mdiobus[bustype] = phy_dev->bus; -+ idx = IPROC_MDIOBUS_NUM_MAX; -+ } -+ } -+#if !(defined(CONFIG_MACH_GH2) || (defined(CONFIG_MACH_HR3) && defined(CONFIG_MACH_WH2))) -+ } -+#endif -+ return iproc_mdiobus[bustype]; -+} -+ -+ -+/** -+ * iproc_mii_read - General iProc interface function for reading a given PHY register -+ if not registered PHY interface by phy_driver_register -+ * @busnum: currently we're using busnum value 0 -+ * @bustype: the mdio bus type, coud be IPROC_MDIOBUS_TYPE_INTERNAL or IPROC_MDIOBUS_TYPE_EXTERNAL -+ * @phy_addr: the phy address -+ * @regnum: register number to read, if MII_ADDR_C45 == (@regnum & MII_ADDR_C45), means a C45 request -+ * @val: the address to store read value if the read operation is successful -+ * -+ * Returns 0 on success, or a negative value on error. -+ */ -+int iproc_mii_read(int dev_type, int phy_addr, u32 reg_off, u16 *data) -+{ -+ struct mii_bus *mii_bus; -+ int bustype; -+ int err = -1; -+ -+ if (MII_DEV_LOCAL == dev_type) { -+ bustype = IPROC_MDIOBUS_TYPE_INTERNAL; -+ } else if (MII_DEV_EXT == dev_type) { -+ bustype = IPROC_MDIOBUS_TYPE_EXTERNAL; -+ } else { -+ return -EINVAL; -+ } -+ -+ mii_bus = get_iproc_mdiobus(bustype, phy_addr); -+ if (mii_bus) { -+ err = mii_bus->read(mii_bus, phy_addr, reg_off); -+ if (err >= 0) { -+ *data = err; -+ } -+ } else { -+ pr_err("%s : mdiobus:%d:%d is invalid!\n", __func__, 0, bustype); -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(iproc_mii_read); -+ -+/** -+ * iproc_mii_write - General iProc interface function for writing a given PHY register -+ if not registered PHY interface by phy_driver_register -+ * @busnum: currently we're using busnum value 0 -+ * @bustype: the mdio bus type, coud be IPROC_MDIOBUS_TYPE_INTERNAL or IPROC_MDIOBUS_TYPE_EXTERNAL -+ * @phy_addr: the phy address -+ * @regnum: register number to write, if MII_ADDR_C45 == (@regnum & MII_ADDR_C45), means a C45 request -+ * @val: value to write to @regnum -+ * -+ * Returns 0 on success, or a negative value on error. -+ */ -+int iproc_mii_write(int dev_type, int phy_addr, u32 reg_off, u16 data) -+{ -+ struct mii_bus *mii_bus; -+ int bustype; -+ int err = -1; -+ -+ if (MII_DEV_LOCAL == dev_type) { -+ bustype = IPROC_MDIOBUS_TYPE_INTERNAL; -+ } else if (MII_DEV_EXT == dev_type) { -+ bustype = IPROC_MDIOBUS_TYPE_EXTERNAL; -+ } else { -+ return -EINVAL; -+ } -+ -+ mii_bus = get_iproc_mdiobus(bustype, phy_addr); -+ if (mii_bus) { -+ err = mii_bus->write(mii_bus, phy_addr, reg_off, data); -+ } else { -+ pr_err("%s : mdiobus:%d:%d is invalid!\n", __func__, 0, bustype); -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(iproc_mii_write); -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/iproc_mdio.h b/drivers/net/ethernet/broadcom/mdio/iproc_mdio.h ---- a/drivers/net/ethernet/broadcom/mdio/iproc_mdio.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/iproc_mdio.h 2017-11-09 17:53:44.082312000 +0800 -@@ -0,0 +1,97 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+ -+#ifndef _bcm5301x_ccb_mii_h_ -+#define _bcm5301x_ccb_mii_h_ -+ -+#include -+ -+typedef struct _mdio_info_s { -+ void *h; /* dev handle */ -+ spinlock_t lock; -+} mdio_info_t; -+ -+/* reutrn value for MII driver */ -+#define MII_ERR_NONE 0 -+#define MII_ERR_TIMEOUT -1 -+#define MII_ERR_INTERNAL -2 -+#define MII_ERR_PARAM -3 -+#define MII_ERR_UNAVAIL -4 -+#define MII_ERR_UNKNOW -5 -+#define MII_ERR_INIT -6 -+ -+/* device type */ -+#define MII_DEV_LOCAL 0 -+#define MII_DEV_EXT 1 -+ -+/* MII register definition */ -+#define MII_MGMT 0x18003000 -+#define MII_MGMT_BASE 0x000 -+#define MII_MGMT_DATAMASK 0x000007ff -+#define MII_CMD_DATA 0x18003004 -+#define MII_CMD_DATA_BASE 0x004 -+#define MII_CMD_DATA_DATAMASK 0xffffffff -+ -+/* fields in MII_MGMT */ -+#define MII_MGMT_BYP_MASK 0x00000400 -+#define MII_MGMT_BYP_SHIFT 10 -+#define MII_MGMT_EXP_MASK 0x00000200 -+#define MII_MGMT_EXP_SHIFT 9 -+#define MII_MGMT_BSY_MASK 0x00000100 -+#define MII_MGMT_BSY_SHIFT 8 -+#define MII_MGMT_PRE_MASK 0x00000080 -+#define MII_MGMT_PRE_SHIFT 7 -+#define MII_MGMT_MDCDIV_MASK 0x0000007f -+#define MII_MGMT_MDCDIV_SHIFT 0 -+/* fields in MII_CMD_DATA */ -+#define MII_CMD_DATA_SB_MASK 0xc0000000 -+#define MII_CMD_DATA_SB_SHIFT 30 -+#define MII_CMD_DATA_OP_MASK 0x30000000 -+#define MII_CMD_DATA_OP_SHIFT 28 -+#define MII_CMD_DATA_PA_MASK 0x0f800000 -+#define MII_CMD_DATA_PA_SHIFT 23 -+#define MII_CMD_DATA_RA_MASK 0x007c0000 -+#define MII_CMD_DATA_RA_SHIFT 18 -+#define MII_CMD_DATA_TA_MASK 0x00030000 -+#define MII_CMD_DATA_TA_SHIFT 16 -+#define MII_CMD_DATA_DATA_MASK 0x0000ffff -+#define MII_CMD_DATA_DATA_SHIFT 0 -+ -+ -+/****** iProc General Interface for mdio bus support ******/ -+struct iproc_mdiobus_data { -+ /* the mdio bus num and type from chip view */ -+ u8 logbus_num; -+ u8 logbus_type; -+ /* the actual bus num and type that mdio bus comes from */ -+ u8 phybus_num; -+ u8 phybus_type; -+ /* Note : -+ * Usually the logbus_num and logbus_type are the same as phybus_num and -+ * phybus_type, but they may be different on some special cases. For example, -+ * we may use cmicd mdio external bus 2 for the iProc mdio external bus 0, -+ * this configuration could be described as phybus_num=2, phybus_type=external, -+ * logbus_num=0, logbus_type=external. From iProc's view, the Phy devices -+ * for iProc AMAC should use mdiobus by logbus_num and logbus_type. But internally -+ * we'll configure the mdio core by phybus_num and phybus_type. -+ */ -+}; -+ -+#define IPROC_MDIOBUS_TYPE_INTERNAL 0 -+#define IPROC_MDIOBUS_TYPE_EXTERNAL 1 -+ -+#define IPROC_MDIOBUS_NUM_MAX 8 -+#define IPROC_MDIOBUS_TYPE_MAX 2 -+ -+/* iproc_mii:[bus_num]:[bus_type] */ -+#define IPROC_MDIO_ID_FMT "iproc_mii:%01x:%01x" -+ -+ -+/* General interface for iProc mdio bus read/write function */ -+extern int iproc_mii_read(int dev_type, int phy_addr, u32 reg_off, u16 *data); -+extern int iproc_mii_write(int dev_type, int phy_addr, u32 reg_off, u16 data); -+/****** iProc General Interface for mdio bus support ******/ -+ -+#endif /* _bcm5301x_ccb_mii_h_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/net/ethernet/broadcom/mdio/iproc_mdio_dev.h b/drivers/net/ethernet/broadcom/mdio/iproc_mdio_dev.h ---- a/drivers/net/ethernet/broadcom/mdio/iproc_mdio_dev.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/net/ethernet/broadcom/mdio/iproc_mdio_dev.h 2017-11-09 17:53:44.083307000 +0800 -@@ -0,0 +1,32 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+ -+#ifndef _IPROC_MDIO_DEV_H -+#define _IPROC_MDIO_DEV_H -+ -+/* IOCTL commands */ -+ -+#define MDIO_IOC_MAGIC 'm' -+ -+struct mdio_ioc_transfer { -+ uint8_t pa; /* phy address */ -+ uint8_t ra; /* register address */ -+ uint16_t tx_buf; -+ uint16_t rx_buf; -+}; -+ -+#define MDIO_MSGSIZE(N) \ -+ ((((N)*(sizeof (struct mdio_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ -+ ? ((N)*(sizeof (struct mdio_ioc_transfer))) : 0) -+ -+#define MDIO_IOC_MESSAGE(N) _IOW(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(N)]) -+ -+#define MDIO_IOC_EXTERNAL_R_REG _IOWR(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(1)]) -+#define MDIO_IOC_EXTERNAL_W_REG _IOW(MDIO_IOC_MAGIC, 1, char[MDIO_MSGSIZE(1)]) -+#define MDIO_IOC_LOCAL_R_REG _IOWR(MDIO_IOC_MAGIC, 2, char[MDIO_MSGSIZE(1)]) -+#define MDIO_IOC_LOCAL_W_REG _IOW(MDIO_IOC_MAGIC, 3, char[MDIO_MSGSIZE(1)]) -+ -+ -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig ---- a/drivers/pci/host/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/pci/host/Kconfig 2017-11-09 17:53:50.841348000 +0800 -@@ -118,6 +118,15 @@ config PCI_VERSATILE - bool "ARM Versatile PB PCI controller" - depends on ARCH_VERSATILE - -+config PCIE_XGS_IPROC -+ tristate "Broadcom XGS iProc PCIe controller" -+ select PCI_DOMAINS -+ depends on ARCH_XGS_IPROC -+ default n -+ help -+ This enables the XGS iProc PCIe core controller support for Broadcom's -+ iProc family of SoCs. -+ - config PCIE_IPROC - tristate "Broadcom iProc PCIe controller" - depends on OF && (ARM || ARM64) -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile ---- a/drivers/pci/host/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/pci/host/Makefile 2017-11-09 17:53:50.842362000 +0800 -@@ -16,6 +16,7 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-laye - obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o - obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o - obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o -+obj-$(CONFIG_PCIE_XGS_IPROC) += pcie-xgs-iproc.o - obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o - obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o - obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/pci/host/pcie-xgs-iproc.c b/drivers/pci/host/pcie-xgs-iproc.c ---- a/drivers/pci/host/pcie-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/pci/host/pcie-xgs-iproc.c 2017-11-09 17:53:50.893339000 +0800 -@@ -0,0 +1,469 @@ -+/* -+ * Copyright (C) 2014 Hauke Mehrtens -+ * Copyright (C) 2015 Broadcom 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 version 2. -+ * -+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any -+ * kind, whether express or implied; 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CLK_CONTROL_OFFSET 0x000 -+ -+#define CFG_IND_ADDR_OFFSET 0x120 -+#define CFG_IND_ADDR_MASK 0x00001ffc -+#define CFG_IND_DATA_OFFSET 0x124 -+ -+#define CFG_ADDR_OFFSET 0x1f8 -+#define CFG_ADDR_BUS_NUM_SHIFT 20 -+#define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 -+#define CFG_ADDR_DEV_NUM_SHIFT 15 -+#define CFG_ADDR_DEV_NUM_MASK 0x000f8000 -+#define CFG_ADDR_FUNC_NUM_SHIFT 12 -+#define CFG_ADDR_FUNC_NUM_MASK 0x00007000 -+#define CFG_ADDR_REG_NUM_SHIFT 2 -+#define CFG_ADDR_REG_NUM_MASK 0x00000ffc -+#define CFG_ADDR_CFG_TYPE_SHIFT 0 -+#define CFG_ADDR_CFG_TYPE_MASK 0x00000003 -+ -+#define CFG_DATA_OFFSET 0x1fc -+ -+#define SYS_RC_INTX_EN 0x330 -+#define SYS_RC_INTX_MASK 0xf -+ -+#define IPROC_PCIE_MAX_NUM_IRQS 6 -+ -+/** -+ * iProc PCIe device -+ * @dev: pointer to device data structure -+ * @base: PCIe host controller I/O register base -+ * @resources: linked list of all PCI resources -+ * @sysdata: Per PCI controller data (ARM-specific) -+ * @root_bus: pointer to root bus -+ * @phy: optional PHY device that controls the Serdes -+ * @irqs: interrupt IDs -+ */ -+struct iproc_pcie { -+ struct device *dev; -+ void __iomem *base; -+#ifdef CONFIG_ARM -+ struct pci_sys_data sysdata; -+#endif -+ struct pci_bus *root_bus; -+ struct phy *phy; -+ int irqs[IPROC_PCIE_MAX_NUM_IRQS]; -+ int (*map_irq)(const struct pci_dev *, u8, u8); -+}; -+ -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) \ -+ || defined(CONFIG_MACH_GH2)) -+#define PCI_PERST_SWR (1) -+#define PCI_CONFIG_SWR (1) -+#else -+#define PCI_PERST_SWR (0) -+#define PCI_CONFIG_SWR (0) -+#endif /* defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2)*/ -+ -+#if PCI_CONFIG_SWR -+extern char * nvram_get(const char *name); -+#endif /* PCI_CONFIG_SWR */ -+ -+#define MII_DEV_LOCAL 0 -+extern int iproc_mii_write(int dev_type, int phy_addr, u32 reg_off, u16 data); -+ -+static inline struct iproc_pcie *iproc_pcie_data(struct pci_bus *bus) -+{ -+ struct iproc_pcie *pcie; -+#ifdef CONFIG_ARM -+ struct pci_sys_data *sys = bus->sysdata; -+ -+ pcie = sys->private_data; -+#else -+ pcie = bus->sysdata; -+#endif -+ return pcie; -+} -+ -+/** -+ * Note access to the configuration registers are protected at the higher layer -+ * by 'pci_lock' in drivers/pci/access.c -+ */ -+static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, -+ unsigned int devfn, -+ int where) -+{ -+ struct iproc_pcie *pcie = iproc_pcie_data(bus); -+ unsigned slot = PCI_SLOT(devfn); -+ unsigned fn = PCI_FUNC(devfn); -+ unsigned busno = bus->number; -+ u32 val; -+ -+ /* root complex access */ -+ if (busno == 0) { -+ if (slot >= 1) -+ return NULL; -+ writel(where & CFG_IND_ADDR_MASK, -+ pcie->base + CFG_IND_ADDR_OFFSET); -+ return (pcie->base + CFG_IND_DATA_OFFSET); -+ } -+ -+ if (fn > 1) -+ return NULL; -+ -+ /* EP device access */ -+ val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | -+ (slot << CFG_ADDR_DEV_NUM_SHIFT) | -+ (fn << CFG_ADDR_FUNC_NUM_SHIFT) | -+ (where & CFG_ADDR_REG_NUM_MASK) | -+ (1 & CFG_ADDR_CFG_TYPE_MASK); -+ writel(val, pcie->base + CFG_ADDR_OFFSET); -+ -+ return (pcie->base + CFG_DATA_OFFSET); -+} -+ -+static struct pci_ops iproc_pcie_ops = { -+ .map_bus = iproc_pcie_map_cfg_bus, -+ .read = pci_generic_config_read32, -+ .write = pci_generic_config_write32, -+}; -+ -+static void iproc_pcie_reset(struct iproc_pcie *pcie) -+{ -+ /* Configure the PCIe controller as root complex and send a downstream reset */ -+ writel(0, pcie->base + CLK_CONTROL_OFFSET); -+ mdelay(1); -+ writel(1, pcie->base + CLK_CONTROL_OFFSET); -+ mdelay(100); -+} -+ -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2)) -+static int pcie_serdes_reg_write(int phyaddr, int reg, u16 val) -+{ -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, 0x1f, reg & 0xfff0); -+ iproc_mii_write(MII_DEV_LOCAL, phyaddr, reg & 0xf, val); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int pcie_rc_war(struct iproc_pcie * pcie) -+{ -+ /* Setting for PCIe Serdes PLL output */ -+ pcie_serdes_reg_write(2, 0x2103, 0x2b1c); -+ pcie_serdes_reg_write(2, 0x1300, 0x000b); -+ mdelay(100); -+ -+#if PCI_PERST_SWR -+ iproc_pcie_reset(pcie); -+#endif /* PCI_PERST_SWR */ -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+#endif /* CONFIG_MACH_GH || CONFIG_MACH_SB2) || CONFIG_MACH_HR3 || defined(CONFIG_MACH_GH2) */ -+ -+static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) -+{ -+ u8 hdr_type; -+ u32 link_ctrl; -+ u16 pos, link_status; -+ bool link_is_active = false; -+ u32 class; -+#if PCI_CONFIG_SWR -+ u32 tmp32, devfn = 0; -+ char *pcie_configs = NULL; -+#endif /* PCI_CONFIG_SWR */ -+ -+ -+ /* make sure we are not in EP mode */ -+ pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); -+ if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { -+ dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type); -+ return -EFAULT; -+ } -+ -+#if (defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_SB2) || defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2)) -+ pcie_rc_war(pcie); -+#endif -+ -+#if PCI_CONFIG_SWR -+ pcie_configs = nvram_get("pcie_configs"); -+ if (pcie_configs) { -+ if (!strcmp(pcie_configs, "tx-de-emp")) { -+ pci_bus_read_config_dword(bus, devfn, 0xdc, &tmp32); -+ tmp32 |= (0x1 << 6); -+ pci_bus_write_config_dword(bus, devfn, 0xdc, tmp32); -+ pci_bus_read_config_dword(bus, devfn, 0xdc, &tmp32); -+ } -+ } -+#endif /* PCI_CONFIG_SWR */ -+ -+ /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ -+ /* -+ * After this modification, the CLASS code in configuration space would be -+ * read as PCI_CLASS_BRIDGE_PCI(0x0604) instead of network interface(0x0200) -+ */ -+#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c -+#define PCI_CLASS_BRIDGE_MASK 0xffff00 -+#define PCI_CLASS_BRIDGE_SHIFT 8 -+ pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); -+ class &= ~PCI_CLASS_BRIDGE_MASK; -+ class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); -+ pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); -+ -+ /* check link status to see if link is active */ -+ pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); -+ pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); -+ if (link_status & PCI_EXP_LNKSTA_NLW) -+ link_is_active = true; -+ -+ if (!link_is_active) { -+ /* try GEN 1 link speed */ -+#define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc -+#define PCI_TARGET_LINK_SPEED_MASK 0xf -+#define PCI_TARGET_LINK_SPEED_GEN2 0x2 -+#define PCI_TARGET_LINK_SPEED_GEN1 0x1 -+ pci_bus_read_config_dword(bus, 0, -+ PCI_LINK_STATUS_CTRL_2_OFFSET, -+ &link_ctrl); -+ if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == -+ PCI_TARGET_LINK_SPEED_GEN2) { -+ link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; -+ link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; -+ pci_bus_write_config_dword(bus, 0, -+ PCI_LINK_STATUS_CTRL_2_OFFSET, -+ link_ctrl); -+ msleep(100); -+ -+ pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); -+ pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, -+ &link_status); -+ if (link_status & PCI_EXP_LNKSTA_NLW) -+ link_is_active = true; -+ } -+ } -+ -+ dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); -+ -+ return link_is_active ? 0 : -ENODEV; -+} -+ -+static void iproc_pcie_enable(struct iproc_pcie *pcie) -+{ -+ writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); -+} -+ -+int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) -+{ -+ int ret; -+ void *sysdata; -+ struct pci_bus *bus; -+ -+ if (!pcie || !pcie->dev || !pcie->base) -+ return -EINVAL; -+ -+ ret = phy_init(pcie->phy); -+ if (ret) { -+ dev_err(pcie->dev, "unable to initialize PCIe PHY\n"); -+ return ret; -+ } -+ -+ ret = phy_power_on(pcie->phy); -+ if (ret) { -+ dev_err(pcie->dev, "unable to power on PCIe PHY\n"); -+ goto err_exit_phy; -+ } -+ -+ iproc_pcie_reset(pcie); -+ -+#ifdef CONFIG_ARM -+ pcie->sysdata.private_data = pcie; -+ sysdata = &pcie->sysdata; -+#else -+ sysdata = pcie; -+#endif -+ -+ bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops, sysdata, res); -+ if (!bus) { -+ dev_err(pcie->dev, "unable to create PCI root bus\n"); -+ ret = -ENOMEM; -+ goto err_power_off_phy; -+ } -+ pcie->root_bus = bus; -+ -+ ret = iproc_pcie_check_link(pcie, bus); -+ if (ret) { -+ dev_err(pcie->dev, "no PCIe EP device detected\n"); -+ goto err_rm_root_bus; -+ } -+ -+ iproc_pcie_enable(pcie); -+ -+ pci_scan_child_bus(bus); -+ pci_assign_unassigned_bus_resources(bus); -+#ifdef CONFIG_ARM -+ pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); -+#endif -+ pci_bus_add_devices(bus); -+ -+ return 0; -+ -+err_rm_root_bus: -+ pci_stop_root_bus(bus); -+ pci_remove_root_bus(bus); -+ -+err_power_off_phy: -+ phy_power_off(pcie->phy); -+err_exit_phy: -+ phy_exit(pcie->phy); -+ return ret; -+} -+EXPORT_SYMBOL(iproc_pcie_setup); -+ -+ -+#if ( defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HR2) ) -+static void WrongPCIGen2TemplateWAR(int port, u32 reg, u16 val) -+{ -+ /* port = phy addr */ -+ iproc_mii_write(MII_DEV_LOCAL, port, 0x1f, 0x8630); -+ iproc_mii_write(MII_DEV_LOCAL, port, reg, val); -+} -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_SKT2) || defined(CONFIG_MACH_HR2) */ -+ -+ -+int iproc_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) -+{ -+ struct iproc_pcie *pcie = iproc_pcie_data(pdev->bus); -+ int irq = pcie->irqs[4]; -+ -+ return irq; -+} -+ -+static int iproc_pcie_probe(struct platform_device *pdev) -+{ -+ struct iproc_pcie *pcie; -+ struct device_node *np = pdev->dev.of_node; -+ struct resource reg; -+ resource_size_t iobase = 0; -+ LIST_HEAD(res); -+ int ret; -+ //u32 irqs_total; -+ int i; -+ -+ pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL); -+ if (!pcie) -+ return -ENOMEM; -+ -+ pcie->dev = &pdev->dev; -+ platform_set_drvdata(pdev, pcie); -+ -+ ret = of_address_to_resource(np, 0, ®); -+ if (ret < 0) { -+ dev_err(pcie->dev, "unable to obtain controller resources\n"); -+ return ret; -+ } -+ -+ pcie->base = devm_ioremap_resource(pcie->dev, ®); -+ if (IS_ERR(pcie->base)) -+ return PTR_ERR(pcie->base); -+ -+ /* PHY use is optional */ -+ pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy"); -+ if (IS_ERR(pcie->phy)) { -+ if (PTR_ERR(pcie->phy) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ pcie->phy = NULL; -+ } -+ -+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &iobase); -+ if (ret) { -+ dev_err(pcie->dev, -+ "unable to get PCI host bridge resources\n"); -+ return ret; -+ } -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HR2)) -+// if (of_device_is_compatible(np, "iproc-p2") || of_device_is_compatible(np, "iproc-p6")) { -+ WrongPCIGen2TemplateWAR(of_get_pci_domain_nr(np) + 7, 0x13, 0x190); -+ WrongPCIGen2TemplateWAR(of_get_pci_domain_nr(np) + 7, 0x19, 0x191); -+// } -+#endif -+ -+ /*Parse IRQ*/ -+ /* of_irq_count is not exported for module to call */ -+#if 0 -+ irqs_total = of_irq_count(np); -+ if ( !irqs_total || (irqs_total > IPROC_PCIE_MAX_NUM_IRQS) ) -+ return -EINVAL; -+#endif -+ -+ for (i = 0; i < IPROC_PCIE_MAX_NUM_IRQS; i++) { -+ pcie->irqs[i] = irq_of_parse_and_map(np, i); -+ if (!pcie->irqs[i]) { -+ dev_err(&pdev->dev, "unable to parse or map irq index:%d\n", i); -+ return -EINVAL; -+ } -+ } -+ -+ //pcie->map_irq = of_irq_parse_and_map_pci; -+ pcie->map_irq = iproc_pcie_map_irq; -+ -+ ret = iproc_pcie_setup(pcie, &res); -+ if (ret) -+ dev_err(pcie->dev, "PCIe controller setup failed\n"); -+ -+ pci_free_resource_list(&res); -+ -+ return ret; -+} -+ -+static int iproc_pcie_remove(struct platform_device *pdev) -+{ -+ struct iproc_pcie *pcie = platform_get_drvdata(pdev); -+ -+ pci_stop_root_bus(pcie->root_bus); -+ pci_remove_root_bus(pcie->root_bus); -+ -+ phy_power_off(pcie->phy); -+ phy_exit(pcie->phy); -+ -+ return 0; -+} -+ -+static const struct of_device_id iproc_pcie_of_match_table[] = { -+ { .compatible = "brcm,iproc-pcie", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table); -+ -+static struct platform_driver iproc_pcie_pltfm_driver = { -+ .driver = { -+ .name = "iproc-pcie", -+ .of_match_table = of_match_ptr(iproc_pcie_of_match_table), -+ }, -+ .probe = iproc_pcie_probe, -+ .remove = iproc_pcie_remove, -+}; -+ -+module_platform_driver(iproc_pcie_pltfm_driver); -+ -+MODULE_DESCRIPTION("Broadcom XGS iProc PCIe driver"); -+MODULE_LICENSE("GPL v2"); -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/soc/Kconfig b/drivers/soc/Kconfig ---- a/drivers/soc/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/soc/Kconfig 2017-11-09 17:53:55.652386000 +0800 -@@ -1,6 +1,7 @@ - menu "SOC (System On Chip) specific Drivers" - - source "drivers/soc/brcmstb/Kconfig" -+source "drivers/soc/bcm/Kconfig" - source "drivers/soc/mediatek/Kconfig" - source "drivers/soc/qcom/Kconfig" - source "drivers/soc/rockchip/Kconfig" -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/soc/Makefile b/drivers/soc/Makefile ---- a/drivers/soc/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/soc/Makefile 2017-11-09 17:53:55.653381000 +0800 -@@ -2,6 +2,7 @@ - # Makefile for the Linux Kernel SOC specific device drivers. - # - -+obj-$(CONFIG_SOC_XGS_IPROC) += bcm/ - obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ - obj-$(CONFIG_MACH_DOVE) += dove/ - obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig ---- a/drivers/soc/bcm/Kconfig 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/soc/bcm/Kconfig 2017-11-09 17:53:55.664395000 +0800 -@@ -0,0 +1,8 @@ -+menuconfig SOC_XGS_IPROC -+ bool "Broadcom XGS iProc IDM/DMU/PMU drivers" -+ depends on ARCH_XGS_IPROC -+ default ARCH_XGS_IPROC -+ help -+ This option enables XGS iProc IDM/DMU/PMU related drivers. -+ -+ If unsure, say Y. -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile ---- a/drivers/soc/bcm/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/soc/bcm/Makefile 2017-11-09 17:53:55.665375000 +0800 -@@ -0,0 +1 @@ -+obj-$(CONFIG_SOC_XGS_IPROC) += xgs-iproc-wrap-idm-dmu.o xgs-iproc-idm.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/soc/bcm/xgs-iproc-idm.c b/drivers/soc/bcm/xgs-iproc-idm.c ---- a/drivers/soc/bcm/xgs-iproc-idm.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/soc/bcm/xgs-iproc-idm.c 2017-11-09 17:53:55.666387000 +0800 -@@ -0,0 +1,842 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern void __iomem *get_iproc_idm_base(int); -+extern void __iomem *get_iproc_idm_base_phys(int); -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_HR2) -+#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18107900 -+#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18107904 -+#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18107908 -+#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810790c -+#define IHOST_S1_IDM_ERROR_LOG_ID 0x18107914 -+#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810791c -+#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18107a00 -+#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18108900 -+#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18108904 -+#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18108908 -+#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810890c -+#define IHOST_S0_IDM_ERROR_LOG_ID 0x18108914 -+#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810891c -+#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18108a00 -+#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18109900 -+#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18109904 -+#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18109908 -+#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810990c -+#define DDR_S1_IDM_ERROR_LOG_ID 0x18109914 -+#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810991c -+#define DDR_S1_IDM_INTERRUPT_STATUS 0x18109a00 -+#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x1810a900 -+#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x1810a904 -+#define DDR_S2_IDM_ERROR_LOG_STATUS 0x1810a908 -+#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c -+#define DDR_S2_IDM_ERROR_LOG_ID 0x1810a914 -+#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810a91c -+#define DDR_S2_IDM_INTERRUPT_STATUS 0x1810aa00 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810b900 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810b904 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810b908 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810b90c -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810b914 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810b91c -+#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810ba00 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810d900 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810d904 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810d908 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810d90c -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810d914 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810d91c -+#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810da00 -+#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810f900 -+#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810f904 -+#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810f908 -+#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810f90c -+#define APBY_S0_IDM_IDM_ERROR_LOG_ID 0x1810f914 -+#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810f91c -+#define APBY_S0_IDM_IDM_INTERRUPT_STATUS 0x1810fa00 -+#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 -+#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 -+#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 -+#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c -+#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 -+#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c -+#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 -+#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811b900 -+#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811b904 -+#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811b908 -+#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c -+#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811b914 -+#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811b91c -+#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811ba00 -+#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811c900 -+#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811c904 -+#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811c908 -+#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811c90c -+#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811c914 -+#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811c91c -+#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811ca00 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811d914 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c -+#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811da00 -+#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x18120900 -+#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x18120904 -+#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x18120908 -+#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c -+#define SRAM_S0_IDM_ERROR_LOG_ID 0x18120914 -+#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1812091c -+#define SRAM_S0_IDM_INTERRUPT_STATUS 0x18120a00 -+#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 -+#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 -+#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS 0x18121908 -+#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190c -+#define APBZ_S0_IDM_IDM_ERROR_LOG_ID 0x18121914 -+#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812191c -+#define APBZ_S0_IDM_IDM_INTERRUPT_STATUS 0x18121a00 -+#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18123900 -+#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18123904 -+#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x18123908 -+#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1812390c -+#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18123914 -+#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1812391c -+#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18123a00 -+#define APBW_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 -+#define APBW_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 -+#define APBW_IDM_IDM_ERROR_LOG_STATUS 0x18131908 -+#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c -+#define APBW_IDM_IDM_ERROR_LOG_ID 0x18131914 -+#define APBW_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c -+#define APBW_IDM_IDM_INTERRUPT_STATUS 0x18131a00 -+#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 -+#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 -+#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18132908 -+#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c -+#define APBX_IDM_IDM_ERROR_LOG_ID 0x18132914 -+#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c -+#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18132a00 -+#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18141900 -+#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18141904 -+#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18141908 -+#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1814190c -+#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18141914 -+#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1814191c -+#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18141a00 -+ -+#elif defined(CONFIG_MACH_HR3) -+ -+#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 -+#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 -+#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 -+#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790c -+#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 -+#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791c -+#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107a00 -+#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 -+#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 -+#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 -+#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690c -+#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 -+#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691c -+#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106a00 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18108900 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18108904 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x18108908 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810890c -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x18108914 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810891c -+#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x18108a00 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810a900 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810a904 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810a908 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810a914 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810a91c -+#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810aa00 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18119900 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18119904 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x18119908 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811990c -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x18119914 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811991c -+#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x18119a00 -+#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18130900 -+#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18130904 -+#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18130908 -+#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813090c -+#define APBX_IDM_IDM_ERROR_LOG_ID 0x18130914 -+#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813091c -+#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18130a00 -+#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18104900 -+#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18104904 -+#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18104908 -+#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810490c -+#define DDR_S1_IDM_ERROR_LOG_ID 0x18104914 -+#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810491c -+#define DDR_S1_IDM_INTERRUPT_STATUS 0x18104a00 -+#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x18105900 -+#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x18105904 -+#define DDR_S2_IDM_ERROR_LOG_STATUS 0x18105908 -+#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810590c -+#define DDR_S2_IDM_ERROR_LOG_ID 0x18105914 -+#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810591c -+#define DDR_S2_IDM_INTERRUPT_STATUS 0x18105a00 -+#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 -+#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 -+#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 -+#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c -+#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 -+#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c -+#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 -+#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 -+#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 -+#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 -+#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c -+#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811d914 -+#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c -+#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811da00 -+#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811f900 -+#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811f904 -+#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811f908 -+#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811f90c -+#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811f914 -+#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811f91c -+#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811fa00 -+#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18120900 -+#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18120904 -+#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18120908 -+#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c -+#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18120914 -+#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1812091c -+#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18120a00 -+ -+#elif defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_SB2) || \ -+ defined(CONFIG_MACH_GH2) -+ -+#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 -+#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 -+#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 -+#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790c -+#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 -+#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791c -+#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107a00 -+#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 -+#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 -+#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 -+#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690c -+#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 -+#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691c -+#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106a00 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18108900 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18108904 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x18108908 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810890c -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x18108914 -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810891c -+#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x18108a00 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810a900 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810a904 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810a908 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810a914 -+#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810a91c -+#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810aa00 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18119900 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18119904 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x18119908 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811990c -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x18119914 -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811991c -+#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x18119a00 -+#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x1811b900 -+#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x1811b904 -+#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x1811b908 -+#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c -+#define SRAM_S0_IDM_ERROR_LOG_ID 0x1811b914 -+#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1811b91c -+#define SRAM_S0_IDM_INTERRUPT_STATUS 0x1811ba00 -+#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18130900 -+#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18130904 -+#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18130908 -+#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813090c -+#define APBX_IDM_IDM_ERROR_LOG_ID 0x18130914 -+#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813091c -+#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18130a00 -+#define DDR_S1_IDM_ERROR_LOG_CONTROL 0xf8102900 -+#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0xf8102904 -+#define DDR_S1_IDM_ERROR_LOG_STATUS 0xf8102908 -+#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0xf810290c -+#define DDR_S1_IDM_ERROR_LOG_ID 0xf8102914 -+#define DDR_S1_IDM_ERROR_LOG_FLAGS 0xf810291c -+#define DDR_S1_IDM_INTERRUPT_STATUS 0xf8102a00 -+#define DDR_S2_IDM_ERROR_LOG_CONTROL 0xf8103900 -+#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0xf8103904 -+#define DDR_S2_IDM_ERROR_LOG_STATUS 0xf8103908 -+#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0xf810390c -+#define DDR_S2_IDM_ERROR_LOG_ID 0xf8103914 -+#define DDR_S2_IDM_ERROR_LOG_FLAGS 0xf810391c -+#define DDR_S2_IDM_INTERRUPT_STATUS 0xf8103a00 -+#define ROM_S0_IDM_ERROR_LOG_CONTROL 0xf8104900 -+#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0xf8104904 -+#define ROM_S0_IDM_ERROR_LOG_STATUS 0xf8104908 -+#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0xf810490c -+#define ROM_S0_IDM_ERROR_LOG_ID 0xf8104914 -+#define ROM_S0_IDM_ERROR_LOG_FLAGS 0xf810491c -+#define ROM_S0_IDM_INTERRUPT_STATUS 0xf8104a00 -+#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0xf8105900 -+#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0xf8105904 -+#define NAND_IDM_IDM_ERROR_LOG_STATUS 0xf8105908 -+#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810590c -+#define NAND_IDM_IDM_ERROR_LOG_ID 0xf8105914 -+#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0xf810591c -+#define NAND_IDM_IDM_INTERRUPT_STATUS 0xf8105a00 -+#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0xf8106900 -+#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0xf8106904 -+#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0xf8106908 -+#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810690c -+#define QSPI_IDM_IDM_ERROR_LOG_ID 0xf8106914 -+#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0xf810691c -+#define QSPI_IDM_IDM_INTERRUPT_STATUS 0xf8106a00 -+#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18120900 -+#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18120904 -+#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18120908 -+#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c -+#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18120914 -+#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1812091c -+#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18120a00 -+#if !defined(CONFIG_MACH_GH2) -+#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x1811e900 -+#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x1811e904 -+#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x1811e908 -+#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1811e90c -+#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x1811e914 -+#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1811e91c -+#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x1811ea00 -+#endif /* !defined(CONFIG_MACH_GH2) */ -+ -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ -+ defined(CONFIG_MACH_HR2) */ -+ -+#if defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_SB2) || \ -+ defined(CONFIG_MACH_GH2) -+#define IDM_IO_PHYS_TO_VIRT(x) (void __iomem *) \ -+ (((x & 0xFFF00000) == (int)get_iproc_idm_base_phys(0))? \ -+ get_iproc_idm_base(0) + x - get_iproc_idm_base_phys(0) : \ -+ get_iproc_idm_base(1) + x - get_iproc_idm_base_phys(1)) -+#else -+#define IDM_IO_PHYS_TO_VIRT(x) (void __iomem *) \ -+ (get_iproc_idm_base(0) + x - get_iproc_idm_base_phys(0)) -+#endif -+ -+ -+#define IHOST_S1_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_CONTROL) -+#define IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_COMPLETE) -+#define IHOST_S1_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_STATUS) -+#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB) -+#define IHOST_S1_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ID) -+#define IHOST_S1_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_FLAGS) -+ -+#define IHOST_S0_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_CONTROL) -+#define IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_COMPLETE) -+#define IHOST_S0_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_STATUS) -+#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB) -+#define IHOST_S0_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ID) -+#define IHOST_S0_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_FLAGS) -+ -+#define DDR_S1_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_CONTROL) -+#define DDR_S1_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_COMPLETE) -+#define DDR_S1_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_STATUS) -+#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ADDR_LSB) -+#define DDR_S1_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ID) -+#define DDR_S1_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_FLAGS) -+ -+#define DDR_S2_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_CONTROL) -+#define DDR_S2_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_COMPLETE) -+#define DDR_S2_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_STATUS) -+#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ADDR_LSB) -+#define DDR_S2_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ID) -+#define DDR_S2_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_FLAGS) -+ -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL) -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE) -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS) -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID) -+#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL) -+#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE) -+#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS) -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ID) -+#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_CONTROL) -+#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE) -+#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_STATUS) -+#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define APBY_S0_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ID) -+#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define ROM_S0_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_CONTROL) -+#define ROM_S0_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_COMPLETE) -+#define ROM_S0_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_STATUS) -+#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ADDR_LSB) -+#define ROM_S0_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ID) -+#define ROM_S0_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_FLAGS) -+ -+#define NAND_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_CONTROL) -+#define NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_COMPLETE) -+#define NAND_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_STATUS) -+#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define NAND_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ID) -+#define NAND_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_CONTROL) -+#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_COMPLETE) -+#define QSPI_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_STATUS) -+#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define QSPI_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ID) -+#define QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL) -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE) -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS) -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID) -+#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define SRAM_S0_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_CONTROL) -+#define SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_COMPLETE) -+#define SRAM_S0_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_STATUS) -+#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB) -+#define SRAM_S0_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ID) -+#define SRAM_S0_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_FLAGS) -+ -+#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL) -+#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE) -+#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS) -+#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ID) -+#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_CONTROL) -+#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE) -+#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_STATUS) -+#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB) -+#define AXIIC_DS_3_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ID) -+#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS) -+ -+#define APBW_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_CONTROL) -+#define APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_COMPLETE) -+#define APBW_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_STATUS) -+#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define APBW_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ID) -+#define APBW_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define APBX_IDM_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_CONTROL) -+#define APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_COMPLETE) -+#define APBX_IDM_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_STATUS) -+#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB) -+#define APBX_IDM_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ID) -+#define APBX_IDM_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_FLAGS) -+ -+#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_CONTROL) -+#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE) -+#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_STATUS) -+#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB) -+#define AXIIC_DS_0_IDM_ERROR_LOG_ID_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ID) -+#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA IDM_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS) -+ -+#define IDM_ERROR_LOG_ENABLE 0x33A -+#define IDM_ERROR_LOG_CLEAR 0x3 -+ -+#ifdef CONFIG_MACH_IPROC_P7 -+ -+#if defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2) -+#define IHOST_S0_IDM_IRQ 52 -+#define DDR_S1_IDM_IRQ 53 -+#define DDR_S2_IDM_IRQ 54 -+#define AXI_PCIE_S0_IDM_IRQ 55 -+#define ROM_S0_IDM_IRQ 56 -+#define NAND_IDM_IRQ 57 -+#define QSPI_IDM_IRQ 58 -+#define PNOR_IDM_IRQ 59 -+#define SRAM_S0_IDM_IRQ 60 -+#define A9JTAG_S0_IDM_IRQ 61 -+#define APX_IDM_IRQ 64 -+#define CMICD_S0_IDM_IRQ 67 -+#define AXIIC_DS_0_IDM_IRQ 68 -+#define AXIIC_DS_1_IDM_IRQ 69 -+#define AXIIC_DS_2_IDM_IRQ 70 -+#else -+#define IHOST_S0_IDM_IRQ 52 -+#define DDR_S1_IDM_IRQ 54 -+#define DDR_S2_IDM_IRQ 55 -+#define AXI_PCIE_S0_IDM_IRQ 56 -+#define AXI_PCIE_S1_IDM_IRQ 57 -+#define ROM_S0_IDM_IRQ 58 -+#define NAND_IDM_IRQ 59 -+#define QSPI_IDM_IRQ 60 -+#define SRAM_S0_IDM_IRQ 62 -+#define A9JTAG_S0_IDM_IRQ 64 -+#define APX_IDM_IRQ 68 -+#define CMICD_S0_IDM_IRQ 71 -+#define AXIIC_DS_0_IDM_IRQ 78 -+#define AXIIC_DS_1_IDM_IRQ 79 -+#define AXIIC_DS_2_IDM_IRQ 80 -+#define AXIIC_DS_3_IDM_IRQ 81 -+#endif /* defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2) */ -+ -+#else /* CONFIG_MACH_IPROC_P7 */ -+ -+#define IHOST_S1_IDM_IRQ 62 -+#define IHOST_S0_IDM_IRQ 63 -+#define DDR_S1_IDM_IRQ 64 -+#define DDR_S2_IDM_IRQ 65 -+#define AXI_PCIE_S0_IDM_IRQ 66 -+#define AXI_PCIE_S1_IDM_IRQ 67 -+#define CMICD_S0_IDM_IRQ 68 -+#define ROM_S0_IDM_IRQ 69 -+#define NAND_IDM_IRQ 70 -+#define QSPI_IDM_IRQ 71 -+#define A9JTAG_S0_IDM_IRQ 73 -+#define SRAM_S0_IDM_IRQ 74 -+#define APW_IDM_IRQ 75 -+#define APX_IDM_IRQ 76 -+#define APBY_S0_IDM_IRQ 77 -+#define APBZ_S0_IDM_IRQ 78 -+#define AXIIC_DS_0_IDM_IRQ 79 -+#define AXIIC_DS_1_IDM_IRQ 80 -+#define AXIIC_DS_2_IDM_IRQ 81 -+#define AXIIC_DS_3_IDM_IRQ 82 -+#define AXIIC_DS_4_IDM_IRQ 83 -+ -+#endif /* CONFIG_MACH_IPROC_P7 */ -+ -+static irqreturn_t idm_timeout_handler(int val, void *ptr) -+{ -+ u32 errval; -+ -+ printk(KERN_DEBUG "%s: %d, %d entry\n", __func__, __LINE__, val); -+ errval = readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S1_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S1_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S0_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(IHOST_S0_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S1_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S1_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S2_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(DDR_S2_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#if !defined(CONFIG_MACH_IPROC_P7) -+ errval = readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBY_S0_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#endif -+ errval = readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(ROM_S0_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(ROM_S0_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, ROM_S0_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(NAND_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(NAND_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(QSPI_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#if !defined(CONFIG_MACH_IPROC_P7) -+ errval = readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(SRAM_S0_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(SRAM_S0_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#endif -+ -+#if !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2) -+ errval = readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_3_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#endif /* !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2)*/ -+ -+#if !defined(CONFIG_MACH_IPROC_P7) -+ errval = readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBW_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBW_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+#endif -+ errval = readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBX_IDM_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(APBX_IDM_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ errval = readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); -+ if (errval > 0) -+ { -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_0_IDM_ERROR_LOG_ID_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ errval = readl(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA); -+ printk(KERN_DEBUG "%s: %d, %08x\n", __func__, __LINE__, errval); -+ writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA); -+ errval = readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); -+ printk(KERN_DEBUG "%s: %d, %d\n", __func__, __LINE__, errval); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+void init_request_idm_timeout(void) -+{ -+ /* clear all pending idm interrupts */ -+ idm_timeout_handler(0, NULL); -+ -+ /* enable idm error log for all slaves */ -+ -+ writel(IDM_ERROR_LOG_ENABLE, IHOST_S1_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); -+ writel(IDM_ERROR_LOG_ENABLE, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); -+ writel(IDM_ERROR_LOG_ENABLE, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); -+ writel(IDM_ERROR_LOG_ENABLE, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ -+#if !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2) -+ writel(IDM_ERROR_LOG_ENABLE, SRAM_S0_IDM_ERROR_LOG_CONTROL_VA); -+#endif /* !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2)*/ -+ -+#ifndef CONFIG_MACH_IPROC_P7 -+ writel(IDM_ERROR_LOG_ENABLE, APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, APBW_IDM_IDM_ERROR_LOG_CONTROL_VA); -+#endif -+ -+ writel(IDM_ERROR_LOG_ENABLE, ROM_S0_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, NAND_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); -+#if !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2) -+ writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); -+#endif /* !defined(CONFIG_MACH_HR3) && !defined(CONFIG_MACH_GH2) */ -+ writel(IDM_ERROR_LOG_ENABLE, APBX_IDM_IDM_ERROR_LOG_CONTROL_VA); -+ writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA); -+} -+ -+int request_idm_timeout_interrupts(struct device_node *np) -+{ -+ int i, ret, irq; -+ unsigned int irqs_total; -+ -+ init_request_idm_timeout(); -+ -+ irqs_total = of_irq_count(np); -+ if (!irqs_total) -+ return -EINVAL; -+ -+ for (i=0; i -+#include -+#include -+#include -+ -+#define IPROC_DMU_PCU_COMPATIBLE "brcm,iproc-dmu-pcu" -+#define IPROC_WRAP_CTRL_COMPATIBLE "brcm,iproc-wrap-ctrl" -+#define IPROC_IDM_COMPATIBLE "brcm,iproc-idm" -+#define MAX_IDM_NUM 2 -+ -+static void __iomem *iproc_dmu_pcu_base=NULL; -+static void __iomem *iproc_wrap_ctrl_base=NULL; -+static void __iomem *iproc_idm_base[MAX_IDM_NUM]={NULL}; -+static void __iomem *iproc_idm_base_phys[MAX_IDM_NUM]={NULL}; -+ -+ -+extern void request_idm_timeout_interrupts(struct device_node *); -+ -+void inline __iomem *get_iproc_dmu_pcu_base(void) { -+ return iproc_dmu_pcu_base; -+} -+ -+void inline __iomem *get_iproc_wrap_ctrl_base(void) { -+ return iproc_wrap_ctrl_base; -+} -+ -+void inline __iomem *get_iproc_idm_base(int index) { -+ return iproc_idm_base[index]; -+} -+ -+void inline __iomem *get_iproc_idm_base_phys(int index) { -+ return iproc_idm_base_phys[index]; -+} -+ -+int xgs_iproc_wrap_idm_dmu_base_reg_setup(void) -+{ -+ struct device_node *np; -+ -+ /* Get DMU/PCU base addr */ -+ np = of_find_compatible_node(NULL, NULL, IPROC_DMU_PCU_COMPATIBLE); -+ if (!np) { -+ pr_err("%s: No dmu/pcu node found\n", __func__); -+ return -ENODEV ; -+ } -+ iproc_dmu_pcu_base = of_iomap(np, 0); -+ if (!iproc_dmu_pcu_base) -+ return -ENOMEM; -+ -+ /* Get WRAP CTRL base addr */ -+ np = of_find_compatible_node(NULL, NULL, IPROC_WRAP_CTRL_COMPATIBLE); -+ if (!np) { -+ pr_err("%s: No wrap ctrl node found\n", __func__); -+ return -ENODEV; -+ } -+ iproc_wrap_ctrl_base = of_iomap(np, 0); -+ if (!iproc_wrap_ctrl_base) -+ return -ENOMEM; -+ -+ /* Get IDM base addr */ -+ np = of_find_compatible_node(NULL, NULL, IPROC_IDM_COMPATIBLE); -+ if (!np) { -+ pr_err("%s: No IDM node found\n", __func__); -+ return -ENODEV; -+ } -+ iproc_idm_base[0] = of_iomap(np, 0); -+ if (!iproc_idm_base[0]) -+ return -ENOMEM; -+ -+ /* Second IDM base addr required for GH/SB2/GH2 IDM timeout handling. -+ * For other devices, the second IDM base addr is not used. So, it is -+ * fine even the addr is NULL. -+ */ -+ iproc_idm_base[1] = of_iomap(np, 1); -+ -+ return 1; -+} -+ -+void xgs_iproc_idm_timeout_handler_setup(void) -+{ -+ struct device_node *np; -+ struct platform_device *pdev=NULL; -+ struct resource *res_mem; -+ -+ /* To get IDM phys addr */ -+ np = of_find_compatible_node(NULL, NULL, IPROC_IDM_COMPATIBLE); -+ if (!np) { -+ pr_warn("%s: No IDM node found\n", __func__); -+ return; -+ } -+ pdev = of_find_device_by_node(np); -+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res_mem) { -+ pr_warn("%s: No resource found\n", __func__); -+ return; -+ } -+ iproc_idm_base_phys[0] = (void __iomem *)res_mem->start; -+ -+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ /* Only GH/SB2/GH2 has second IDM base addr */ -+ if (res_mem) -+ iproc_idm_base_phys[1] = (void __iomem *)res_mem->start; -+ -+ /* register IDM timeout interrupt handler */ -+ request_idm_timeout_interrupts(np); -+} -\ No newline at end of file -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/spi/Kconfig b/drivers/spi/Kconfig ---- a/drivers/spi/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/spi/Kconfig 2017-11-09 17:53:55.798375000 +0800 -@@ -654,6 +654,74 @@ config SPI_NUC900 - help - SPI driver for Nuvoton NUC900 series ARM SoCs - -+config SPI_XGS_IPROC -+ tristate "BRCM XGS iProc QSPI support" -+ depends on ARCH_XGS_IPROC -+ default n -+ help -+ This selects a driver for the iProc QSPI Controller (for serial flash). -+ -+ If unsure, say N. -+ -+if SPI_XGS_IPROC -+ -+choice -+ prompt "Multi I/O SPI support" -+ default IPROC_QSPI_SINGLE_MODE -+ help -+ Number of (multi I/O) data lanes supported by the SPI flash. -+ -+config IPROC_QSPI_SINGLE_MODE -+ bool "Single lane" -+ help -+ Single lane. -+ -+config IPROC_QSPI_DUAL_MODE -+ bool "Dual mode" -+ help -+ Dual mode. -+ -+config IPROC_QSPI_QUAD_MODE -+ bool "Quad mode" -+ help -+ Quad mode. -+ -+endchoice -+ -+config IPROC_QSPI_MULTI_LANE_ADDR -+ bool "Use multi lanes also for address" -+ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE -+ default y -+ help -+ Use multi lanes also for address. -+ -+config IPROC_QSPI_READ_CMD -+ hex "Flash opcode for multi I/O read" -+ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE -+ range 0x00 0xff -+ default 0xbb if IPROC_QSPI_DUAL_MODE -+ default 0xeb -+ help -+ Flash opcode to send to flash for multip I/O read. -+ -+config IPROC_QSPI_READ_DUMMY_CYCLES -+ int "Dummy cycles for multi I/O read operation" -+ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE -+ range 0 255 -+ default 8 if IPROC_QSPI_DUAL_MODE -+ default 10 -+ help -+ Dummy cycles for flash read operation -+ -+config IPROC_QSPI_MAX_HZ -+ int "Maximal SPI clock in HZ" -+ range 1 1000000000 -+ default 62500000 -+ help -+ The maximal SPI clock (in Hz) supported by the flash. -+ -+endif # SPI_XGS_IPROC -+ - # - # Add new SPI master controllers in alphabetical order above this line - # -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/spi/Makefile b/drivers/spi/Makefile ---- a/drivers/spi/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/spi/Makefile 2017-11-09 17:53:55.799375000 +0800 -@@ -93,3 +93,5 @@ obj-$(CONFIG_SPI_XILINX) += spi-xilinx. - obj-$(CONFIG_SPI_XLP) += spi-xlp.o - obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o - obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o -+obj-$(CONFIG_SPI_XGS_IPROC) += spi-xgs-iproc.o -+ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/spi/spi-xgs-iproc.c b/drivers/spi/spi-xgs-iproc.c ---- a/drivers/spi/spi-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/spi/spi-xgs-iproc.c 2017-11-09 17:53:55.932382000 +0800 -@@ -0,0 +1,1982 @@ -+/* -+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_OF -+#include -+#include -+#include -+#include -+#endif -+ -+#define DBG(...) /* */ -+ -+/* -+ * Interrupts -+ */ -+ -+#define QSPI_INTR_COUNT (7) -+ -+#define QSPI_INTR_MSPI_HALTED_MASK (0x00000040) -+#define QSPI_INTR_MSPI_DONE_MASK (0x00000020) -+#define QSPI_INTR_BSPI_LR_OVERREAD_MASK (0x00000010) -+#define QSPI_INTR_BSPI_LR_SESSION_DONE_MASK (0x00000008) -+#define QSPI_INTR_BSPI_LR_IMPATIENT_MASK (0x00000004) -+#define QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK (0x00000002) -+#define QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK (0x00000001) -+ -+#define BSPI_LR_INTERRUPTS_DATA \ -+ (QSPI_INTR_BSPI_LR_SESSION_DONE_MASK | \ -+ QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK) -+ -+#define BSPI_LR_INTERRUPTS_ERROR \ -+ (QSPI_INTR_BSPI_LR_OVERREAD_MASK | \ -+ QSPI_INTR_BSPI_LR_IMPATIENT_MASK | \ -+ QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK) -+ -+#define BSPI_LR_INTERRUPTS_ALL \ -+ (BSPI_LR_INTERRUPTS_ERROR | \ -+ BSPI_LR_INTERRUPTS_DATA) -+ -+#define SPBR_MIN 8U -+#define SPBR_MAX 255U -+#define DEFAULT_SPEED_HZ 25000000UL -+#define MSPI_REFCLK_SOURCE "c_clk125" /* To be doubled */ -+#define MSPI_REFCLK_SOURCE_DEVID "iproc_slow" -+ -+/* -+ * Flash opcode and parameters -+ */ -+#define OPCODE_RDID 0x9f -+#define OPCODE_WREN 0x06 -+#define OPCODE_WRDI 0x04 -+#define OPCODE_WRR 0x01 -+#define OPCODE_RCR 0x35 -+#define OPCODE_READ 0x03 -+#define OPCODE_RDSR 0x05 -+#define OPCODE_WRSR 0x01 -+#define OPCODE_RDFSR 0x70 -+#define OPCODE_FAST_READ 0x0B -+#define OPCODE_FAST_READ_4B 0x0C -+#define OPCODE_EN4B 0xB7 -+#define OPCODE_EX4B 0xE9 -+#define OPCODE_BRWR 0x17 -+ -+#define BSPI_WIDTH_1BIT 1 -+#define BSPI_WIDTH_2BIT 2 -+#define BSPI_WIDTH_4BIT 4 -+ -+#define BSPI_ADDRLEN_3BYTES 3 -+#define BSPI_ADDRLEN_4BYTES 4 -+ -+#define BSPI_FLASH_TYPE_SPANSION 0 -+#define BSPI_FLASH_TYPE_MACRONIX 1 -+#define BSPI_FLASH_TYPE_NUMONYX 2 -+#define BSPI_FLASH_TYPE_SST 3 -+#define BSPI_FLASH_TYPE_UNKNOWN -1 -+ -+/* -+ * Register masks/fields/values -+ */ -+#define QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK (0x00000002) -+#define QSPI_BSPI_RAF_CONTROL_START_MASK (0x00000001) -+#define QSPI_BSPI_RAF_CONTROL_CLEAR_MASK (0x00000002) -+#define QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK (0x00010000) -+#define QSPI_BSPI_BPP_MODE_BPP_MASK (0x00000100) -+#define QSPI_BSPI_FLEX_MODE_ENABLE_MASK (0x00000001) -+ -+ -+/* -+ * Module parameters -+ */ -+ -+/* Mulit I/O for read: 0 - single, 1 - dual, 2 - quad */ -+#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE -+static int io_mode = 0; -+#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+#ifdef CONFIG_IPROC_QSPI_DUAL_MODE -+static int io_mode = 1; -+#else /* !CONFIG_IPROC_QSPI_DUAL_MODE */ -+static int io_mode = 2; -+#endif /* !CONFIG_IPROC_QSPI_DUAL_MODE */ -+#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+module_param(io_mode, int, 0444); -+ -+/* Multi I/O for address (only if not in single mode) */ -+#ifdef CONFIG_IPROC_QSPI_MULTI_LANE_ADDR -+static int addr_multi = 1; -+#else /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ -+static int addr_multi = 0; -+#endif /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ -+module_param(addr_multi, int, 0444); -+ -+/* Read opcode (only if not in single mode) */ -+#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE -+static int read_opcode = OPCODE_FAST_READ; -+#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+static int read_opcode = CONFIG_IPROC_QSPI_READ_CMD; -+#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+module_param(read_opcode, int, 0444); -+ -+/* Dummy cycles for read (only if not in single mode) */ -+#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE -+static int dummy_cycles = 8; -+#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+static int dummy_cycles = CONFIG_IPROC_QSPI_READ_DUMMY_CYCLES; -+#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ -+module_param(dummy_cycles, int, 0444); -+ -+/* Max SPI clock HZ */ -+static int max_hz = 0; -+module_param(max_hz, int, 0444); -+ -+/* Spansion high performance mode */ -+static int bspi_hp; -+module_param(bspi_hp, int, 0444); -+ -+struct brcmspi_platform_data { -+ int flash_cs; -+}; -+ -+struct bcmspi_parms { -+ u32 speed_hz; -+ u8 chip_select; -+ u8 mode; -+ u8 bits_per_word; -+}; -+ -+struct position { -+ struct spi_message *msg; -+ struct spi_transfer *trans; -+ int byte; -+ int mspi_16bit; -+}; -+ -+#define NUM_TXRAM 32 -+#define NUM_RXRAM 32 -+#define NUM_CDRAM 16 -+ -+struct bcm_mspi_hw { -+ u32 spcr0_lsb; /* 0x000 */ -+ u32 spcr0_msb; /* 0x004 */ -+ u32 spcr1_lsb; /* 0x008 */ -+ u32 spcr1_msb; /* 0x00c */ -+ u32 newqp; /* 0x010 */ -+ u32 endqp; /* 0x014 */ -+ u32 spcr2; /* 0x018 */ -+ u32 reserved0; /* 0x01c */ -+ u32 mspi_status; /* 0x020 */ -+ u32 cptqp; /* 0x024 */ -+ u32 reserved1[6]; /* 0x028 */ -+ u32 txram[NUM_TXRAM]; /* 0x040 */ -+ u32 rxram[NUM_RXRAM]; /* 0x0c0 */ -+ u32 cdram[NUM_CDRAM]; /* 0x140 */ -+ u32 write_lock; /* 0x180 */ -+ u32 disable_flush_gen; /* 0x184 */ -+}; -+ -+struct bcm_bspi_hw { -+ u32 revision_id; /* 0x000 */ -+ u32 scratch; /* 0x004 */ -+ u32 mast_n_boot_ctrl; /* 0x008 */ -+ u32 busy_status; /* 0x00c */ -+ u32 intr_status; /* 0x010 */ -+ u32 b0_status; /* 0x014 */ -+ u32 b0_ctrl; /* 0x018 */ -+ u32 b1_status; /* 0x01c */ -+ u32 b1_ctrl; /* 0x020 */ -+ u32 strap_override_ctrl; /* 0x024 */ -+ u32 flex_mode_enable; /* 0x028 */ -+ u32 bits_per_cycle; /* 0x02C */ -+ u32 bits_per_phase; /* 0x030 */ -+ u32 cmd_and_mode_byte; /* 0x034 */ -+ u32 flash_upper_addr_byte; /* 0x038 */ -+ u32 xor_value; /* 0x03C */ -+ u32 xor_enable; /* 0x040 */ -+ u32 pio_mode_enable; /* 0x044 */ -+ u32 pio_iodir; /* 0x048 */ -+ u32 pio_data; /* 0x04C */ -+}; -+ -+struct bcm_bspi_raf { -+ u32 start_address; /* 0x00 */ -+ u32 num_words; /* 0x04 */ -+ u32 ctrl; /* 0x08 */ -+ u32 fullness; /* 0x0C */ -+ u32 watermark; /* 0x10 */ -+ u32 status; /* 0x14 */ -+ u32 read_data; /* 0x18 */ -+ u32 word_cnt; /* 0x1C */ -+ u32 curr_addr; /* 0x20 */ -+}; -+ -+struct bcm_idm_qspi_ctrl { -+ u32 io_ctrl_direct; -+}; -+ -+struct bcm_cru_control { -+ u32 cru_control; -+}; -+ -+struct bcm_flex_mode { -+ int width; -+ int addrlen; -+ int hp; -+}; -+ -+#define STATE_IDLE 0 -+#define STATE_RUNNING 1 -+#define STATE_SHUTDOWN 2 -+ -+struct bcmspi_priv { -+ struct platform_device *pdev; -+ struct spi_master *master; -+ spinlock_t lock; -+ struct bcmspi_parms last_parms; -+ struct position pos; -+ struct list_head msg_queue; -+ int state; -+ int outstanding_bytes; -+ int next_udelay; -+ int cs_change; -+ unsigned int mspi_refclk; -+ unsigned int max_speed_hz; -+ volatile struct bcm_mspi_hw *mspi_hw; -+ int irq; -+ struct tasklet_struct tasklet; -+ int curr_cs; -+ -+ /* BSPI */ -+ volatile struct bcm_bspi_hw *bspi_hw; -+ volatile struct bcm_cru_control *cru_hw; -+ int bspi_enabled; -+ /* all chip selects controlled by BSPI */ -+ int bspi_chip_select; -+ -+ /* LR */ -+ volatile struct bcm_bspi_raf *bspi_hw_raf; -+ struct spi_transfer *cur_xfer; -+ u32 cur_xfer_idx; -+ u32 cur_xfer_len; -+ u32 xfer_status; -+ struct spi_message *cur_msg; -+ u32 actual_length; -+ u32 raf_next_addr; -+ u32 raf_next_len; -+ -+ /* Interrupts */ -+ volatile u32 *qspi_intr; -+ volatile struct bcm_idm_qspi_ctrl *idm_qspi; -+ -+ /* current flex mode settings */ -+ struct bcm_flex_mode flex_mode; -+}; -+ -+static void bcmspi_enable_interrupt(struct bcmspi_priv *priv, u32 mask) -+{ -+ priv->idm_qspi->io_ctrl_direct |= cpu_to_le32(mask << 2); -+} -+ -+static void bcmspi_disable_interrupt(struct bcmspi_priv *priv, u32 mask) -+{ -+ priv->idm_qspi->io_ctrl_direct &= cpu_to_le32(~(mask << 2)); -+} -+ -+static void bcmspi_clear_interrupt(struct bcmspi_priv *priv, u32 mask) -+{ -+ int i; -+ -+ for(i=0; iqspi_intr[i] = cpu_to_le32(1); -+ } -+ } -+} -+ -+static u32 bcmspi_read_interrupt(struct bcmspi_priv *priv) -+{ -+ int i; -+ u32 status = 0; -+ -+ for(i=0; iqspi_intr[i] & cpu_to_le32(1)) { -+ status |= 1UL << i; -+ } -+ } -+ -+ return status; -+} -+ -+static void bcmspi_flush_prefetch_buffers(struct bcmspi_priv *priv) -+{ -+ priv->bspi_hw->b0_ctrl = 0; -+ priv->bspi_hw->b1_ctrl = 0; -+ priv->bspi_hw->b0_ctrl = cpu_to_le32(1); -+ priv->bspi_hw->b1_ctrl = cpu_to_le32(1); -+} -+ -+static int bcmspi_lr_is_fifo_empty(struct bcmspi_priv *priv) -+{ -+ return priv->bspi_hw_raf->status & cpu_to_le32(QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK); -+} -+ -+static inline u32 bcmspi_lr_read_fifo(struct bcmspi_priv *priv) -+{ -+ /* for performance reasons return the raw data, rather than -+ * byte-swapped data. This works because the caller writes -+ * values 32-bits at a time to the destination buffer, giving -+ * an automatic byte-swap on big-endian machines. */ -+ -+ return priv->bspi_hw_raf->read_data; -+} -+ -+static inline void bcmspi_lr_start(struct bcmspi_priv *priv) -+{ -+ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_START_MASK); -+} -+ -+static inline void bcmspi_lr_clear(struct bcmspi_priv *priv) -+{ -+ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_CLEAR_MASK); -+ bcmspi_flush_prefetch_buffers(priv); -+} -+ -+static inline int bcmspi_is_4_byte_mode(struct bcmspi_priv *priv) -+{ -+ return priv->flex_mode.addrlen == BSPI_ADDRLEN_4BYTES; -+} -+ -+static int bcmbspi_flash_type(struct bcmspi_priv *priv); -+ -+static int bcmspi_set_flex_mode(struct bcmspi_priv *priv, -+ int width, int addrlen, int hp) -+{ -+ int bpc = 0, bpp = dummy_cycles, command = read_opcode; -+ int flex_mode = 1, error = 0; -+ -+ switch (width) { -+ case BSPI_WIDTH_1BIT: -+ if (addrlen == BSPI_ADDRLEN_3BYTES) { -+ /* default mode, does not need flex_cmd */ -+ flex_mode = 0; -+ } else { -+ bpp = 8; /* dummy cycles */ -+ //if (bcmbspi_flash_type(priv) == BSPI_FLASH_TYPE_SPANSION) -+ // command = OPCODE_FAST_READ_4B; -+ //else -+ command = OPCODE_FAST_READ; -+ } -+ break; -+ case BSPI_WIDTH_2BIT: -+ bpc = 0x00000001; /* only data is 2-bit */ -+ if (addr_multi) { -+ bpc |= 0x00010000; -+ } -+ if (hp) { -+ bpc |= 0x00010100; /* address and mode are 2-bit too */ -+ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; -+ } -+ break; -+ case BSPI_WIDTH_4BIT: -+ bpc = 0x00000002; /* only data is 4-bit */ -+ if (addr_multi) { -+ bpc |= 0x00020000; -+ } -+ if (hp) { -+ bpc |= 0x00020200; /* address and mode are 4-bit too */ -+ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; -+ } -+ break; -+ default: -+ error = 1; -+ break; -+ } -+ -+ if (addrlen == BSPI_ADDRLEN_4BYTES) { -+ bpp |= QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK; -+ } -+ -+ if (!error) { -+ priv->bspi_hw->flex_mode_enable = 0; -+ priv->bspi_hw->bits_per_cycle = cpu_to_le32(bpc); -+ priv->bspi_hw->bits_per_phase = cpu_to_le32(bpp); -+ priv->bspi_hw->cmd_and_mode_byte = cpu_to_le32(command); -+ priv->bspi_hw->flex_mode_enable = flex_mode ? -+ cpu_to_le32(QSPI_BSPI_FLEX_MODE_ENABLE_MASK) -+ : 0; -+ DBG("%s: width=%d addrlen=%d hp=%d\n", -+ __func__, width, addrlen, hp); -+ DBG("%s: fme=%08x bpc=%08x bpp=%08x cmd=%08x\n", __func__, -+ le32_to_cpu(priv->bspi_hw->flex_mode_enable), -+ le32_to_cpu(priv->bspi_hw->bits_per_cycle), -+ le32_to_cpu(priv->bspi_hw->bits_per_phase), -+ le32_to_cpu(priv->bspi_hw->cmd_and_mode_byte)); -+ } -+ -+ return error; -+} -+ -+static void bcmspi_set_mode(struct bcmspi_priv *priv, -+ int width, int addrlen, int hp) -+{ -+ int error = 0; -+ int show_info = 0; -+ -+ if ((width != -1 && width != priv->flex_mode.width) || -+ (hp != -1 && hp != priv->flex_mode.hp)) { -+ /* Don't print things if only for address mode change because it -+ * could be very frequent. */ -+ show_info = 1; -+ } -+ if (width == -1) -+ width = priv->flex_mode.width; -+ if (addrlen == -1) -+ addrlen = priv->flex_mode.addrlen; -+ if (hp == -1) -+ hp = priv->flex_mode.hp; -+ -+ error = bcmspi_set_flex_mode(priv, width, addrlen, hp); -+ -+ if (!error) { -+ priv->flex_mode.width = width; -+ priv->flex_mode.addrlen = addrlen; -+ priv->flex_mode.hp = hp; -+ if (show_info) { -+ dev_info(&priv->pdev->dev, -+ "%d-lane output, %d-byte address%s\n", -+ priv->flex_mode.width, -+ priv->flex_mode.addrlen, -+ priv->flex_mode.hp ? ", high-performance mode" : ""); -+ } -+ } else -+ dev_warn(&priv->pdev->dev, -+ "INVALID COMBINATION: width=%d addrlen=%d hp=%d\n", -+ width, addrlen, hp); -+} -+ -+static void bcmspi_set_chip_select(struct bcmspi_priv *priv, int cs) -+{ -+ if (priv->curr_cs != cs) { -+ DBG("Switching CS%1d => CS%1d\n", -+ priv->curr_cs, cs); -+ -+ /* We don't have multiple chip selects for now */ -+ } -+ priv->curr_cs = cs; -+ -+} -+ -+static inline int is_bspi_chip_select(struct bcmspi_priv *priv, u8 cs) -+{ -+ return priv->bspi_chip_select & (1 << cs); -+} -+ -+static void bcmspi_disable_bspi(struct bcmspi_priv *priv) -+{ -+ int i; -+ -+ if (!priv->bspi_hw || !priv->bspi_enabled) -+ return; -+ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 1) { -+ priv->bspi_enabled = 0; -+ return; -+ } -+ -+ DBG("disabling bspi\n"); -+ for (i = 0; i < 1000; i++) { -+ if ((priv->bspi_hw->busy_status & cpu_to_le32(1)) == 0) { -+ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); -+ priv->bspi_enabled = 0; -+ udelay(1); -+ return; -+ } -+ udelay(1); -+ } -+ dev_warn(&priv->pdev->dev, "timeout setting MSPI mode\n"); -+} -+ -+static void bcmspi_enable_bspi(struct bcmspi_priv *priv) -+{ -+ if (!priv->bspi_hw || priv->bspi_enabled) -+ return; -+ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 0) { -+ priv->bspi_enabled = 1; -+ return; -+ } -+ -+ DBG("enabling bspi\n"); -+ priv->bspi_hw->mast_n_boot_ctrl = 0; -+ priv->bspi_enabled = 1; -+} -+ -+static void bcmspi_hw_set_parms(struct bcmspi_priv *priv, -+ const struct bcmspi_parms *xp) -+{ -+ if (xp->speed_hz) { -+ unsigned int spbr = priv->mspi_refclk / (2 * xp->speed_hz); -+ -+ priv->mspi_hw->spcr0_lsb = cpu_to_le32(max(min(spbr, SPBR_MAX), SPBR_MIN)); -+ } else { -+ priv->mspi_hw->spcr0_lsb = cpu_to_le32(SPBR_MIN); -+ } -+ -+ if (priv->pos.msg == NULL || xp->bits_per_word > 8) { -+ /* Global hw init for 16bit spi_transfer */ -+ int bits = xp->bits_per_word; -+ bits = bits? (bits == 16? 0 : bits) : 8; -+ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ -+ (bits << 2) | -+ (xp->mode & 3)); -+ } else { -+ /* Configure for a new 8-bit spi_transfer */ -+ if (priv->pos.byte == 0) { -+ /* Use 16-bit MSPI transfer for performance if applicable */ -+ if (priv->pos.mspi_16bit ^ (!(priv->pos.trans->len & 1))) { -+ /* Update it only if needed */ -+ priv->pos.mspi_16bit = !priv->pos.mspi_16bit; -+ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ -+ ((priv->pos.mspi_16bit? 0 : 8) << 2) | -+ (xp->mode & 3)); -+ } -+ } -+ } -+ priv->last_parms = *xp; -+} -+ -+#define PARMS_NO_OVERRIDE 0 -+#define PARMS_OVERRIDE 1 -+ -+static int bcmspi_update_parms(struct bcmspi_priv *priv, -+ struct spi_device *spidev, struct spi_transfer *trans, int override) -+{ -+ struct bcmspi_parms xp; -+ -+ xp.speed_hz = min(trans->speed_hz ? trans->speed_hz : -+ (spidev->max_speed_hz ? spidev->max_speed_hz : DEFAULT_SPEED_HZ), -+ DEFAULT_SPEED_HZ); -+ xp.chip_select = spidev->chip_select; -+ xp.mode = spidev->mode; -+ xp.bits_per_word = trans->bits_per_word ? trans->bits_per_word : -+ (spidev->bits_per_word ? spidev->bits_per_word : 8); -+ -+ if ((override == PARMS_OVERRIDE) || -+ ((xp.speed_hz == priv->last_parms.speed_hz) && -+ (xp.chip_select == priv->last_parms.chip_select) && -+ (xp.mode == priv->last_parms.mode) && -+ (xp.bits_per_word == priv->last_parms.bits_per_word))) { -+ bcmspi_hw_set_parms(priv, &xp); -+ return 0; -+ } -+ /* no override, and parms do not match */ -+ return 1; -+} -+ -+ -+static int bcmspi_setup(struct spi_device *spi) -+{ -+ struct bcmspi_parms *xp; -+ struct bcmspi_priv *priv = spi_master_get_devdata(spi->master); -+ unsigned int speed_hz; -+ -+ DBG("%s\n", __func__); -+ -+ if (spi->bits_per_word > 16) -+ return -EINVAL; -+ -+ /* Module parameter override */ -+ if (max_hz != 0) { -+ speed_hz = max_hz; -+ } else { -+ speed_hz = spi->max_speed_hz; -+ } -+ -+ xp = spi_get_ctldata(spi); -+ if (!xp) { -+ xp = kzalloc(sizeof(struct bcmspi_parms), GFP_KERNEL); -+ if (!xp) -+ return -ENOMEM; -+ spi_set_ctldata(spi, xp); -+ } -+ if (speed_hz < priv->max_speed_hz) -+ xp->speed_hz = speed_hz; -+ else -+ xp->speed_hz = 0; -+ -+ priv->cru_hw->cru_control &= cpu_to_le32(~0x00000006); -+ (void)priv->cru_hw->cru_control; /* Need to read back */ -+ if (speed_hz >= 62500000) { -+ priv->cru_hw->cru_control |= cpu_to_le32(0x00000006); -+ } else if (speed_hz >= 50000000) { -+ priv->cru_hw->cru_control |= cpu_to_le32(0x00000002); -+ } else if (speed_hz >= 31250000) { -+ priv->cru_hw->cru_control |= cpu_to_le32(0x00000004); -+ } -+ (void)priv->cru_hw->cru_control; /* Need to read back */ -+ -+ xp->chip_select = spi->chip_select; -+ xp->mode = spi->mode; -+ xp->bits_per_word = spi->bits_per_word ? spi->bits_per_word : 8; -+ -+ return 0; -+} -+ -+/* stop at end of transfer, no other reason */ -+#define FNB_BREAK_NONE 0 -+/* stop at end of spi_message */ -+#define FNB_BREAK_EOM 1 -+/* stop at end of spi_transfer if delay */ -+#define FNB_BREAK_DELAY 2 -+/* stop at end of spi_transfer if cs_change */ -+#define FNB_BREAK_CS_CHANGE 4 -+/* stop if we run out of bytes */ -+#define FNB_BREAK_NO_BYTES 8 -+/* stop at end of spi_transfer */ -+#define FNB_BREAK_EOT 16 -+ -+/* events that make us stop filling TX slots */ -+#define FNB_BREAK_TX (FNB_BREAK_EOM | FNB_BREAK_DELAY | \ -+ FNB_BREAK_CS_CHANGE) -+ -+/* events that make us deassert CS */ -+#define FNB_BREAK_DESELECT (FNB_BREAK_EOM | FNB_BREAK_CS_CHANGE) -+ -+ -+static int find_next_byte(struct bcmspi_priv *priv, struct position *p, -+ struct list_head *completed, int flags) -+{ -+ int ret = FNB_BREAK_NONE; -+ -+ p->byte++; -+ -+ while (p->byte >= p->trans->len) { -+ /* we're at the end of the spi_transfer */ -+ -+ /* in TX mode, need to pause for a delay or CS change */ -+ if (p->trans->delay_usecs && (flags & FNB_BREAK_DELAY)) -+ ret |= FNB_BREAK_DELAY; -+ if (p->trans->cs_change && (flags & FNB_BREAK_CS_CHANGE)) -+ ret |= FNB_BREAK_CS_CHANGE; -+ if (ret) -+ return ret; -+ -+ /* advance to next spi_message? */ -+ if (list_is_last(&p->trans->transfer_list, -+ &p->msg->transfers)) { -+ struct spi_message *next_msg = NULL; -+ -+ /* TX breaks at the end of each message as well */ -+ if (!completed || (flags & FNB_BREAK_EOM)) { -+ DBG("find_next_byte: advance msg exit\n"); -+ return FNB_BREAK_EOM; -+ } -+ if (!list_is_last(&p->msg->queue, &priv->msg_queue)) { -+ next_msg = list_entry(p->msg->queue.next, -+ struct spi_message, queue); -+ } -+ /* delete from run queue, add to completion queue */ -+ list_del(&p->msg->queue); -+ list_add_tail(&p->msg->queue, completed); -+ -+ p->msg = next_msg; -+ p->byte = 0; -+ if (p->msg == NULL) { -+ p->trans = NULL; -+ ret = FNB_BREAK_NO_BYTES; -+ break; -+ } -+ -+ /* -+ * move on to the first spi_transfer of the new -+ * spi_message -+ */ -+ p->trans = list_entry(p->msg->transfers.next, -+ struct spi_transfer, transfer_list); -+ } else { -+ /* or just advance to the next spi_transfer */ -+ p->trans = list_entry(p->trans->transfer_list.next, -+ struct spi_transfer, transfer_list); -+ p->byte = 0; -+ -+ /* Separate spi_transfers into MSPI transfers */ -+ ret = FNB_BREAK_EOT; -+ } -+ } -+ DBG("find_next_byte: msg %p trans %p len %d byte %d ret %x\n", -+ p->msg, p->trans, p->trans ? p->trans->len : 0, p->byte, ret); -+ return ret; -+} -+ -+static void read_from_hw(struct bcmspi_priv *priv, struct list_head *completed) -+{ -+ struct position p; -+ int slot = 0, n = priv->outstanding_bytes; -+ -+ DBG("%s\n", __func__); -+ -+ p = priv->pos; -+ -+ while (n > 0) { -+ BUG_ON(p.msg == NULL); -+ -+ if (p.trans->bits_per_word <= 8) { -+ u8 *buf = p.trans->rx_buf; -+ -+ if (buf) { -+ -+ if (p.mspi_16bit) { -+ /* Using 16-bit SPI transfers for performance */ -+ buf[p.byte] = -+ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0]) & 0xff; -+ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); -+ buf[p.byte + 1] = -+ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; -+ DBG("RD %02x\n", buf ? buf[p.byte + 1] : 0xff); -+ } else { -+ buf[p.byte] = -+ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; -+ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); -+ } -+ } -+ } else { -+ u16 *buf = p.trans->rx_buf; -+ -+ if (buf) { -+ buf[p.byte] = -+ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff) << 0) | -+ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0] & 0xff)) << 8); -+ DBG("RD %04x\n", buf ? buf[p.byte] : 0xffff); -+ } -+ } -+ slot++; -+ n--; -+ p.msg->actual_length++; -+ if (p.mspi_16bit) { -+ p.byte++; -+ p.msg->actual_length++; -+ } -+ -+ find_next_byte(priv, &p, completed, FNB_BREAK_NONE); -+ } -+ -+ priv->pos = p; -+ priv->outstanding_bytes = 0; -+} -+ -+static void write_to_hw(struct bcmspi_priv *priv) -+{ -+ struct position p; -+ int slot = 0, fnb = 0; -+ struct spi_message *msg = NULL; -+ -+ DBG("%s\n", __func__); -+ -+ bcmspi_disable_bspi(priv); -+ -+ p = priv->pos; -+ -+ while (1) { -+ if (p.msg == NULL) -+ break; -+ if (!msg) { -+ msg = p.msg; -+ bcmspi_update_parms(priv, msg->spi, p.trans, -+ PARMS_OVERRIDE); -+ } else { -+ /* break if the speed, bits, etc. changed */ -+ if (bcmspi_update_parms(priv, msg->spi, p.trans, -+ PARMS_NO_OVERRIDE)) { -+ DBG("parms don't match, breaking\n"); -+ break; -+ } -+ } -+ if (p.trans->bits_per_word <= 8) { -+ const u8 *buf = p.trans->tx_buf; -+ -+ priv->mspi_hw->txram[slot << 1] = -+ cpu_to_le32(buf ? (buf[p.byte] & 0xff) : 0xff); -+ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); -+ -+ if (priv->pos.mspi_16bit) { -+ /* Using 16-bit SPI transfers for performance */ -+ p.byte++; -+ priv->mspi_hw->txram[(slot << 1) + 1] = -+ cpu_to_le32(buf ? (buf[p.byte] & 0xff) : 0xff); -+ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); -+ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); -+ } else { -+ priv->mspi_hw->cdram[slot] = cpu_to_le32(0x8e); -+ } -+ -+ } else { -+ const u16 *buf = p.trans->tx_buf; -+ -+ priv->mspi_hw->txram[(slot << 1) + 0] = -+ cpu_to_le32(buf ? (buf[p.byte] >> 8) : 0xff); -+ priv->mspi_hw->txram[(slot << 1) + 1] = -+ cpu_to_le32(buf ? (buf[p.byte] & 0xff) : 0xff); -+ DBG("WR %04x\n", buf ? buf[p.byte] : 0xffff); -+ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); -+ } -+ slot++; -+ -+ fnb = find_next_byte(priv, &p, NULL, FNB_BREAK_TX); -+ -+ if (fnb & FNB_BREAK_CS_CHANGE) -+ priv->cs_change = 1; -+ if (fnb & FNB_BREAK_DELAY) -+ priv->next_udelay = p.trans->delay_usecs; -+ if (fnb || (slot == NUM_CDRAM)) -+ break; -+ } -+ -+ if (slot) { -+ DBG("submitting %d slots\n", slot); -+ priv->mspi_hw->newqp = 0; -+ priv->mspi_hw->endqp = cpu_to_le32(slot - 1); -+ -+ /* deassert CS on the final byte */ -+ if (fnb & FNB_BREAK_DESELECT) -+ priv->mspi_hw->cdram[slot - 1] &= cpu_to_le32(~0x80); -+ -+ /* tell HIF_MSPI which CS to use */ -+ bcmspi_set_chip_select(priv, msg->spi->chip_select); -+ -+ priv->mspi_hw->write_lock = cpu_to_le32(1); -+ priv->mspi_hw->spcr2 = cpu_to_le32(0xe0); /* cont | spe | spifie */ -+ -+ priv->state = STATE_RUNNING; -+ priv->outstanding_bytes = slot; -+ } else { -+ priv->mspi_hw->write_lock = 0; -+ priv->state = STATE_IDLE; -+ } -+} -+ -+#define DWORD_ALIGNED(a) (!(((unsigned long)(a)) & 3)) -+#define ACROSS_16MB(a, l) (((a) ^ ((a) + (l) - 1)) & 0xFF000000) -+ -+static int bcmspi_emulate_flash_read(struct bcmspi_priv *priv, -+ struct spi_message *msg) -+{ -+ u32 addr, len; -+ int idx = 0; /* Also used for checking continuation */ -+ unsigned long flags = 0; -+ -+ /* Check if it's a continuation */ -+ if (priv->raf_next_len != 0) { -+ -+ /* Continuation (read across 16MB boundary) */ -+ addr = priv->raf_next_addr; -+ len = priv->raf_next_len; -+ -+ /* Update upper address byte */ -+ if (bcmspi_is_4_byte_mode(priv)) { -+ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); -+ /* Flush prefecth buffers since upper byte changed */ -+ bcmspi_flush_prefetch_buffers(priv); -+ } -+ -+ } else { -+ -+ /* It's the first session of this transfer */ -+ struct spi_transfer *trans; -+ u8 *buf; -+ -+ /* acquire lock when the MSPI is idle */ -+ while (1) { -+ spin_lock_irqsave(&priv->lock, flags); -+ if (priv->state == STATE_IDLE) -+ break; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ if (priv->state == STATE_SHUTDOWN) -+ return -EIO; -+ udelay(1); -+ } -+ bcmspi_set_chip_select(priv, msg->spi->chip_select); -+ -+ /* first transfer - OPCODE_READ + 3-byte address */ -+ trans = list_entry(msg->transfers.next, struct spi_transfer, -+ transfer_list); -+ buf = (void *)trans->tx_buf; -+ -+ idx = 1; -+ -+ /* Check upper address byte for 4-byte mode */ -+ if (bcmspi_is_4_byte_mode(priv)) { -+ addr = buf[idx++] << 24; -+ } else { -+ addr = 0; -+ } -+ -+ /* -+ * addr coming into this function is a raw flash offset -+ * we need to convert it to the BSPI address -+ */ -+ addr |= (buf[idx] << 16) | (buf[idx+1] << 8) | buf[idx+2]; -+ -+ /* second transfer - read result into buffer */ -+ trans = list_entry(msg->transfers.next->next, struct spi_transfer, -+ transfer_list); -+ -+ buf = (void *)trans->rx_buf; -+ -+ len = trans->len; -+ -+ /* non-aligned and very short transfers are handled by MSPI */ -+ if (unlikely(!DWORD_ALIGNED(addr) || -+ !DWORD_ALIGNED(buf) || -+ len < sizeof(u32) || -+ !priv->bspi_hw_raf)) { -+ spin_unlock_irqrestore(&priv->lock, flags); -+ return -1; -+ } -+ -+ /* Flush prefetch buffers only if upper address byte changed */ -+ if ((addr & 0xFF000000) != le32_to_cpu(priv->bspi_hw->flash_upper_addr_byte)) { -+ bcmspi_flush_prefetch_buffers(priv); -+ /* Update upper address byte */ -+ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); -+ } -+ -+ /* Switching to BSPI */ -+ bcmspi_enable_bspi(priv); -+ -+ DBG("%s: dst %p src %p len %x addr BSPI %06x\n", -+ __func__, buf, addr, len, addr); -+ -+ /* initialize software parameters */ -+ priv->xfer_status = 0; -+ priv->cur_xfer = trans; -+ priv->cur_xfer_idx = 0; -+ priv->cur_msg = msg; -+ priv->actual_length = idx + 4 + trans->len; -+ } -+ -+ if (bcmspi_is_4_byte_mode(priv) && ACROSS_16MB(addr, len)) { -+ -+ /* Size for the first session */ -+ u32 bytes = 0x1000000 - (addr & 0x00FFFFFF); -+ -+ /* Address and size for remaining sessions */ -+ priv->raf_next_addr = addr + bytes; -+ priv->raf_next_len = len - bytes; -+ -+ len = bytes; -+ -+ } else { -+ priv->raf_next_len = 0; -+ } -+ -+ /* Length for this session */ -+ priv->cur_xfer_len = len; -+ -+ /* setup hardware */ -+ /* address must be 4-byte aligned */ -+ priv->bspi_hw_raf->start_address = cpu_to_le32(addr & 0x00FFFFFF); -+ priv->bspi_hw_raf->num_words = cpu_to_le32((len + 3) >> 2); -+ priv->bspi_hw_raf->watermark = 0; -+ -+ DBG("READ: %08x %08x (%08x)\n", addr, ((len + 3) >> 2), len); -+ -+ bcmspi_clear_interrupt(priv, 0xffffffff); -+ bcmspi_enable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); -+ bcmspi_lr_start(priv); -+ -+ if (idx) { -+ spin_unlock_irqrestore(&priv->lock, flags); -+ } -+ -+ return 0; -+} -+ -+/* -+ * m25p80_read() calls wait_till_ready() before each read to check -+ * the flash status register for pending writes. -+ * -+ * This can be safely skipped if our last transaction was just an -+ * emulated BSPI read. -+ */ -+static int bcmspi_emulate_flash_rdsr(struct bcmspi_priv *priv, -+ struct spi_message *msg) -+{ -+ u8 *buf; -+ struct spi_transfer *trans; -+ -+ if (priv->bspi_enabled == 0) -+ return 1; -+ -+ trans = list_entry(msg->transfers.next->next, struct spi_transfer, -+ transfer_list); -+ -+ buf = (void *)trans->rx_buf; -+ *buf = 0x00; -+ -+ msg->actual_length = 2; -+ msg->status = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -+ spi_finalize_current_message(priv->master); -+#else -+ msg->complete(msg->context); -+#endif -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -+static int bcmspi_prepare_transfer(struct spi_master *master) -+{ -+ return 0; -+} -+ -+static int bcmspi_unprepare_transfer(struct spi_master *master) -+{ -+ return 0; -+} -+#endif -+ -+static int bcmspi_transfer_one(struct spi_master *master, struct spi_message *msg) -+{ -+ struct bcmspi_priv *priv = spi_master_get_devdata(master); -+ unsigned long flags; -+ -+ DBG("%s\n", __func__); -+ -+ if (is_bspi_chip_select(priv, msg->spi->chip_select)) { -+ struct spi_transfer *trans; -+ -+ trans = list_entry(msg->transfers.next, -+ struct spi_transfer, transfer_list); -+ if (trans && trans->len && trans->tx_buf) { -+ u8 command = ((u8 *)trans->tx_buf)[0]; -+ switch (command) { -+ case OPCODE_FAST_READ: -+ if (bcmspi_emulate_flash_read(priv, msg) == 0) -+ return 0; -+ break; -+ case OPCODE_RDSR: -+ if (bcmspi_emulate_flash_rdsr(priv, msg) == 0) -+ return 0; -+ break; -+ case OPCODE_EN4B: -+ DBG("ENABLE 4-BYTE MODE\n"); -+ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_4BYTES, -1); -+ break; -+ case OPCODE_EX4B: -+ DBG("DISABLE 4-BYTE MODE\n"); -+ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_3BYTES, -1); -+ break; -+ case OPCODE_BRWR: -+ { -+ u8 enable = ((u8 *)trans->tx_buf)[1]; -+ DBG("%s 4-BYTE MODE\n", enable ? "ENABLE" : "DISABLE"); -+ bcmspi_set_mode(priv, -1, -+ enable ? BSPI_ADDRLEN_4BYTES : -+ BSPI_ADDRLEN_3BYTES, -1); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ /* Mark prefetch buffers dirty (by using upper byte) if needed */ -+ switch(command) { -+ case OPCODE_RDID: -+ case OPCODE_WREN: -+ case OPCODE_WRDI: -+ case OPCODE_RCR: -+ case OPCODE_READ: -+ case OPCODE_RDSR: -+ case OPCODE_WRSR: -+ case OPCODE_RDFSR: -+ case OPCODE_FAST_READ: -+ case OPCODE_FAST_READ_4B: -+ case OPCODE_EN4B: -+ case OPCODE_EX4B: -+ case OPCODE_BRWR: -+ /* These are known opcodes that are not writing/erasing */ -+ break; -+ default: -+ /* Could be writing/erasing; mark buffers dirty */ -+ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(0xff000000); -+ break; -+ } -+ } -+ } -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ if (priv->state == STATE_SHUTDOWN) { -+ spin_unlock_irqrestore(&priv->lock, flags); -+ return -EIO; -+ } -+ -+ msg->actual_length = 0; -+ -+ list_add_tail(&msg->queue, &priv->msg_queue); -+ -+ if (priv->state == STATE_IDLE) { -+ BUG_ON(priv->pos.msg != NULL); -+ priv->pos.msg = msg; -+ priv->pos.trans = list_entry(msg->transfers.next, -+ struct spi_transfer, transfer_list); -+ priv->pos.byte = 0; -+ -+ write_to_hw(priv); -+ } -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) -+static int bcmspi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ return bcmspi_transfer_one(spi->master, msg); -+} -+#endif -+ -+static void bcmspi_cleanup(struct spi_device *spi) -+{ -+ struct bcmspi_parms *xp = spi_get_ctldata(spi); -+ -+ DBG("%s\n", __func__); -+ -+ kfree(xp); -+} -+ -+static irqreturn_t bcmspi_interrupt(int irq, void *dev_id) -+{ -+ struct bcmspi_priv *priv = dev_id; -+ -+ if (priv->bspi_enabled && priv->cur_xfer) { -+ int done = 0; -+ u32 status = bcmspi_read_interrupt(priv); -+ u32 *buf = (u32 *)priv->cur_xfer->rx_buf; -+ if (status & BSPI_LR_INTERRUPTS_DATA) { -+ while (!bcmspi_lr_is_fifo_empty(priv)) { -+ u32 data = bcmspi_lr_read_fifo(priv); -+ if (likely(priv->cur_xfer_len >= 4)) { -+ buf[priv->cur_xfer_idx++] = data; -+ priv->cur_xfer_len -= 4; -+ } else { -+ /* -+ * Read out remaining bytes, make sure -+ * we do not cross the buffer boundary -+ */ -+ u8 *cbuf = -+ (u8 *)&buf[priv->cur_xfer_idx]; -+ data = cpu_to_le32(data); -+ while (priv->cur_xfer_len) { -+ *cbuf++ = (u8)data; -+ data >>= 8; -+ priv->cur_xfer_len--; -+ } -+ } -+ } -+ } -+ if (status & BSPI_LR_INTERRUPTS_ERROR) { -+ dev_err(&priv->pdev->dev, "ERROR %02x\n", status); -+ priv->xfer_status = -EIO; -+ } else if ((status & QSPI_INTR_BSPI_LR_SESSION_DONE_MASK) && -+ priv->cur_xfer_len == 0) { -+ -+ if (priv->raf_next_len) { -+ -+ /* Continuation for reading across 16MB boundary */ -+ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); -+ bcmspi_emulate_flash_read(priv, NULL); -+ return IRQ_HANDLED; -+ -+ } else { -+ done = 1; -+ } -+ } -+ -+ if (done) { -+ priv->cur_xfer = NULL; -+ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); -+ -+ if (priv->xfer_status) { -+ bcmspi_lr_clear(priv); -+ } else { -+ if (priv->cur_msg) { -+ priv->cur_msg->actual_length = priv->actual_length; -+ priv->cur_msg->status = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -+ spi_finalize_current_message(priv->master); -+#else -+ priv->cur_msg->complete(priv->cur_msg->context); -+#endif -+ } -+ } -+ priv->cur_msg = NULL; -+ } -+ bcmspi_clear_interrupt(priv, status); -+ return IRQ_HANDLED; -+ } -+ -+ if (priv->mspi_hw->mspi_status & cpu_to_le32(1)) { -+ /* clear interrupt */ -+ priv->mspi_hw->mspi_status &= cpu_to_le32(~1); -+ bcmspi_clear_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); -+ -+ tasklet_schedule(&priv->tasklet); -+ return IRQ_HANDLED; -+ } else -+ return IRQ_NONE; -+} -+ -+static void bcmspi_complete(void *arg) -+{ -+ complete(arg); -+} -+ -+static void bcmspi_tasklet(unsigned long param) -+{ -+ struct bcmspi_priv *priv = (void *)param; -+ struct list_head completed; -+ struct spi_message *msg; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD(&completed); -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ if (priv->next_udelay) { -+ udelay(priv->next_udelay); -+ priv->next_udelay = 0; -+ } -+ -+ msg = priv->pos.msg; -+ -+ read_from_hw(priv, &completed); -+ if (priv->cs_change) { -+ udelay(10); -+ priv->cs_change = 0; -+ } -+ -+ write_to_hw(priv); -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ while (!list_empty(&completed)) { -+ msg = list_first_entry(&completed, struct spi_message, queue); -+ list_del(&msg->queue); -+ msg->status = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -+ if (msg->complete == bcmspi_complete) -+ msg->complete(msg->context); -+ else -+ spi_finalize_current_message(priv->master); -+#else -+ if (msg->complete) -+ msg->complete(msg->context); -+#endif -+ -+ } -+} -+ -+static struct spi_master *default_master; -+ -+static int bcmspi_simple_transaction(struct bcmspi_parms *xp, -+ const void *tx_buf, int tx_len, void *rx_buf, int rx_len) -+{ -+ DECLARE_COMPLETION_ONSTACK(fini); -+ struct spi_message m; -+ struct spi_transfer t_tx, t_rx; -+ struct spi_device spi; -+ int ret; -+ -+ memset(&spi, 0, sizeof(spi)); -+ spi.max_speed_hz = xp->speed_hz; -+ spi.chip_select = xp->chip_select; -+ spi.mode = xp->mode; -+ spi.bits_per_word = xp->bits_per_word; -+ spi.master = default_master; -+ -+ spi_message_init(&m); -+ m.complete = bcmspi_complete; -+ m.context = &fini; -+ m.spi = &spi; -+ -+ memset(&t_tx, 0, sizeof(t_tx)); -+ memset(&t_rx, 0, sizeof(t_rx)); -+ t_tx.tx_buf = tx_buf; -+ t_tx.len = tx_len; -+ t_rx.rx_buf = rx_buf; -+ t_rx.len = rx_len; -+ -+ if (tx_len) -+ spi_message_add_tail(&t_tx, &m); -+ if (rx_len) -+ spi_message_add_tail(&t_rx, &m); -+ -+ ret = bcmspi_transfer_one(default_master, &m); -+ if (!ret) -+ wait_for_completion(&fini); -+ return ret; -+} -+ -+static void bcmspi_hw_init(struct bcmspi_priv *priv) -+{ -+ const struct bcmspi_parms bcmspi_default_parms_cs0 = { -+ .speed_hz = DEFAULT_SPEED_HZ, -+ .chip_select = 0, -+ .mode = SPI_MODE_3, -+ .bits_per_word = 8, -+ }; -+ -+ priv->mspi_hw->spcr1_lsb = 0; -+ priv->mspi_hw->spcr1_msb = 0; -+ priv->mspi_hw->newqp = 0; -+ priv->mspi_hw->endqp = 0; -+ priv->mspi_hw->spcr2 = cpu_to_le32(0x20); /* spifie */ -+ -+ bcmspi_hw_set_parms(priv, &bcmspi_default_parms_cs0); -+ -+ priv->bspi_enabled = 1; -+ bcmspi_disable_bspi(priv); -+} -+ -+static void bcmspi_hw_uninit(struct bcmspi_priv *priv) -+{ -+ priv->mspi_hw->spcr2 = 0x0; /* disable irq and enable bits */ -+ bcmspi_enable_bspi(priv); -+} -+ -+static int bcmbspi_flash_type(struct bcmspi_priv *priv) -+{ -+ char tx_buf[4]; -+ unsigned char jedec_id[5] = {0}; -+ int bspi_flash; -+ -+ /* Read ID */ -+ tx_buf[0] = OPCODE_RDID; -+ bcmspi_simple_transaction(&priv->last_parms, tx_buf, 1, &jedec_id, 5); -+ -+ switch (jedec_id[0]) { -+ case 0x01: /* Spansion */ -+ case 0xef: -+ bspi_flash = BSPI_FLASH_TYPE_SPANSION; -+ break; -+ case 0xc2: /* Macronix */ -+ bspi_flash = BSPI_FLASH_TYPE_MACRONIX; -+ break; -+ case 0xbf: /* SST */ -+ bspi_flash = BSPI_FLASH_TYPE_SST; -+ break; -+ case 0x89: /* Numonyx */ -+ bspi_flash = BSPI_FLASH_TYPE_NUMONYX; -+ break; -+ default: -+ bspi_flash = BSPI_FLASH_TYPE_UNKNOWN; -+ break; -+ } -+ return bspi_flash; -+} -+ -+static int bcmspi_set_quad_mode(struct bcmspi_priv *priv, int _enable) -+{ -+ char tx_buf[4]; -+ unsigned char cfg_reg, sts_reg; -+ -+ switch (bcmbspi_flash_type(priv)) { -+ case BSPI_FLASH_TYPE_SPANSION: -+ /* RCR */ -+ tx_buf[0] = OPCODE_RCR; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, &cfg_reg, 1); -+ if (_enable) -+ cfg_reg |= 0x2; -+ else -+ cfg_reg &= ~0x2; -+ /* WREN */ -+ tx_buf[0] = OPCODE_WREN; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, NULL, 0); -+ /* WRR */ -+ tx_buf[0] = OPCODE_WRR; -+ tx_buf[1] = 0; /* status register */ -+ tx_buf[2] = cfg_reg; /* configuration register */ -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 3, NULL, 0); -+ /* wait till ready */ -+ do { -+ tx_buf[0] = OPCODE_RDSR; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, &sts_reg, 1); -+ udelay(1); -+ } while (sts_reg & 1); -+ break; -+ case BSPI_FLASH_TYPE_MACRONIX: -+ /* RDSR */ -+ tx_buf[0] = OPCODE_RDSR; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, &cfg_reg, 1); -+ if (_enable) -+ cfg_reg |= 0x40; -+ else -+ cfg_reg &= ~0x40; -+ /* WREN */ -+ tx_buf[0] = OPCODE_WREN; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, NULL, 0); -+ /* WRSR */ -+ tx_buf[0] = OPCODE_WRSR; -+ tx_buf[1] = cfg_reg; /* status register */ -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 2, NULL, 0); -+ /* wait till ready */ -+ do { -+ tx_buf[0] = OPCODE_RDSR; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, &sts_reg, 1); -+ udelay(1); -+ } while (sts_reg & 1); -+ /* RDSR */ -+ tx_buf[0] = OPCODE_RDSR; -+ bcmspi_simple_transaction(&priv->last_parms, -+ tx_buf, 1, &cfg_reg, 1); -+ break; -+ case BSPI_FLASH_TYPE_SST: -+ case BSPI_FLASH_TYPE_NUMONYX: -+ /* TODO - send Quad mode control command */ -+ break; -+ default: -+ return _enable ? -1 : 0; -+ } -+ -+ return 0; -+} -+ -+static int bcmspi_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct brcmspi_platform_data *pdata; -+ struct bcmspi_priv *priv; -+ struct spi_master *master; -+ struct resource *res; -+ struct clk *clk; -+ int ret; -+ u32 irq; -+#ifdef CONFIG_OF -+ struct device_node *dn = pdev->dev.of_node; -+ u32 qspi_bus_id; -+ u32 qspi_cs; -+ int i, irqs_total; -+#endif -+ -+ DBG("bcmspi_probe\n"); -+ -+ pdata = (struct brcmspi_platform_data *)pdev->dev.platform_data; -+ -+ master = spi_alloc_master(dev, sizeof(struct bcmspi_priv)); -+ if (!master) { -+ dev_err(&pdev->dev, "error allocating spi_master\n"); -+ return -ENOMEM; -+ } -+ -+ priv = spi_master_get_devdata(master); -+ -+ priv->pdev = pdev; -+ priv->state = STATE_IDLE; -+ priv->pos.msg = NULL; -+ priv->pos.mspi_16bit = 0; -+ priv->master = master; -+ priv->raf_next_len = 0; -+ -+#ifndef CONFIG_OF -+ master->bus_num = pdev->id; -+#else -+ if (of_property_read_u32(dn, "#bus-id", &qspi_bus_id)) { -+ dev_warn(&pdev->dev, -+ "missing #bus-id property (default to 1)\n"); -+ qspi_bus_id = 1; -+ } -+ master->bus_num = qspi_bus_id; -+ pdev->id = qspi_bus_id; -+#endif -+ master->num_chipselect = 1; -+ master->mode_bits = SPI_MODE_3; -+ -+ master->setup = bcmspi_setup; -+ master->cleanup = bcmspi_cleanup; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -+ master->prepare_transfer_hardware = bcmspi_prepare_transfer; -+ master->unprepare_transfer_hardware = bcmspi_unprepare_transfer; -+ master->transfer_one_message = bcmspi_transfer_one; -+ master->transfer = NULL; -+#else -+ master->transfer = bcmspi_transfer; -+#endif -+/* needed for supporting child SPI devices*/ -+#ifdef CONFIG_OF -+ master->dev.of_node = pdev->dev.of_node; -+#endif -+ -+ priv->mspi_hw = NULL; -+ priv->bspi_hw = NULL; -+ priv->bspi_hw_raf = NULL; -+ priv->qspi_intr = NULL; -+ priv->idm_qspi = NULL; -+ priv->irq = -1; -+ -+ /* Get MSPI reference clock and max speed hz */ -+#ifndef CONFIG_OF -+ clk = clk_get_sys(MSPI_REFCLK_SOURCE_DEVID, MSPI_REFCLK_SOURCE); -+#else -+ clk = of_clk_get (dn, 0); -+#endif /* CONFIG_OF */ -+ if (!clk) { -+ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", -+ MSPI_REFCLK_SOURCE); -+ ret = -EIO; -+ goto err2; -+ } -+ priv->mspi_refclk = (unsigned int)clk_get_rate(clk) * 2; -+ priv->max_speed_hz = priv->mspi_refclk / (2 * SPBR_MIN); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "can't get resource 0\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ /* MSPI register range */ -+ priv->mspi_hw = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->mspi_hw) { -+ dev_err(&pdev->dev, "can't ioremap\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ DBG("priv->mspi_hw=%p\n", priv->mspi_hw); -+ -+ /* BSPI register range */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (res) { -+ priv->bspi_hw = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->bspi_hw) { -+ dev_err(&pdev->dev, "can't ioremap BSPI range\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ } else -+ priv->bspi_hw = NULL; -+ DBG("priv->bspi_hw=%p\n", priv->bspi_hw); -+ -+ /* BSPI_RAF register range */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -+ if (res) { -+ priv->bspi_hw_raf = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->bspi_hw_raf) { -+ dev_err(&pdev->dev, "can't ioremap BSPI_RAF range\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ } else -+ priv->bspi_hw_raf = NULL; -+ DBG("priv->bspi_hw_raf=%p\n", priv->bspi_hw_raf); -+ -+ /* QSPI interrupt register range */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3); -+ if (res) { -+ priv->qspi_intr = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->qspi_intr) { -+ dev_err(&pdev->dev, "can't ioremap QSPI interrupt range\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ } else { -+ dev_err(&pdev->dev, "can't get resource 3\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ DBG("priv->qspi_intr=%p\n", priv->qspi_intr); -+ -+ /* IDM QSPI io ctrl register range */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 4); -+ if (res) { -+ priv->idm_qspi = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->idm_qspi) { -+ dev_err(&pdev->dev, "can't ioremap IDM QSPI range\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ } else { -+ dev_err(&pdev->dev, "can't get resource 4\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ DBG("priv->idm_qspi=%p\n", priv->idm_qspi); -+ -+ /* CRU control register */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 5); -+ if (res) { -+ priv->cru_hw = (volatile void *)ioremap(res->start, -+ res->end - res->start); -+ if (!priv->cru_hw) { -+ dev_err(&pdev->dev, "can't ioremap CRU range\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ } else { -+ dev_err(&pdev->dev, "can't get resource 4\n"); -+ ret = -EIO; -+ goto err2; -+ } -+ DBG("priv->cru_hw=%p\n", priv->cru_hw); -+ -+ /* IRQ */ -+#ifndef CONFIG_OF -+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no IRQ defined\n"); -+ ret = -ENODEV; -+ goto err2; -+ } -+#else -+ irqs_total = of_irq_count(dn); -+#endif /*CONFIG_OF*/ -+ -+ /* Basic initialization (before enabling interrupts) */ -+ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); -+ bcmspi_disable_interrupt(priv, 0xffffffff); -+ bcmspi_clear_interrupt(priv, 0xffffffff); -+ bcmspi_enable_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); -+ -+ /* Request all IRQs */ -+#ifndef CONFIG_OF -+ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { -+#else -+ for (i=0; idev, "unable to allocate IRQ\n"); -+ goto err1; -+ } -+ } -+ -+ bcmspi_hw_init(priv); -+ priv->curr_cs = -1; -+ -+#ifdef CONFIG_OF -+ if (of_property_read_u32(dn, "#chip-select", &qspi_cs)) { -+ dev_warn(&pdev->dev, -+ "missing #chip-selects property (default to 0)\n"); -+ qspi_cs = 0; -+ } -+ priv->bspi_chip_select = (1 << qspi_cs); -+ if (pdata == 0) { -+ struct brcmspi_platform_data platformdata; -+ memset(&platformdata, 0, sizeof(platformdata)); -+ platformdata.flash_cs = qspi_cs; -+ platform_device_add_data(pdev, &platformdata, sizeof(platformdata)); -+ pdata = (struct brcmspi_platform_data *)pdev->dev.platform_data; -+ } -+#else -+ priv->bspi_chip_select = (priv->bspi_hw && pdata) ? (1 << pdata->flash_cs) : 0; -+#endif /* CONFIG_OF */ -+ -+ INIT_LIST_HEAD(&priv->msg_queue); -+ spin_lock_init(&priv->lock); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ tasklet_init(&priv->tasklet, bcmspi_tasklet, (unsigned long)priv); -+ -+ if (!default_master) -+ default_master = master; -+ -+ -+ if (priv->bspi_chip_select) { -+ int bspi_width = BSPI_WIDTH_1BIT; -+ -+ /* Module parameter validation */ -+ if (io_mode != 0) { -+ if (read_opcode < 0 || read_opcode > 255) { -+ dev_err(&pdev->dev, "invalid read_opcode\n"); -+ io_mode = 0; -+ } else if (dummy_cycles < 0 || dummy_cycles > 255) { -+ dev_err(&pdev->dev, "invalid dummy_cycles\n"); -+ io_mode = 0; -+ } -+ } -+ if (io_mode == 2) { -+ bspi_width = BSPI_WIDTH_4BIT; -+ } else if (io_mode == 1) { -+ bspi_width = BSPI_WIDTH_2BIT; -+ } else if (io_mode != 0) { -+ dev_err(&pdev->dev, "invalid io_mode (0/1/2)\n"); -+ } -+ -+ if (io_mode == 2) -+ bcmspi_set_quad_mode(priv, 1); -+ -+ bcmspi_set_mode(priv, bspi_width, BSPI_ADDRLEN_3BYTES, bspi_hp); -+ } -+ -+ ret = spi_register_master(master); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "can't register master\n"); -+ goto err0; -+ } -+ -+ return 0; -+ -+err0: -+ bcmspi_hw_uninit(priv); -+err1: -+#ifdef CONFIG_OF -+ while ( i-- ) { -+ irq = irq_of_parse_and_map(dn, i-1); -+ free_irq(irq, priv); -+ } -+#endif -+err2: -+ if (priv->idm_qspi) { -+ iounmap(priv->idm_qspi); -+ } -+ if (priv->qspi_intr) { -+ iounmap(priv->qspi_intr); -+ } -+ if (priv->bspi_hw_raf) { -+ iounmap(priv->bspi_hw_raf); -+ } -+ if (priv->bspi_hw) { -+ iounmap(priv->bspi_hw); -+ } -+ if (priv->mspi_hw) { -+ iounmap(priv->mspi_hw); -+ } -+ spi_master_put(master); -+ return ret; -+} -+ -+static int bcmspi_remove(struct platform_device *pdev) -+{ -+ struct bcmspi_priv *priv = platform_get_drvdata(pdev); -+ unsigned long flags; -+ u32 irq; -+#ifdef CONFIG_OF -+ struct device_node *dn = pdev->dev.of_node; -+ u32 irq_start=0, irq_end=0; -+#else -+ struct resource *res; -+#endif /* CONFIG_OF */ -+ -+ /* acquire lock when the MSPI is idle */ -+ while (1) { -+ spin_lock_irqsave(&priv->lock, flags); -+ if (priv->state == STATE_IDLE) -+ break; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ udelay(100); -+ } -+ priv->state = STATE_SHUTDOWN; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ tasklet_kill(&priv->tasklet); -+ platform_set_drvdata(pdev, NULL); -+ bcmspi_hw_uninit(priv); -+ if (priv->bspi_hw_raf) -+ iounmap(priv->bspi_hw_raf); -+ if (priv->bspi_hw) -+ iounmap((volatile void __iomem *)priv->bspi_hw); -+#ifdef CONFIG_OF -+ irq_start = irq_of_parse_and_map(dn, 0); -+ irq_end = irq_of_parse_and_map(dn, 1); -+ if (irq_start && irq_end) { -+ for(irq=irq_start; irq<=irq_end; irq++) -+ free_irq(irq, priv); -+ } -+#else -+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -+ if (res) { -+ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { -+ free_irq(irq, priv); -+ } -+ } -+#endif -+ -+ iounmap((volatile void __iomem *)priv->mspi_hw); -+ spi_unregister_master(priv->master); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int bcmspi_suspend(struct device *dev) -+{ -+ struct bcmspi_priv *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ if (priv == NULL || priv->master == NULL) { -+ return -EINVAL; -+ } -+ -+ /* Do nothing if it's not yet initialized */ -+ if (!priv->bspi_hw) -+ return 0; -+ -+ /* Flush transactions and stop the queue */ -+ ret = spi_master_suspend(priv->master); -+ if (ret) { -+ dev_warn(dev, "cannot suspend master\n"); -+ return ret; -+ } -+ -+ /* Disable flex mode */ -+ priv->bspi_hw->flex_mode_enable = 0; -+ -+ /* Clear upper byte */ -+ priv->bspi_hw->flash_upper_addr_byte = 0; -+ -+ /* Ensure BSPI read is clean */ -+ bcmspi_flush_prefetch_buffers(priv); -+ -+ /* Switch to BSPI for waking up from boot code */ -+ if (!priv->bspi_enabled) -+ priv->bspi_hw->mast_n_boot_ctrl = 0; -+ -+ return 0; -+}; -+ -+static int bcmspi_resume(struct device *dev) -+{ -+ struct bcmspi_priv *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ if (priv == NULL || priv->master == NULL) -+ return -EINVAL; -+ -+ /* Do nothing if it's not yet initialized */ -+ if (!priv->bspi_hw) -+ return 0; -+ -+ /* Restore MSPI/BSPI mode */ -+ priv->bspi_enabled = !priv->bspi_enabled; -+ if (priv->bspi_enabled) -+ bcmspi_disable_bspi(priv); -+ else -+ bcmspi_enable_bspi(priv); -+ -+ /* Restore controller configuration */ -+ bcmspi_hw_set_parms(priv, &priv->last_parms); -+ -+ /* Restore flex mode configuration */ -+ bcmspi_set_mode(priv, -+ priv->flex_mode.width, priv->flex_mode.addrlen, priv->flex_mode.hp); -+ -+ -+ /* Restore interrupts */ -+ bcmspi_disable_interrupt(priv, 0xffffffff); -+ bcmspi_clear_interrupt(priv, 0xffffffff); -+ bcmspi_enable_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); -+ -+ /* Ensure BSPI read is clean */ -+ bcmspi_flush_prefetch_buffers(priv); -+ -+ /* Start the queue running */ -+ ret = spi_master_resume(priv->master); -+ if (ret) -+ dev_err(dev, "problem starting queue (%d)\n", ret); -+ -+ return ret; -+} -+ -+static const struct dev_pm_ops bcmspi_pm_ops = { -+ .suspend = bcmspi_suspend, -+ .resume = bcmspi_resume, -+}; -+#endif /* CONFIG_PM */ -+ -+ -+#ifdef CONFIG_OF -+static const struct of_device_id qspi_iproc_dt_ids[] = { -+ {.compatible = "brcm,iproc-qspi"}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, qspi_iproc_dt_ids); -+ -+ -+static struct platform_driver qspi_iproc_driver = { -+ .driver = { -+ .name = "iproc-qspi", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(qspi_iproc_dt_ids), -+#ifdef CONFIG_PM -+ .pm = &bcmspi_pm_ops, -+#endif -+ }, -+ .probe = bcmspi_probe, -+ .remove = bcmspi_remove, -+}; -+ -+module_platform_driver(qspi_iproc_driver); -+ -+#else /*CONFIG_OF*/ -+ -+static struct platform_driver driver = { -+ .driver = { -+ .name = "qspi_iproc", -+ .bus = &platform_bus_type, -+ .owner = THIS_MODULE, -+#ifdef CONFIG_PM -+ .pm = &bcmspi_pm_ops, -+#endif -+ }, -+ .probe = bcmspi_probe, -+ .remove = __devexit_p(bcmspi_remove), -+}; -+ -+static int __init bcmspi_spi_init(void) -+{ -+ platform_driver_register(&driver); -+ return 0; -+} -+ -+static void __exit bcmspi_spi_exit(void) -+{ -+ platform_driver_unregister(&driver); -+} -+ -+module_init(bcmspi_spi_init); -+module_exit(bcmspi_spi_exit); -+#endif /*CONFIG_OF*/ -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("iProc QSPI driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c ---- a/drivers/usb/gadget/legacy/serial.c 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/gadget/legacy/serial.c 2017-11-09 17:54:01.552429000 +0800 -@@ -250,7 +250,7 @@ static int __init init(void) - */ - if (use_acm) { - serial_config_driver.label = "CDC ACM config"; -- serial_config_driver.bConfigurationValue = 2; -+ serial_config_driver.bConfigurationValue = 1; - device_desc.bDeviceClass = USB_CLASS_COMM; - device_desc.idProduct = - cpu_to_le16(GS_CDC_PRODUCT_ID); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig ---- a/drivers/usb/gadget/udc/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/gadget/udc/Kconfig 2017-11-09 17:54:01.588427000 +0800 -@@ -373,6 +373,17 @@ config USB_GADGET_XILINX - dynamically linked module called "udc-xilinx" and force all - gadget drivers to also be dynamically linked. - -+config USB_XGS_IPROC_UDC -+ tristate "Broadcom XGS IPROC USB Device driver" -+ depends on ARCH_XGS_IPROC && USB_GADGET -+ default n -+ help -+ USB peripheral controller driver for Broadcom XGS IPROC USB 2 device. -+ -+ Say "y" to link the driver statically, or "m" to build a dynamically -+ linked module called "xgs_iproc_udc" and force all gadget drivers to -+ also be dynamically linked. -+ - # - # LAST -- dummy/emulated controller - # -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile ---- a/drivers/usb/gadget/udc/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/gadget/udc/Makefile 2017-11-09 17:54:01.589418000 +0800 -@@ -30,4 +30,5 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210 - obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o - obj-$(CONFIG_USB_GR_UDC) += gr_udc.o - obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o -+obj-$(CONFIG_USB_XGS_IPROC_UDC) += xgs_iproc_udc.o - obj-$(CONFIG_USB_BDC_UDC) += bdc/ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_iproc_udc.c b/drivers/usb/gadget/udc/xgs_iproc_udc.c ---- a/drivers/usb/gadget/udc/xgs_iproc_udc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/usb/gadget/udc/xgs_iproc_udc.c 2017-11-09 17:54:01.736429000 +0800 -@@ -0,0 +1,2114 @@ -+/***************************************************************************** -+* Copyright 2006 - 2010 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+/****************************************************************************/ -+/** -+* @file bcm_dwc_udc.c -+* -+* @brief Broadcom Linux driver for DWC USB 2.0 Device Controller (UDC) -+* -+* This driver implements the Linux Gadget driver API as defined in usb_gadget.h -+* -+* @note -+* -+* This driver was written with the intent of being able to support any -+* variations on how this block is integrated into different Broadcom chips. -+* -+* There is a requirement on how the DWC UDC is configured. In particular, this -+* driver requires that the following options be defined and enabled in the -+* UDC core. -+* -+* UDC20AHB_CNAK_CLR_ENH_CC -+* UDC20AHB_STALL_SET_ENH_CC -+* UDC20AHB_SNAK_ENH_CC -+* -+* Some other UDC attributes can be supported by setting compile time options -+* or with some minor modifications to the source code. Ideally these would -+* be run-time info that is provided by the device instance to the driver. -+* These attributes include the following. -+* -+* IPROC_UDC_EP_CNT -+* IPROC_UDC_EP_MAX_PKG_SIZE -+* Type of each endpoint: Control, IN, OUT, or Bidirectional -+*/ -+/****************************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xgs_iproc_udc.h" -+ -+#define XGS_IPROC_UDC_NAME "iproc-udc" -+/* Would be nice if DMA_ADDR_INVALID or similar was defined in dma-mapping.h */ -+#define DMA_ADDR_INVALID (~(dma_addr_t)0) -+/* -+ * FRAME_NUM_INVALID is used for ISOC IN transfers for frame alignment. -+ * The device specifies the interval at which it wants to do transfers, -+ * but the host initiates all transfers. If the interval is some multiple -+ * number of frames, the device has no idea which frame in an interval -+ * window the host is going to start transfers. This could even be at a -+ * point many frames beyond the current window, as the starting point -+ * can be very application dependant and subject to an indeterminate -+ * amount of latency. -+ */ -+#define FRAME_NUM_INVALID (~(uint)0) -+/* Would be nice if ENOERROR or similar was defined in errno.h */ -+#define ENOERROR 0 -+ -+/* ---- Private Function Prototypes -------------------------------------- */ -+#ifdef IPROC_UDC_DEBUG -+static void iproc_dbg_dma_dump(struct iproc_udc *udc); -+static void iproc_dbg_dma_dump_desc(char *label, struct iproc_udc_dma_desc *virt, struct iproc_udc_dma_desc *phys); -+static void iproc_dbg_dma_dump_ep(struct iproc_ep *ep); -+#endif /* IPROC_UDC_DEBUG */ -+ -+static void iproc_ep_setup_init(struct iproc_ep *ep, int status); -+static void iproc_ep_setup_process(struct iproc_ep *ep, struct usb_ctrlrequest *setup); -+ -+static void iproc_dma_ep_init(struct iproc_ep *ep); -+static void iproc_dma_data_init(struct iproc_ep *ep); -+static void iproc_dma_data_finish(struct iproc_ep *ep); -+static void iproc_dma_data_add_ready(struct iproc_ep *ep); -+static void iproc_dma_data_rm_done(struct iproc_ep *ep); -+ -+static int iproc_platform_dma_alloc(struct platform_device *platformDevP, struct iproc_udc *udc); -+static void iproc_platform_dma_free(struct platform_device *platformDevP, struct iproc_udc *udc); -+ -+static void iproc_udc_req_queue_flush(struct iproc_ep *ep, int status); -+static void iproc_udc_req_xfer_error(struct iproc_ep *ep, int status); -+static void iproc_udc_req_xfer_done(struct iproc_ep *ep, struct iproc_ep_req *req, int status); -+static void iproc_udc_req_xfer_process(struct iproc_ep *ep); -+static void iproc_udc_req_xfer_add(struct iproc_ep *ep, struct iproc_ep_req *req); -+ -+static void iproc_udc_ops_finish(struct iproc_udc *udc); -+static void iproc_udc_ops_init(struct iproc_udc *udc); -+static void iproc_udc_ops_stop(struct iproc_udc *udc); -+static void iproc_udc_ops_start(struct iproc_udc *udc); -+static void iproc_udc_ops_disconnect(struct iproc_udc *udc); -+static void iproc_udc_ops_shutdown(struct iproc_udc *udc); -+ -+static int xgs_iproc_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc); -+static int xgs_iproc_ep_disable(struct usb_ep *ep); -+static struct usb_request *xgs_iproc_ep_alloc_request(struct usb_ep *ep, uint gfp_flags); -+static void xgs_iproc_ep_free_request(struct usb_ep *ep, struct usb_request *req); -+static int xgs_iproc_ep_queue(struct usb_ep *ep, struct usb_request *req, uint gfp_flags); -+static int xgs_iproc_ep_dequeue(struct usb_ep *ep, struct usb_request *req); -+static int xgs_iproc_ep_set_halt(struct usb_ep *ep, int value); -+static int xgs_iproc_ep_fifo_status(struct usb_ep *ep); -+static void xgs_iproc_ep_fifo_flush(struct usb_ep *ep); -+ -+static int xgs_iproc_udc_start(struct usb_gadget *, struct usb_gadget_driver *); -+static int xgs_iproc_udc_stop(struct usb_gadget *); -+ -+static int xgs_iproc_udc_probe(struct platform_device *pdev); -+static int xgs_iproc_udc_remove(struct platform_device *pdev); -+ -+static void xgs_iproc_udc_proc_create(void); -+static void xgs_iproc_udc_proc_remove(void); -+ -+/* ---- Private Variables ------------------------------------------------ */ -+static const struct { -+ const char *name; -+ const int type; -+ const int msize; -+ const struct usb_ep_caps caps; -+} xgs_iproc_ep_info[] = { -+#define EP_INFO(_name, _type, _size, _caps) \ -+ { \ -+ .name = _name, \ -+ .type = _type, \ -+ .msize = _size, \ -+ .caps = _caps, \ -+ } -+ -+ EP_INFO("ep0", USB_ENDPOINT_XFER_CONTROL, IPROC_UDC_CTRL_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), -+ EP_INFO("ep1in", USB_ENDPOINT_XFER_ISOC, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), -+ EP_INFO("ep2out", USB_ENDPOINT_XFER_ISOC, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), -+ EP_INFO("ep3in", USB_ENDPOINT_XFER_BULK, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), -+ EP_INFO("ep4out", USB_ENDPOINT_XFER_BULK, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), -+ EP_INFO("ep5in", USB_ENDPOINT_XFER_INT, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), -+ EP_INFO("ep6out", USB_ENDPOINT_XFER_INT, IPROC_UDC_EP_MAX_PKG_SIZE, -+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)), -+#undef EP_INFO -+}; -+ -+static struct usb_gadget_ops xgs_iproc_udc_ops = { -+ .udc_start = xgs_iproc_udc_start, -+ .udc_stop = xgs_iproc_udc_stop, -+}; -+ -+static struct usb_ep_ops xgs_iproc_udc_ep_ops = { -+ .enable = xgs_iproc_ep_enable, -+ .disable = xgs_iproc_ep_disable, -+ .alloc_request = xgs_iproc_ep_alloc_request, -+ .free_request = xgs_iproc_ep_free_request, -+ .queue = xgs_iproc_ep_queue, -+ .dequeue = xgs_iproc_ep_dequeue, -+ .set_halt = xgs_iproc_ep_set_halt, -+ .fifo_status = xgs_iproc_ep_fifo_status, -+ .fifo_flush = xgs_iproc_ep_fifo_flush, -+}; -+ -+/*********************************************************************** -+ * Convenience functions -+ ***********************************************************************/ -+static inline struct iproc_udc *gadget_to_udc(struct usb_gadget *g) -+{ -+ return container_of(g, struct iproc_udc, gadget); -+} -+ -+static inline struct iproc_ep *our_ep(struct usb_ep *ep) -+{ -+ return container_of(ep, struct iproc_ep, usb_ep); -+} -+ -+static inline struct iproc_ep_req *our_req(struct usb_request *req) -+{ -+ return container_of(req, struct iproc_ep_req, usb_req); -+} -+ -+/**************************************************************************** -+ * DMA descriptor chain routines. -+ * -+ * dma_desc_chain_reset - Initialize chain in preparation for transfer -+ * dma_desc_chain_full - Indicates if no descriptors in chain for available for use. -+ * dma_desc_chain_alloc - Get next free descriptor for use. Have to check if chain not full first. -+ * dma_desc_chain_empty - Indicates if no descriptors in the chain are being used. -+ * dma_desc_chain_head - Pointer to 1st entry in chain. Have to check if chain not empty first. -+ * dma_desc_chain_free - Frees up 1st entry for use. Only do this if DMA for this descriptor has completed. -+ * -+ ***************************************************************************/ -+static inline struct iproc_udc_dma_desc *dma_desc_chain_alloc(struct iproc_ep *ep) -+{ -+ uint idx; -+ -+ idx = ep->dma.add_idx++; -+ -+ return &ep->dma.vir_addr->desc[IPROC_EP_DMA_DESC_IDX(idx)]; -+} -+ -+static inline int dma_desc_chain_empty(struct iproc_ep *ep) -+{ -+ return ep->dma.add_idx == ep->dma.rm_idx; -+} -+ -+static inline void dma_desc_chain_free(struct iproc_ep *ep) -+{ -+ ep->dma.rm_idx++; -+} -+ -+static inline int dma_desc_chain_full(struct iproc_ep *ep) -+{ -+ return (!dma_desc_chain_empty(ep) && (IPROC_EP_DMA_DESC_IDX(ep->dma.add_idx) == IPROC_EP_DMA_DESC_IDX(ep->dma.rm_idx))); -+} -+ -+static inline struct iproc_udc_dma_desc *dma_desc_chain_head(struct iproc_ep *ep) -+{ -+ return (&ep->dma.vir_addr->desc[IPROC_EP_DMA_DESC_IDX(ep->dma.rm_idx)]); -+} -+ -+static inline void dma_desc_chain_reset(struct iproc_ep *ep) -+{ -+ ep->dma.add_idx = 0; -+ ep->dma.rm_idx = 0; -+} -+ -+ -+/**************************************************************************** -+ * APIs used by a Gadget driver to attach / detach from the UDC driver. -+ ***************************************************************************/ -+static int xgs_iproc_udc_start(struct usb_gadget *gadget, -+ struct usb_gadget_driver *gadget_driver) -+{ -+ struct iproc_udc *udc = gadget_to_udc(gadget); -+ ulong flags; -+ -+ if (!udc) { -+ dev_err(udc->dev, "UDC driver not initialized\n"); -+ return -ENODEV; -+ } -+ -+ if (!gadget_driver || !gadget_driver->setup || -+ gadget_driver->max_speed < USB_SPEED_FULL) { -+ dev_err(udc->dev, "invalid gadget driver\n" ); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ if (udc->gadget_driver) { -+ spin_unlock_irqrestore(&udc->lock, flags); -+ dev_err(udc->dev, "UDC driver busy\n"); -+ return -EBUSY; -+ } -+ -+ /* Hook up the gadget driver to the UDC controller driver */ -+ gadget_driver->driver.bus = NULL; -+ udc->gadget_driver = gadget_driver; -+ udc->gadget.dev.driver = &gadget_driver->driver; -+ udc->pullup_on = 1; -+ -+ iproc_udc_ops_start(udc); -+ /* un-stop the control endpoint */ -+ udc->ep[0].stopped = 0; -+ iproc_usbd_bus_conn(udc->usbd_regs); -+ -+ iproc_usbd_setup_done(udc->usbd_regs); -+ iproc_usbd_dma_en(udc->usbd_regs); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ENOERROR; -+} -+ -+static int xgs_iproc_udc_stop(struct usb_gadget *gadget) -+{ -+ ulong flags; -+ struct iproc_udc *udc = gadget_to_udc(gadget); -+ -+ if (!udc) { -+ dev_err(udc->dev, "UDC driver not initialized\n"); -+ return -ENODEV; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ udc->ep[0].stopped = 1; -+ iproc_udc_ops_stop(udc); -+ udelay(20); -+ udc->pullup_on = 0; -+ iproc_usbd_bus_disconn(udc->usbd_regs); -+ iproc_udc_ops_shutdown(udc); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ENOERROR; -+} -+ -+/**************************************************************************** -+ * -+ * Platform device level alloc / free of memory used for DMA descriptors. -+ * A single block of memory static in size is used for DMA descriptors. -+ * Each endpoint has a small number of descriptors for its exclusive use. -+ * These are chained in a loop. See bcm_udc_dwc.h and iproc_dma_ep_init() for more -+ * details. -+ * -+ ***************************************************************************/ -+static int iproc_platform_dma_alloc(struct platform_device *platformDevP, struct iproc_udc *udc) -+{ -+ udc->dma.vir_addr = dma_alloc_coherent(&platformDevP->dev, sizeof(struct iproc_udc_dma), -+ (dma_addr_t *)&udc->dma.phy_addr, GFP_KERNEL); -+ -+ if (!udc->dma.vir_addr) { -+ dev_err(udc->dev, "dma_alloc_coherent() failed\n"); -+ return -ENOMEM; -+ } -+ -+ return ENOERROR; -+} -+ -+static void iproc_platform_dma_free(struct platform_device *platformDevP, struct iproc_udc *udc) -+{ -+ int idx; -+ -+ dma_free_coherent(&platformDevP->dev, sizeof(struct iproc_udc_dma), udc->dma.vir_addr, -+ (dma_addr_t)udc->dma.phy_addr); -+ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx ++) { -+ if (udc->ep[idx].dma.align_buff) { -+ dma_free_coherent(NULL, udc->ep[idx].dma.align_len, -+ udc->ep[idx].dma.align_buff, -+ udc->ep[idx].dma.align_addr); -+ udc->ep[idx].dma.align_buff = NULL; -+ } -+ } -+} -+ -+/**************************************************************************** -+ * Linux Gadget endpoint operations. See usb_ep_ops in usb_gadget.h. -+ ***************************************************************************/ -+static int xgs_iproc_ep_enable(struct usb_ep *usb_ep, const struct usb_endpoint_descriptor *desc) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ ulong flags; -+ uint xferType; -+ int ret = ENOERROR; -+ -+ if (!usb_ep || (ep->beq_addr != desc->bEndpointAddress)) { -+ dev_err(udc->dev, "invalid endpoint (%p)\n", usb_ep); -+ return -EINVAL; -+ } -+ -+ if (!desc || (desc->bDescriptorType != USB_DT_ENDPOINT)) { -+ dev_err(udc->dev, "ep%d: invalid descriptor=%p type=%d\n", ep->num, desc, desc ? desc->bDescriptorType : -1); -+ return -EINVAL; -+ } -+ -+ if (desc == ep->desc) { -+ dev_warn(udc->dev, "ep%d: already enabled with same descriptor\n", ep->num); -+ return -EEXIST; -+ } -+ -+ if (ep->desc) { -+ dev_warn(udc->dev, "ep%d: already enabled with another descriptor\n", ep->num); -+ return -EBUSY; -+ } -+ -+ if (!udc->gadget_driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) { -+ dev_warn(udc->dev, "%s: invalid device state\n", ep->usb_ep.name); -+ return -ESHUTDOWN; -+ } -+ -+ xferType = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -+ if ((ep->dir == USB_DIR_IN) && (xferType == USB_ENDPOINT_XFER_ISOC)) { -+ if ((desc->bInterval < 1) || (desc->bInterval > 16)) { -+ dev_err(udc->dev, "%s: invalid ISOC bInterval=%u\n", ep->usb_ep.name, desc->bInterval); -+ return -ERANGE; -+ } -+ -+ /* -+ * We don't know when the host will send the first ISO IN request, so we need to set up -+ * to capture that event so we can align subsequent transfers to that particular frame -+ * number. Also set the frame number increment. The endpoint descriptor specifies this -+ * as a power of 2 (2**(n-1)). Translate this into a specific number of frames. -+ */ -+ ep->dma.frame_num = FRAME_NUM_INVALID; -+ ep->dma.frame_incr = 1 << (desc->bInterval - 1); -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ ep->desc = desc; -+ ep->stopped = 0; -+ -+ /** @todo Rework the UdcEpCfg() so it includes iproc_usbd_ep_cfg_set() ... */ -+ iproc_usbd_ep_cfg_set(udc->usbd_regs, ep->num, iproc_usbd_cfg_num(udc->usbd_regs)); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ret; -+} -+ -+static int xgs_iproc_ep_disable(struct usb_ep *usb_ep) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ ulong flags; -+ int ret = ENOERROR; -+ -+ if (!usb_ep) { -+ dev_err(udc->dev, "invalid endpoint\n"); -+ return -EINVAL; -+ } -+ -+ if (!ep->desc) { -+ dev_warn(udc->dev, "%s: already disabled\n", ep->usb_ep.name); -+ return ENOERROR; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ iproc_udc_req_queue_flush(ep, -ESHUTDOWN); -+ iproc_usbd_ep_irq_dis(udc->usbd_regs, ep->num, ep->dir); -+ ep->desc = NULL; -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ret; -+} -+ -+struct usb_request * xgs_iproc_ep_alloc_request(struct usb_ep *usb_ep, uint gfp_flags) -+{ -+ struct iproc_ep_req *req; -+ -+ if (!usb_ep) { -+ return NULL; -+ } -+ -+ if ((req = kzalloc(sizeof(*req), gfp_flags)) != NULL) { -+ /* -+ * Set the usb_req.dma to DMA_ADDR_INVALID so it can be determined if the usb_req.buf needs -+ * to be mapped when the request is subsequently queued. -+ */ -+ INIT_LIST_HEAD(&req->list_node); -+ req->usb_req.dma = DMA_ADDR_INVALID; -+ -+ return &req->usb_req; -+ } -+ -+ return NULL; -+} -+ -+static void xgs_iproc_ep_free_request(struct usb_ep *usb_ep, struct usb_request *usb_req) -+{ -+ struct iproc_ep_req *req = our_req(usb_req); -+ -+ if (usb_req) { -+ kfree(req); -+ } -+} -+ -+static int xgs_iproc_ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, uint gfp_flags) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ struct iproc_ep_req *req = our_req(usb_req); -+ ulong flags; -+ int ret = ENOERROR; -+ -+ if (!usb_ep || !usb_req || !req->usb_req.complete || !req->usb_req.buf || !list_empty(&req->list_node)) { -+ dev_err(udc->dev, "invalid request\n"); -+ return -EINVAL; -+ } -+ -+ if (!ep->desc && (ep->num != 0)) { -+ dev_err(udc->dev, "%s: invalid EP state\n", ep->usb_ep.name); -+ return -EFAULT; -+ } -+ -+ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && !list_empty(&ep->list_queue)) { -+ dev_err(udc->dev, "%s: CTRL EP queue not empty\n", ep->usb_ep.name); -+ return -EPERM; -+ } -+ -+ if (usb_req->length > 16384 /* FSG_BUFLEN */) { -+ dev_err(udc->dev, "%s: request too big, length=%u\n", ep->usb_ep.name, usb_req->length); -+ return -E2BIG; -+ } -+ -+ /* -+ * Restrict ISOC IN requests to the max packet size. Assumption is that it does not make -+ * much sense to have more than one interval's (scheduled bandwidth's) worth of data. -+ */ -+ if ((ep->type == USB_ENDPOINT_XFER_ISOC) && (ep->dir == USB_DIR_IN) && (usb_req->length > ep->usb_ep.maxpacket)) { -+ dev_err(udc->dev, "%s: request > scheduled bandwidth, length=%u\n", ep->usb_ep.name, usb_req->length); -+ return -EFBIG; -+ } -+ -+ if (!udc->gadget_driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) { -+ dev_warn(udc->dev, "%s: invalid device state\n", ep->usb_ep.name); -+ return -ESHUTDOWN; -+ } -+ -+ if (((ulong)req->usb_req.buf) & 0x3UL) { -+ /* -+ * The DMA buffer does not have the alignment required by the hardware. We keep an endpoint level -+ * buffer available to handle this situation if it arises. If we don't currently have one available -+ * for this purpose, or if the current one is not large enough, then allocate a new one. Since -+ * we only have one buffer, we won't copy into the buffer until we are ready to do the DMA transfer. -+ * Mark the request as needing this alignment (copy). -+ */ -+ if ((ep->dma.align_buff != NULL) && (ep->dma.align_len < req->usb_req.length)) { -+ dma_free_coherent(NULL, ep->dma.align_len, ep->dma.align_buff, ep->dma.align_addr); -+ ep->dma.align_buff = NULL; -+ } -+ -+ if (ep->dma.align_buff == NULL) { -+ ep->dma.align_len = req->usb_req.length; -+ ep->dma.align_buff = dma_alloc_coherent(NULL, ep->dma.align_len, &(ep->dma.align_addr), GFP_KERNEL); -+ } -+ -+ if (ep->dma.align_buff == NULL) { -+ dev_err(udc->dev, "%s: dma_alloc_coherent() failed, length=%u\n", ep->usb_ep.name, usb_req->length); -+ return -ENOMEM; -+ } -+ -+ req->dma_aligned = 1; -+ } else if ((req->usb_req.dma == DMA_ADDR_INVALID) || (req->usb_req.dma == 0)) { -+ /* A physical address was not provided for the DMA buffer, so request it. */ -+ req->dma_mapped = 1; -+ req->usb_req.dma = dma_map_single(udc->gadget.dev.parent, -+ req->usb_req.buf, -+ req->usb_req.length, -+ (ep->dir == USB_DIR_IN ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ req->usb_req.status = -EINPROGRESS; -+ req->usb_req.actual = 0; -+ -+ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && (ep->dir == USB_DIR_OUT) && (req->usb_req.length == 0)) { -+ /* -+ * This might happen if gadget driver decides to send zero length packet (ZLP) during STATUS phase -+ * of a control transfer. This may happen for the cases where there is not a DATA phase. Just consider -+ * things complete. ZLP will be issued by hardware. See the handling of SETUP packets for more details -+ * on control transfer processing. -+ */ -+ iproc_udc_req_xfer_done(ep, req, ENOERROR); -+ } else { -+ if (req->usb_req.length == 0) { -+ req->usb_req.zero = 1; -+ } -+ iproc_udc_req_xfer_add(ep, req); -+ } -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ret; -+} -+ -+static int xgs_iproc_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ struct iproc_ep_req *req = our_req(usb_req); -+ ulong flags; -+ int ret = ENOERROR; -+ -+ if (!usb_ep || !usb_req) { -+ dev_err(udc->dev, "invalid request\n"); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ /* Make sure it's actually queued on this endpoint */ -+ list_for_each_entry(req, &ep->list_queue, list_node) { -+ if (&req->usb_req == usb_req) { -+ break; -+ } -+ } -+ -+ if (&req->usb_req != usb_req) { -+ spin_unlock_irqrestore(&udc->lock, flags); -+ dev_err(udc->dev, "%s: request not queued\n", ep->usb_ep.name); -+ return -ENOLINK; -+ } -+ -+ /** @todo Handle case where the request is in progress, or completed but not dequeued */ -+ -+ iproc_udc_req_xfer_done(ep, req, -ECONNRESET); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ret; -+} -+ -+static int xgs_iproc_ep_set_halt(struct usb_ep *usb_ep, int enable) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ ulong flags; -+ int ret = ENOERROR; -+ -+ if (!usb_ep) { -+ dev_err(udc->dev, "invalid request\n"); -+ return -EINVAL; -+ } -+ -+ if (ep->type == USB_ENDPOINT_XFER_ISOC) { -+ dev_warn(udc->dev, "%s: ISO HALT operations not supported\n", ep->usb_ep.name); -+ return -EOPNOTSUPP; -+ } -+ -+ if (enable && (ep->dir == USB_DIR_IN) && !list_empty(&ep->list_queue)) { -+ /* Only allow halt on an IN EP if its queue is empty */ -+ dev_err(udc->dev, "%s: IN queue not empty\n", ep->usb_ep.name); -+ return -EAGAIN; -+ } -+ -+ if (!enable && (ep->type == USB_ENDPOINT_XFER_CONTROL)) { -+ /* -+ * Halt clear for a control EP should only be handled as part of the subsequent SETUP -+ * exchange that occurs after the Halt was set. -+ */ -+ dev_warn(udc->dev, "%s: CTRL HALT clear\n", ep->usb_ep.name); -+ return -EPROTO; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ if (!enable) { -+ iproc_usbd_ep_stall_dis(udc->usbd_regs, ep->num, ep->dir); -+ } else if (ep->type != USB_ENDPOINT_XFER_CONTROL) { -+ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, ep->dir); -+ } else { -+ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_IN); -+ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_OUT); -+ } -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ mdelay(2); -+ -+ return ret; -+} -+ -+static int xgs_iproc_ep_fifo_status(struct usb_ep *usb_ep) -+{ -+ /* -+ * The DWC UDC core doesn't have a mechanism for determining the number of bytes -+ * currently in a FIFO. The best that can be done is determine whether or not a -+ * FIFO is empty. However, for the situation where a single Rx FIFO is being -+ * used for all endpoints, if cannot be determined which OUT and CTRL EP's are -+ * affected if the Rx FIFO is not empty. -+ */ -+ return -EOPNOTSUPP; -+} -+ -+static void xgs_iproc_ep_fifo_flush(struct usb_ep *usb_ep) -+{ -+ struct iproc_ep *ep = our_ep(usb_ep); -+ struct iproc_udc *udc = ep->udc; -+ ulong flags; -+ -+ if (!usb_ep) { -+ dev_err(udc->dev, "invalid request\n"); -+ return; -+ } -+ -+ /* -+ * FIFO flush for a control EP does not make any sense. The SETUP protocol -+ * should eliminate the need to flush. -+ */ -+ if (ep->type == USB_ENDPOINT_XFER_CONTROL) { -+ dev_warn(udc->dev, "%s: CTRL FIFO flush\n", ep->usb_ep.name); -+ return; -+ } -+ -+ if (iproc_usbd_ep_fifo_empty(udc->usbd_regs, ep->num, ep->dir)) { -+ dev_warn(udc->dev, "%s: FIFO empty\n", ep->usb_ep.name); -+ return; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ iproc_usbd_ep_fifo_flush_en(udc->usbd_regs, ep->num, ep->dir); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+} -+ -+/*************************************************************************** -+ * Routines for debug dump of DMA descriptors -+ **************************************************************************/ -+#ifdef IPROC_UDC_DEBUG -+static void iproc_dbg_dma_dump(struct iproc_udc *udc) -+{ -+ int idx; -+ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ iproc_dbg_dma_dump_ep(&udc->ep[idx]); -+ } -+} -+ -+static void iproc_dbg_dma_dump_desc(char *label, struct iproc_udc_dma_desc *virt, struct iproc_udc_dma_desc *phys) -+{ -+ printk("%s virt=0x%p phys=0x%p: 0x%08x 0x%08x 0x%08x", label, virt, phys, virt->status, virt->reserved, virt->buf_addr); -+} -+ -+static void iproc_dbg_dma_dump_ep(struct iproc_ep *ep) -+{ -+ int idx; -+ -+ printk("EP %d DMA\n", ep->num); -+ printk(" setup\n"); -+ iproc_dbg_dma_dump_desc(" ", (struct iproc_udc_dma_desc *)&ep->dma.vir_addr->setup, (struct iproc_udc_dma_desc *)&ep->dma.phy_addr->setup); -+ printk(" desc\n"); -+ -+ for (idx = 0; idx < IPROC_EP_DMA_DESC_CNT; idx++) { -+ iproc_dbg_dma_dump_desc(" ", &ep->dma.vir_addr->desc[idx], &ep->dma.phy_addr->desc[idx]); -+ -+ /* Don't bother displaying entries beyond the last. */ -+ if (IPROC_USBD_READ(ep->dma.vir_addr->desc[idx].status) & IPROC_USBD_REG_DMA_STAT_LAST_DESC) { -+ break; -+ } -+ } -+} -+#endif /* IPROC_UDC_DEBUG */ -+ -+/**************************************************************************** -+ * Initialization of DMA descriptors at the endpoint level. -+ ***************************************************************************/ -+static void iproc_dma_ep_init(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ int idx; -+ -+ /** @todo shorten names to virtAddr physAddr?? */ -+ ep->dma.vir_addr = &udc->dma.vir_addr->ep[ep->num]; -+ ep->dma.phy_addr = &udc->dma.phy_addr->ep[ep->num]; -+ -+ /* -+ * Control endpoints only do setup in the OUT direction, so only need to set the -+ * buffer address for that direction. The buffer is set, even if not a control -+ * endpoint, just to simplify things. There's no harm with this. -+ */ -+ ep->dma.vir_addr->setup.status = cpu_to_le32(IPROC_USBD_REG_DMA_STAT_BUF_HOST_BUSY); -+ wmb(); -+ iproc_usbd_ep_dma_buf_addr_set(udc->usbd_regs, ep->num, USB_DIR_OUT, &ep->dma.phy_addr->setup); -+ -+ /* -+ * Take ownership of the DMA descriptors, and chain them in a loop. This allows a small number -+ * descriptors to be used for requests. Need to have the DWC DMA Descriptor Update option enabled -+ * in the device control register in order to do this. When a transfer for a descriptor completes, -+ * the descriptor will get re-used if there's still data left in a request to transfer. See the -+ * iproc_dma_data_rm_done() and iproc_dma_data_add_ready() routines. -+ */ -+ /** @todo Put these in endpoint context?? */ -+ for (idx = 0; idx < IPROC_EP_DMA_DESC_CNT; idx++) { -+ ep->dma.vir_addr->desc[idx].status = cpu_to_le32(IPROC_USBD_REG_DMA_STAT_BUF_HOST_BUSY); -+ wmb(); -+ ep->dma.vir_addr->desc[idx].next_addr = cpu_to_le32((uint)&ep->dma.phy_addr->desc[idx+1]); -+ } -+ ep->dma.vir_addr->desc[(IPROC_EP_DMA_DESC_CNT - 1)].next_addr = cpu_to_le32((uint)&ep->dma.phy_addr->desc[0]); -+ -+ /* -+ * To simplify things, register the descriptor chain in both directions. Control endpoints are the -+ * only type that will be transferring in both directions, but they will only be transferring in one -+ * direction at a time, so should not be any issues with using the same descriptor set for both directions. -+ * For single direction endpoints, the other direction will not be used. -+ */ -+ -+ iproc_usbd_ep_dma_desc_addr_set(udc->usbd_regs, ep->num, USB_DIR_OUT, &ep->dma.phy_addr->desc[0]); -+ iproc_usbd_ep_dma_desc_addr_set(udc->usbd_regs, ep->num, USB_DIR_IN, &ep->dma.phy_addr->desc[0]); -+} -+ -+/**************************************************************************** -+ * DMA data routines. -+ * -+ * A gadget usb_request buf is used for the data. The entire buf contents may -+ * or may not fit into the descriptor chain at once. When the DMA transfer -+ * associated with a descriptor completes, the descriptor is re-used to add -+ * more segments of the usb_request to the chain as necessary. -+ * -+ * iproc_dma_data_init - Initialization in preparation for DMA of usb_request. -+ * iproc_dma_data_add_ready - Adds usb_request segments into DMA chain until full or no segments left -+ * iproc_dma_data_rm_done - Removes usb_request segments from DMA chain that have completed transfer -+ * iproc_dma_data_finish - Final stage of DMA of the usb_request -+ * -+ ***************************************************************************/ -+static void iproc_dma_data_init(struct iproc_ep *ep) -+{ -+ struct iproc_ep_req *req; -+ struct iproc_udc *udc = ep->udc; -+ -+ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); -+ -+ if (req->dma_aligned) { -+ /* -+ * This buffer needs to be aligned in order to DMA. We do this by copying into a special buffer we -+ * have for this purpose. Save the original DMA physical address so it can be restored later. -+ * This may not be used, but we'll do it anyways. Then set the DMA address to the aligned buffer -+ * address. Only the DMA physical address is used for the transfers, so the original buffer virtual -+ * address does not need to be changed. Then copy the data into the aligned buffer. -+ */ -+ /** @todo Really only need to do the memcpy for IN data */ -+ -+ req->orig_dma_addr = req->usb_req.dma; -+ req->usb_req.dma = ep->dma.align_addr; -+ memcpy(ep->dma.align_buff, req->usb_req.buf, req->usb_req.length); -+ } -+ -+ ep->dma.done = 0; -+ ep->dma.done_len = 0; -+ ep->dma.todo_len = ep->dma.usb_req->length; -+ ep->dma.buf_addr = ep->dma.usb_req->dma; -+ ep->dma.status = IPROC_USBD_REG_DMA_STAT_RX_SUCCESS; -+ -+ if ((ep->dir == USB_DIR_IN) && (ep->type != USB_ENDPOINT_XFER_ISOC)) { -+ /* -+ * For IN transfers, do not need to segment the buffer into max packet portions -+ * for the DMA descriptors. The hardware will automatically segment into max -+ * packet sizes as necessary. -+ */ -+ ep->dma.max_buf_len = ep->usb_ep.maxpacket; -+ -+ /* -+ * If the request is of zero length, then force the zero flag so iproc_dma_data_add_ready() -+ * will queue the request. Conversely, if the gadget has set the zero flag, leave -+ * it set only if it is needed (request length is a multiple of maxpacket) -+ */ -+ if (ep->dma.usb_req->length == 0) { -+ ep->dma.usb_req->zero = 1; -+ } else if (ep->dma.usb_req->zero) { -+ ep->dma.usb_req->zero = (ep->dma.usb_req->length % ep->usb_ep.maxpacket) ? 0 : 1; -+ } -+ } else { -+ ep->dma.max_buf_len = ep->usb_ep.maxpacket; -+ } -+ -+ dma_desc_chain_reset(ep); -+ -+ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, ep->dir); -+} -+ -+static void iproc_dma_data_finish(struct iproc_ep *ep) -+{ -+ struct iproc_ep_req *req; -+ struct iproc_udc *udc = ep->udc; -+ -+ iproc_usbd_ep_irq_dis(udc->usbd_regs, ep->num, ep->dir); -+ iproc_usbd_ep_dma_dis(udc->usbd_regs, ep->num, ep->dir); -+ -+ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); -+ -+ if (req->dma_aligned) { -+ /* -+ * The original request buffer was not aligned properly, so a special buffer was used -+ * for the transfer. Copy the aligned buffer contents into the original. Also restore -+ * the original dma physical address. -+ */ -+ /** @todo Really only need to do the memcpy for OUT setup/data */ -+ memcpy(req->usb_req.buf, ep->dma.align_buff, req->usb_req.length); -+ req->usb_req.dma = req->orig_dma_addr; -+ } -+} -+ -+static void iproc_dma_data_add_ready(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ volatile struct iproc_udc_dma_desc *dma_desc = NULL; -+ uint status; -+ uint len; -+ int enable_dma = 0; -+ -+ /* -+ * DMA must be disabled while this loop is running, as multi-descriptor transfers -+ * will have the descriptor chain in an intermediate state until the last descriptor -+ * is written and the chain terminated. -+ */ -+ if (iproc_usbd_dma_status(udc->usbd_regs)) { -+ enable_dma = 1; -+ iproc_usbd_dma_dis(udc->usbd_regs); -+ } -+ -+ if (!ep->dma.todo_len) { -+ ep->dma.usb_req->zero = 1; -+ } -+ -+ /* -+ * Will only have one request in the chain at a time. Add request segments to the -+ * chain until all parts of the request have been put in the chain or the chain -+ * has no more room. -+ */ -+ while (!dma_desc_chain_full(ep) && (ep->dma.todo_len || ep->dma.usb_req->zero)) { -+ /* -+ * Get the next descriptor in the chain, and then fill the descriptor contents as needed. -+ * Do not set the descriptor buffer status to ready until last to ensure there's no -+ * contention with the hardware. -+ */ -+ dma_desc = dma_desc_chain_alloc(ep); -+ -+ len = ep->dma.todo_len < ep->dma.max_buf_len ? ep->dma.todo_len : ep->dma.max_buf_len; -+ ep->dma.todo_len -= len; -+ -+ status = 0; -+ -+ if (len < ep->dma.max_buf_len) { -+ /* -+ * If this segment is less than the max, then it is the last segment. There's no need to -+ * send a closing ZLP, although this segment might be a ZLP. Regardless, clear the ZLP flag -+ * to ensure that the processing of this request finishes. Also set the end of the descriptor -+ * chain. -+ */ -+ ep->dma.usb_req->zero = 0; -+ status |= IPROC_USBD_REG_DMA_STAT_LAST_DESC; -+ } else if ((ep->dma.todo_len == 0) && !ep->dma.usb_req->zero) { -+ /* -+ * Segment is of the max packet length. Since there's nothing left, it has to also be the last -+ * last segment. No closing ZLP segment requested, just set the end of the descriptor chain. -+ */ -+ status |= IPROC_USBD_REG_DMA_STAT_LAST_DESC; -+ } -+ -+ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)) { -+ /* -+ * Increment the frame number for transmit, then use it for the next packet. The frame number -+ * may get larger than its 13-bit size, but the mask will handle the wrap-around so we don't -+ * need to add checks for this condition. E.g. 0x7ff + 1 = 0x800. 0x800 & 0x7ff = 0 which -+ * is the next number in the sequence. -+ */ -+ /** @todo Handle ISOC PIDs and frame numbers used with HS high bandwidth transfers */ -+ /** @todo Might not need to set the last descriptor status. Currently restricting -+ * IN ISOC transfers to the max packet size. -+ */ -+ status |= IPROC_USBD_REG_DMA_STAT_LAST_DESC; -+ -+ ep->dma.frame_num += ep->dma.frame_incr; -+ status |= ((ep->dma.frame_num << IPROC_USBD_REG_DMA_STAT_FRAME_NUM_SHIFT) & IPROC_USBD_REG_DMA_STAT_FRAME_NUM_MASK); -+ } -+ -+ IPROC_USBD_WRITE(dma_desc->buf_addr, ep->dma.buf_addr); -+ status |= (len << IPROC_USBD_REG_DMA_STAT_BYTE_CNT_SHIFT); -+ IPROC_USBD_WRITE(dma_desc->status, status | IPROC_USBD_REG_DMA_STAT_BUF_HOST_READY); -+ wmb(); -+ ep->dma.buf_addr += len; -+ -+ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)) { -+ /* With ISOC transfers, only enable one DMA descriptors at a time. -+ */ -+ /** @todo Determine if FIFO will overflow. If it does not, then can remove this check. -+ * This may not even be an issue if the buffer size is restricted to the max packet size -+ * when a request is submitted to the endpoint. -+ */ -+ break; -+ } -+ } -+ /* Set LAST bit on last descriptor we've configured */ -+ if (dma_desc) { -+ IPROC_USBD_BITS_SET(dma_desc->status, IPROC_USBD_REG_DMA_STAT_LAST_DESC); -+ } -+ -+ if (enable_dma) { -+ iproc_usbd_dma_en(udc->usbd_regs); -+ } -+} -+ -+static void iproc_dma_data_rm_done(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ volatile struct iproc_udc_dma_desc *dma_desc; -+ uint status; -+ uint len; -+ -+ /* -+ * Will only have one request in the chain at a time. Remove any completed -+ * request segments from the chain so any segments awaiting transfer can -+ * be put in the chain. -+ */ -+ while (!dma_desc_chain_empty(ep)) { -+ /* -+ * Examine the first entry in the chain. If its status is not done, then there's -+ * nothing to remove. -+ */ -+ dma_desc = dma_desc_chain_head(ep); -+ -+ if ((IPROC_USBD_READ(dma_desc->status) & IPROC_USBD_REG_DMA_STAT_BUF_MASK) != IPROC_USBD_REG_DMA_STAT_BUF_DMA_DONE) { -+ break; -+ } -+ -+ /* -+ * The transfer of this request segment has completed. Save the status info and then -+ * take ownership of the descriptor. It is simpler to do this than modifying parts of -+ * the descriptor in order to take ownership. Don't put the descriptor back in the chain -+ * until all info affected by the status has been updated, just to be safe. -+ */ -+ status = IPROC_USBD_READ(dma_desc->status); -+ IPROC_USBD_WRITE(dma_desc->status, IPROC_USBD_REG_DMA_STAT_BUF_HOST_BUSY); -+ wmb(); -+ -+ len = (status & IPROC_USBD_REG_DMA_STAT_NON_ISO_BYTE_CNT_MASK) >> IPROC_USBD_REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT; -+ -+ /* RX: For multiple descriptors, len is cumulative, not absolute. -+ * RX: So only adjust the dma fields when we get to the last descriptor -+ * TX: Each descriptor entry is absolute, count them all -+ */ -+ if ((ep->dir == USB_DIR_IN) || (status & IPROC_USBD_REG_DMA_STAT_LAST_DESC)) { -+ ep->dma.done_len += len; -+ ep->dma.usb_req->actual += len; -+ } -+ -+ if ((status & IPROC_USBD_REG_DMA_STAT_RX_MASK) != IPROC_USBD_REG_DMA_STAT_RX_SUCCESS) { -+ ep->dma.status = status & IPROC_USBD_REG_DMA_STAT_RX_MASK; -+ ep->dma.usb_req->status = -EIO; -+ dev_warn(udc->dev, "%s: DMA error: desc=0x%p status=0x%x len=%d add=0x%x remove=0x%x\n", -+ ep->usb_ep.name, dma_desc, status, len, ep->dma.add_idx, ep->dma.rm_idx); -+ } -+ -+ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC)){ -+ /** @todo Determine if this special processing needs to be done. May not to do this if the -+ * buffer size is restricted to the max packet size when a request is submitted to the endpoint. -+ */ -+ if (ep->dma.usb_req->actual == ep->dma.usb_req->length) { -+ ep->dma.usb_req->status = ENOERROR; -+ } -+ dma_desc_chain_reset(ep); -+ } else { -+ dma_desc_chain_free(ep); -+ } -+ } -+ -+ /* When last segment processed, update status if there has not been an error */ -+ if (!ep->dma.todo_len && (ep->dma.usb_req->status == -EINPROGRESS)) { -+ ep->dma.usb_req->status = ENOERROR; -+ } -+} -+ -+/*************************************************************************** -+ * UDC Operations routines. -+ * iproc_udc_ops_init - Initialization of the UDC in preparation for use by Gadget driver. -+ * iproc_udc_ops_start - Start UDC operations. Happens after a Gadget driver attaches. -+ * iproc_udc_ops_stop - Stop UDC operations. Happens after a Gadget driver detaches. -+ * iproc_udc_ops_finish - Finish / terminate all UDC operations -+ ***************************************************************************/ -+static void iproc_udc_ops_finish(struct iproc_udc *udc) -+{ -+ /* do nothing */ -+ return; -+} -+ -+static void iproc_udc_ops_init(struct iproc_udc *udc) -+{ -+ int idx; -+ struct iproc_ep *ep; -+ -+ iproc_usbd_ops_init(udc->usbd_regs); -+ -+ /* -+ * See usb/gadget/epautoconf.c for endpoint naming conventions. -+ * Control endpoints are bi-directional, but initial transfer (SETUP stage) is always OUT. -+ */ -+ /** @todo Really should make the non endpoint 0 init attributes configurable by the chip specific part -+ * of the driver, idx.e. the device instantiation. The settings below are for a chip specific DWG UDC -+ * core configuration. Also should incorporate the DWG UDC endpoint type attribute as part of this, -+ * which can be control, IN, OUT, or bidirectional. -+ */ -+ INIT_LIST_HEAD(&udc->gadget.ep_list); -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ ep = &udc->ep[idx]; -+ -+ ep->udc = udc; -+ ep->num = idx; -+ -+ ep->dir = (xgs_iproc_ep_info[idx].caps.dir_in) ? USB_DIR_IN : USB_DIR_OUT;; -+ ep->beq_addr = idx | ep->dir; -+ ep->stopped = 0; -+ ep->type = xgs_iproc_ep_info[idx].type; -+ -+ ep->usb_ep.name = xgs_iproc_ep_info[idx].name; -+ ep->usb_ep.caps = xgs_iproc_ep_info[idx].caps; -+ ep->usb_ep.ops = &xgs_iproc_udc_ep_ops; -+ list_add_tail(&ep->usb_ep.ep_list, &udc->gadget.ep_list); -+ usb_ep_set_maxpacket_limit(&ep->usb_ep, xgs_iproc_ep_info[idx].msize); -+ ep->usb_ep.desc = NULL; -+ INIT_LIST_HEAD(&ep->list_queue); -+ -+ iproc_usbd_ep_ops_init(udc->usbd_regs, ep->num, ep->type, ep->dir, xgs_iproc_ep_info[idx].msize); -+ -+ iproc_dma_ep_init(ep); -+ } -+ -+ udc->gadget.ep0 = &udc->ep[0].usb_ep; -+ list_del(&udc->ep[0].usb_ep.ep_list); -+ -+ iproc_usbd_self_pwr_en(udc->usbd_regs); -+} -+ -+static void iproc_udc_ops_start(struct iproc_udc *udc) -+{ -+ int idx; -+ -+ /* -+ * Just enable interrupts for now. Endpoint 0 will get enabled once the speed enumeration -+ * has completed. The Device DMA enable is global in scope. There's endpoint specific -+ * DMA enables that will happen later. -+ */ -+ iproc_usbd_irq_en(udc->usbd_regs, (IPROC_USBD_IRQ_SPEED_ENUM_DONE | -+ IPROC_USBD_IRQ_BUS_SUSPEND | -+ IPROC_USBD_IRQ_BUS_IDLE | -+ IPROC_USBD_IRQ_BUS_RESET | -+ IPROC_USBD_IRQ_SET_INTF | -+ IPROC_USBD_IRQ_SET_CFG)); -+ iproc_usbd_dma_en(udc->usbd_regs); -+ -+ /* Enable interrupts for all configured endpoints */ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; ++idx) { -+ if (udc->ep[idx].usb_ep.name) { -+ iproc_usbd_ep_irq_en(udc->usbd_regs, udc->ep[idx].num, USB_DIR_OUT); -+ iproc_usbd_ep_irq_en(udc->usbd_regs, udc->ep[idx].num, USB_DIR_IN); -+ } -+ } -+ iproc_usbd_nak_response_dis(udc->usbd_regs); -+} -+ -+static void iproc_udc_ops_stop(struct iproc_udc *udc) -+{ -+ struct iproc_ep *ep; -+ -+ iproc_usbd_dma_dis(udc->usbd_regs); -+ iproc_usbd_irq_dis(udc->usbd_regs, IPROC_USBD_IRQ_ALL); -+ iproc_usbd_irq_clear(udc->usbd_regs, IPROC_USBD_IRQ_ALL); -+ -+ udc->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ iproc_udc_req_queue_flush(&udc->ep[0], -ESHUTDOWN); -+ list_for_each_entry(ep, &udc->gadget.ep_list, usb_ep.ep_list) { -+ iproc_udc_req_queue_flush(ep, -ESHUTDOWN); -+ } -+} -+ -+static void iproc_udc_ops_disconnect(struct iproc_udc *udc) -+{ -+ struct iproc_ep *ep; -+ int idx; -+ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ ep = &udc->ep[idx]; -+ -+ if (ep->dma.usb_req) { -+ /* Flush DMA, reqeust still pending */ -+ iproc_usbd_ep_fifo_flush_en(udc->usbd_regs, 0, IPROC_USBD_EP_DIR_IN); -+ iproc_usbd_ep_fifo_flush_dis(udc->usbd_regs, 0, IPROC_USBD_EP_DIR_IN); -+ -+ iproc_udc_req_xfer_process(ep); -+ } -+ } -+} -+ -+static void iproc_udc_ops_shutdown(struct iproc_udc *udc) -+{ -+ struct iproc_ep *ep; -+ -+ udc->ep[0].desc = NULL; -+ list_for_each_entry(ep, &udc->gadget.ep_list, usb_ep.ep_list) { -+ ep->desc = NULL; -+ } -+ -+ udc->gadget.dev.driver = NULL; -+ udc->gadget_driver = NULL; -+} -+ -+ -+/**************************************************************************** -+ * Control Endpoint SETUP related routines. -+ * -+ * iproc_ep_setup_init - Prepares for next SETUP Rx. Status indicates if STALL req'd. -+ * iproc_ep_setup_process - Handle Rx of a SETUP. -+ ***************************************************************************/ -+static void iproc_ep_setup_init(struct iproc_ep *ep, int status) -+{ -+ struct iproc_udc *udc = ep->udc; -+ -+ /* Re-enable transfers to the SETUP buffer, clear IN and OUT NAKs, and re-enable OUT interrupts. */ -+ ep->dma.vir_addr->setup.status = cpu_to_le32(IPROC_USBD_REG_DMA_STAT_BUF_HOST_READY); -+ ep->dir = USB_DIR_OUT; -+ ep->stopped = 0; -+ -+ if (status == ENOERROR) { -+ /* Handling of previous SETUP was OK. Just clear any NAKs. */ -+ -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_OUT); -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_IN); -+ } else { -+ /* -+ * Handling of previous SETUP failed. Set the STALL. This will get cleared -+ * when the next SETUP is rx'd. -+ */ -+ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_IN); -+ iproc_usbd_ep_stall_en(udc->usbd_regs, ep->num, USB_DIR_OUT); -+ } -+ -+ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, USB_DIR_OUT); -+ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, USB_DIR_OUT); -+} -+ -+void iproc_ep_setup_process(struct iproc_ep *ep, struct usb_ctrlrequest *setup) -+{ -+ struct iproc_udc *udc = ep->udc; -+ uint value; -+ uint index; -+ uint length; -+ int status; -+ -+ value = le16_to_cpu(setup->wValue); -+ index = le16_to_cpu(setup->wIndex); -+ length = le16_to_cpu(setup->wLength); -+ -+ /* -+ * Any SETUP packets appearing here need to be handled by the gadget driver. Some SETUPs may have -+ * already been silently handled and acknowledged by the DWC UDC. The exceptions to this rule are the -+ * USB_REQ_SET_CONFIGURATION and USB_REQ_SET_INTERFACE, which have been only partially handled with -+ * the expectation that some additional software processing is required in order to complete these requests. -+ * Thus, they have not been acknowledged by the DWC UDC. There is no DATA stage for these requests. -+ */ -+ -+ /* -+ * Set the direction of the subsequent DATA stage of a control transfer. This is an -+ * optional stage. It may not exist for all control transfers. If there is a DATA -+ * stage, this info is used for DMA operations for any requests received from the -+ * Gadget driver. -+ */ -+ -+ ep->dir = setup->bRequestType & USB_ENDPOINT_DIR_MASK; -+ -+ if (ep->num != 0) { -+ /** @todo Make changes here if the Linux USB gadget ever supports a control endpoint other -+ * than endpoint 0. The DWC UDC supports multiple control endpoints, and this driver has -+ * been written with this in mind. To make things work, really need to change the Gadget -+ * setup() callback parameters to provide an endpoint context, or add something similar -+ * to the usb_ep structure, or possibly use a usb_request to hold a setup data packet. -+ */ -+ -+ dev_err(udc->dev, "%s: control transfer not supported\n", ep->usb_ep.name); -+ status = -EOPNOTSUPP; -+ } else { -+ /* -+ * Forward the SETUP to the gadget driver for processing. The appropriate directional -+ * interrupt and NAK clear will happen when the DATA stage request is queued. -+ */ -+ spin_unlock(&udc->lock); -+ status = udc->gadget_driver->setup(&udc->gadget, setup); -+ spin_lock(&udc->lock); -+ } -+ -+ if (status < 0) { -+ /* -+ * Error occurred during the processing of the SETUP, so enable STALL. This condition -+ * can only be cleared with the RX of another SETUP, so prepare for that event. -+ */ -+ dev_err(udc->dev, "%s: SETUP %02x.%02x STALL; status=%d\n", -+ ep->usb_ep.name, setup->bRequestType, setup->bRequest, status); -+ -+ iproc_ep_setup_init(ep, status); -+ } else if (length == 0) { -+ /* No DATA stage. Just need to prepare for the next SETUP. */ -+ iproc_ep_setup_init(ep, ENOERROR); -+ } else { -+ /* -+ * The SETUP stage processing has completed OK, and there may or may not be a request queued -+ * for the DATA stage. When the DATA stage completes, preparation for the RX of the next -+ * SETUP will be done. -+ */ -+ } -+} -+ -+ -+/**************************************************************************** -+ * IRQ routines. -+ * -+ * xgs_iproc_udc_isr - top level entry point. -+ * iproc_cfg_isr - device (endpoint 0) set config interrupt handler -+ * iproc_inf_isr - device (endpoint 0) set interface interrupt handler -+ * iproc_speed_isr - device speed enumeration done interrupt handler -+ * iproc_ep_in_isr - top level IN endpoint related interrupt handler -+ * iproc_ep_out_isr - top level OUT endpoint related interrupt handler -+ * iproc_ep_out_setup_isr - Control endpoint SETUP Rx handler. This may get -+ * called directly as the result of an endpoint OUT interrupt, or -+ * indirectly as the result of device SET_CFG or SET_INTF. -+ ***************************************************************************/ -+static void iproc_cfg_isr(struct iproc_udc *udc) -+{ -+ struct usb_ctrlrequest setup; -+ int idx; -+ u16 cfg; -+ -+ /* -+ * Device Configuration SETUP has been received. This is not placed in the SETUP -+ * DMA buffer. The packet has to be re-created here so it can be forwarded to the -+ * gadget driver to act upon. -+ */ -+ -+ cfg = (u16) iproc_usbd_cfg_num(udc->usbd_regs); -+ -+ setup.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; -+ setup.bRequest = USB_REQ_SET_CONFIGURATION; -+ setup.wValue = cpu_to_le16(cfg); -+ setup.wIndex = 0; -+ setup.wLength = 0; -+ -+ /* -+ * Setting the configuration number before the gadget responds is a bit presumptious, but should -+ * not be fatal. -+ */ -+ /** @todo Do not set endpoint 0? Or is it a don't care? */ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ iproc_usbd_ep_cfg_set(udc->usbd_regs, idx, cfg); -+ } -+ -+ printk(KERN_INFO "SET CFG=%d\n", cfg); -+ -+ iproc_ep_setup_process(&udc->ep[0], &setup); -+ iproc_usbd_setup_done(udc->usbd_regs); -+} -+ -+static void iproc_inf_isr(struct iproc_udc *udc) -+{ -+ struct usb_ctrlrequest setup; -+ uint idx; -+ u16 intf; -+ u16 alt; -+ -+ /* -+ * Device Interface SETUP has been received. This is not placed in the SETUP -+ * DMA buffer. The packet has to be re-created here so it can be forwarded to the -+ * gadget driver to act upon. -+ */ -+ intf = (u16)iproc_usbd_intf_num(udc->usbd_regs); -+ alt = (u16)iproc_usbd_alt_num(udc->usbd_regs); -+ -+ setup.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE; -+ setup.bRequest = USB_REQ_SET_INTERFACE; -+ setup.wValue = cpu_to_le16(alt); -+ setup.wIndex = cpu_to_le16(intf); -+ setup.wLength = 0; -+ -+ /* -+ * Setting the interface numbers before the gadget responds is a bit presumptious, but should -+ * not be fatal. -+ */ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ iproc_usbd_ep_alt_set(udc->usbd_regs, idx, alt); -+ iproc_usbd_ep_intf_set(udc->usbd_regs, idx, intf); -+ } -+ -+ iproc_ep_setup_process(&udc->ep[0], &setup); -+ iproc_usbd_setup_done(udc->usbd_regs); -+} -+ -+static void iproc_speed_isr(struct iproc_udc *udc) -+{ -+ uint speed; -+ -+ speed = udc->gadget.speed; -+ -+ switch(iproc_usbd_speed_get(udc->usbd_regs)) { -+ case IPROC_USBD_SPEED_HIGH: -+ printk(KERN_INFO "HIGH SPEED\n"); -+ udc->gadget.speed = USB_SPEED_HIGH; -+ break; -+ case IPROC_USBD_SPEED_FULL: -+ printk(KERN_INFO "FULL SPEED\n"); -+ udc->gadget.speed = USB_SPEED_FULL; -+ break; -+ case IPROC_USBD_SPEED_LOW: -+ dev_warn(udc->dev, "low speed not supported\n"); -+ udc->gadget.speed = USB_SPEED_LOW; -+ break; -+ default: -+ dev_err(udc->dev, "unknown speed=0x%x\n", iproc_usbd_speed_get(udc->usbd_regs)); -+ break; -+ } -+ -+ if ((speed == USB_SPEED_UNKNOWN) && (udc->gadget.speed != USB_SPEED_UNKNOWN)) { -+ /* -+ * Speed has not been enumerated before, so now we can initialize transfers on endpoint 0. -+ * Also have to disable the NAKs at a global level, which has been in place while waiting -+ * for enumeration to complete. -+ */ -+ iproc_ep_setup_init(&udc->ep[0], ENOERROR); -+ iproc_usbd_nak_response_dis(udc->usbd_regs); -+ } -+} -+ -+static void iproc_ep_in_isr(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ uint status; -+ -+ status = iproc_usbd_ep_stat_active(udc->usbd_regs, ep->num, USB_DIR_IN); -+ iproc_usbd_ep_stat_clear(udc->usbd_regs, ep->num, USB_DIR_IN, status); -+ -+ if (!status) { -+ return; -+ } -+ -+ /** @todo check might only be for direction... */ -+ if ((ep->dir != USB_DIR_IN) && (ep->type != USB_ENDPOINT_XFER_CONTROL)) { -+ dev_err(udc->dev, "%s: unexpected IN interrupt\n", ep->usb_ep.name); -+ return; -+ } -+ -+ if (ep->dir != USB_DIR_IN) { -+ /* This probably should not be happening */ -+ dev_warn(udc->dev, "%s: CTRL dir OUT\n", ep->usb_ep.name); -+ } -+ -+ if ((ep->type == USB_ENDPOINT_XFER_ISOC) && -+ (status & (IPROC_USBD_EP_STAT_IN_XFER_DONE | IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL))) { -+ dev_warn(udc->dev, "%s: ISOC IN unexpected status=0x%x\n", ep->usb_ep.name, status); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_IN_TOKEN_RX) { -+ /* -+ * If there's any IN requests, the DMA should be setup and ready to go if -+ * the endpoint is not an ISOC. Nothing to do in this case. However, if -+ * this is an ISOC endpoint, then this interrupt implies there was no -+ * data available for this frame number. This will happen if the gadget -+ * does not have any data queued to send in this frame, or we have been -+ * waiting for this event to occur so we can get alignment with the host -+ * for the interval. This alignment is necessary when the interval is -+ * greater than one frame / uframe. E.g. for an audio stream sending -+ * samples @ 5ms intervals on a FS link, this corresponds to a period -+ * of 5 frames. Samples with be queued for every 5th frame number after -+ * the frame number in which this interrupt occurred. -+ */ -+ status &= ~IPROC_USBD_EP_STAT_IN_TOKEN_RX; -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, USB_DIR_IN); -+ -+ if ((ep->type == USB_ENDPOINT_XFER_ISOC)) { -+ /* Always align to the current frame number for subsequent transfers. */ -+ ep->dma.frame_num = iproc_usbd_last_rx_frame_num(udc->usbd_regs); -+ if (ep->dma.usb_req != NULL) { -+ /* -+ * Might have something queued when waiting for alignment. If something is queued, -+ * it is already too late for the current transfer point. It will also have been -+ * placed in the queue at some point before this interrupt, and it will be stale -+ * if we try to transmit at the next transfer point. -+ */ -+ ep->dma.usb_req->status = -EREMOTEIO; -+ iproc_udc_req_xfer_process(ep); -+ } -+ } -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_IN_DMA_DONE) { -+ /* -+ * DMA has completed, but cannot start next transfer until IPROC_USBD_EP_STAT_IN_XFER_DONE. -+ * To avoid race conditions and other issues, do not release the current transfer until both -+ * interrupts have arrived. Normally this interrupt will arrive at or before the IN_XFER_DONE, -+ * but there have been situations when the system is under load that this interrupt might -+ * arrive after the IN_XFER_DONE, in which case we will need to do the processing now. -+ * The exception to this rule is for ISOC endpoints. They will only get this interrupt to -+ * indicate that DMA has completed. -+ */ -+ status &= ~IPROC_USBD_EP_STAT_IN_DMA_DONE; -+ -+ if ((ep->type == USB_ENDPOINT_XFER_ISOC)) { -+ iproc_udc_req_xfer_process(ep); -+ } else if (ep->dma.done & IPROC_USBD_EP_STAT_IN_XFER_DONE) { -+ /* -+ * Did not receive the IN_DMA_DONE interrupt for this request before or -+ * at the same time as the IN_XFER_DONE interrupt, so the request -+ * processing was postponed until the IN_DMA_DONE interrupt arrived. -+ * See handling of IN_XFER_DONE status below. -+ */ -+ iproc_udc_req_xfer_process(ep); -+ } else { -+ /* -+ * IN_DMA_DONE received. Save this info so request processing will be -+ * done when the IN_XFER_DONE interrupt is received. This may happen -+ * immediately, idx.e. both IN_DMA_DONE and IN_XFER_DONE status are -+ * set when the interrupt processing takes place. -+ */ -+ ep->dma.done = IPROC_USBD_EP_STAT_IN_DMA_DONE; -+ } -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_IN_XFER_DONE) { -+ status &= ~(IPROC_USBD_EP_STAT_IN_XFER_DONE); -+ status &= ~(IPROC_USBD_EP_STAT_IN_FIFO_EMPTY); -+ -+ if (ep->dma.done & IPROC_USBD_EP_STAT_IN_DMA_DONE) { -+ /* -+ * Have received both the IN_DMA_DONE and IN_XFER_DONE interrupts -+ * for this request. OK to process the request (remove the request -+ * and start the next one). -+ */ -+ iproc_udc_req_xfer_process(ep); -+ } else { -+ /* -+ * Have not received the IN_DMA_DONE interrupt for this request. -+ * Need to postpone processing of the request until the IN_DMA_DONE -+ * interrupt occurs. See handling of IN_DMA_DONE status above. -+ */ -+ ep->dma.done = IPROC_USBD_EP_STAT_IN_XFER_DONE; -+ } -+ } -+ -+ /* Clear the FIFO EMPTY bit, not to print error message */ -+ status &= ~(IPROC_USBD_EP_STAT_IN_FIFO_EMPTY); -+ -+ if (status & IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL) { -+ dev_err(udc->dev, "%s: DMA BUF NOT AVAIL\n", ep->usb_ep.name); -+ status &= ~(IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL); -+ iproc_udc_req_xfer_process(ep); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_DMA_ERROR) { -+ status &= ~IPROC_USBD_EP_STAT_DMA_ERROR; -+ dev_err(udc->dev, "%s: DMA ERROR\n", ep->usb_ep.name); -+ iproc_udc_req_xfer_error(ep, -EIO); -+ } -+ -+ if (status) { -+ dev_err(udc->dev, "exit: %s %s: unknown status=0x%x\n", __func__, ep->usb_ep.name, status); -+ } -+} -+ -+static void iproc_ep_out_setup_isr(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ struct iproc_udc_dma_setup *dma; -+ -+ dma = &ep->dma.vir_addr->setup; -+ if ((IPROC_USBD_READ(dma->status) & IPROC_USBD_REG_DMA_STAT_BUF_MASK) != IPROC_USBD_REG_DMA_STAT_BUF_DMA_DONE) { -+ dev_err(udc->dev, "%s: unexpected DMA buf status=0x%x\n", ep->usb_ep.name, (IPROC_USBD_READ(dma->status) & IPROC_USBD_REG_DMA_STAT_BUF_MASK)); -+ iproc_ep_setup_init(ep, ENOERROR); -+ } else if ((IPROC_USBD_READ(dma->status) & IPROC_USBD_REG_DMA_STAT_RX_MASK) != IPROC_USBD_REG_DMA_STAT_RX_SUCCESS) { -+ dev_err(udc->dev, "%s: unexpected DMA rx status=0x%x\n", ep->usb_ep.name, (IPROC_USBD_READ(dma->status) & IPROC_USBD_REG_DMA_STAT_RX_MASK)); -+ iproc_ep_setup_init(ep, ENOERROR); -+ } else { -+ if (ep->num != 0) { -+ /** @todo Handle the cfg / intf / alt fields of the DMA status. This will only be any issue -+ * once the Linux Gadget driver framework supports control transfers on an endpoint other -+ * than 0. -+ */ -+ dev_warn(udc->dev, "%s: CTRL xfr support not complete\n", ep->usb_ep.name); -+ } -+ /* -+ * Take ownership of the descriptor while processing the request. Ownership will be released -+ * when ready to Rx SETUP again. -+ */ -+ IPROC_USBD_BITS_MODIFY(dma->status, IPROC_USBD_REG_DMA_STAT_BUF_MASK, IPROC_USBD_REG_DMA_STAT_BUF_HOST_BUSY); -+ iproc_ep_setup_process(ep, (struct usb_ctrlrequest *)&dma->data1); -+ } -+} -+ -+static void iproc_ep_out_isr(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ uint status; -+ -+ status = iproc_usbd_ep_stat_active(udc->usbd_regs, ep->num, USB_DIR_OUT); -+ iproc_usbd_ep_stat_clear(udc->usbd_regs, ep->num, USB_DIR_OUT, status); -+ -+ /* -+ * Remove the Rx packet size field from the status. The datasheet states this field is not used -+ * in DMA mode, but that is not true. -+ */ -+ status &= IPROC_USBD_EP_STAT_ALL; -+ -+ if (!status) { -+ return; -+ } -+ -+ if ((ep->dir != USB_DIR_OUT) && (ep->type != USB_ENDPOINT_XFER_CONTROL)) { -+ dev_err(udc->dev, "%s: unexpected OUT interrupt\n", ep->usb_ep.name); -+ return; -+ } -+ -+ if (ep->dir != USB_DIR_OUT) { -+ /* This probably should not be happening */ -+ dev_err(udc->dev, "%s: CTRL dir IN\n", ep->usb_ep.name); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_OUT_DMA_DATA_DONE) { -+ status &= ~IPROC_USBD_EP_STAT_OUT_DMA_DATA_DONE; -+ iproc_udc_req_xfer_process(ep); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_OUT_DMA_SETUP_DONE) { -+ status &= ~IPROC_USBD_EP_STAT_OUT_DMA_SETUP_DONE; -+ iproc_ep_out_setup_isr(ep); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL) { -+ /** @todo Verify under what situations this can happen. Should be when chain has emptied but last desc not reached */ -+ /** @todo status for desc updates */ -+ -+ status &= ~IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL; -+ dev_err(udc->dev, "%s: DMA BUF NOT AVAIL\n", ep->usb_ep.name); -+ iproc_udc_req_xfer_process(ep); -+ } -+ -+ if (status & IPROC_USBD_EP_STAT_DMA_ERROR) { -+ status &= ~IPROC_USBD_EP_STAT_DMA_ERROR; -+ dev_err(udc->dev, "%s: DMA ERROR\n", ep->usb_ep.name); -+ /** @todo merge XferError and XferProcess?? */ -+ iproc_udc_req_xfer_error(ep, -EIO); -+ } -+ -+ if (status) { -+ dev_err(udc->dev, "%s: unknown status=0x%x\n", ep->usb_ep.name, status); -+ } -+} -+ -+irqreturn_t xgs_iproc_udc_isr(int irq, void *context) -+{ -+ struct iproc_udc *udc = NULL; -+ ulong flags; -+ uint stat, epin_stat, epout_stat; -+ int idx; -+ -+ udc = (struct iproc_udc *)context; -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ if (!udc || !udc->gadget_driver) { -+ dev_err(udc->dev, "Invalid context or no driver registered: irq dev=0x%x\n", iproc_usbd_irq_active(udc->usbd_regs)); -+ -+ iproc_usbd_irq_clear(udc->usbd_regs, IPROC_USBD_IRQ_ALL); -+ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_IN, ~0); -+ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_OUT, ~0); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ return IRQ_HANDLED; -+ } -+ -+ stat = iproc_usbd_irq_active(udc->usbd_regs); -+ epin_stat = iproc_usbd_ep_irq_list_active(udc->usbd_regs, USB_DIR_IN); -+ epout_stat = iproc_usbd_ep_irq_list_active(udc->usbd_regs, USB_DIR_OUT); -+ -+ if (!(stat || epin_stat || epout_stat)) { -+ return IRQ_NONE; -+ } -+ -+ iproc_usbd_irq_clear(udc->usbd_regs, stat); -+ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_IN, epin_stat); -+ iproc_usbd_ep_irq_list_clear(udc->usbd_regs, USB_DIR_OUT, epout_stat); -+ -+ /* -+ * Handle the SET_CFG and SET_INTF interrupts after the endpoint and other device interrupts. -+ * There can be some race conditions where we have an endpoint 0 interrupt pending for the -+ * completion of a previous endpoint 0 transfer (e.g. a GET config) when a SETUP arrives -+ * corresponding to the SET_CFG and SET_INTF. Need to complete the processing of the previous -+ * transfer before handling the next one, idx.e. the SET_CFG or SET_INTF. -+ */ -+ if (stat & IPROC_USBD_IRQ_BUS_RESET) { -+ printk(KERN_INFO "BUS reset\n"); -+ } -+ if (stat & IPROC_USBD_IRQ_BUS_SUSPEND) { -+ dev_dbg(udc->dev, "BUS suspend\n"); -+ } -+ if (stat & IPROC_USBD_IRQ_BUS_IDLE) { -+ dev_dbg(udc->dev, "BUS idle\n"); -+ iproc_udc_ops_disconnect(udc); -+ } -+ if (stat & IPROC_USBD_IRQ_SPEED_ENUM_DONE) { -+ dev_dbg(udc->dev, "BUS speed enum done\n"); -+ iproc_speed_isr(udc); -+ } -+ -+ /* endpoint interrupts handler */ -+ for (idx = 0; idx < IPROC_UDC_EP_CNT; idx++) { -+ if (epin_stat & (1 << idx)) { -+ iproc_ep_in_isr(&udc->ep[idx]); -+ } -+ if (epout_stat & (1 << idx)) { -+ iproc_ep_out_isr(&udc->ep[idx]); -+ } -+ } -+ -+ /* SET_CFG and SET_INTF interrupts handler */ -+ if (stat & IPROC_USBD_IRQ_SET_CFG) { -+ iproc_cfg_isr(udc); -+ } -+ if (stat & IPROC_USBD_IRQ_SET_INTF) { -+ iproc_inf_isr(udc); -+ } -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return IRQ_HANDLED; -+} -+ -+/*************************************************************************** -+* Endpoint request operations -+***************************************************************************/ -+static void iproc_udc_req_queue_flush(struct iproc_ep *ep, int status) -+{ -+ struct iproc_udc *udc = ep->udc; -+ struct iproc_ep_req *req; -+ -+ ep->stopped = 1; -+ iproc_usbd_ep_ops_finish(udc->usbd_regs, ep->num); -+ -+ while (!list_empty(&ep->list_queue)) { -+ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); -+ iproc_udc_req_xfer_done(ep, req, status); -+ } -+ ep->dma.usb_req = NULL; -+} -+ -+ -+static void iproc_udc_req_xfer_add(struct iproc_ep *ep, struct iproc_ep_req *req) -+{ -+ struct iproc_udc *udc = ep->udc; -+ list_add_tail(&req->list_node, &ep->list_queue); -+ -+ /** @todo Is this necessary?? Stopped happens as a result of a halt, complete(), dequeue(), nuke(). -+ * nuke() is called when ep disabled, during setup processing, and by udc_queisce(). The latter is -+ * called during vbus state change (cable insert/remove), USB reset interrupt, and gadget deregister. -+ */ -+ if (ep->stopped) { -+ return; -+ } -+ -+ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC) && ep->dma.usb_req && (ep->dma.frame_num == FRAME_NUM_INVALID)) { -+ /* -+ * Gadget has a request already queued, but still have not received an IN token from the host -+ * and the interval window is not aligned. Queued packet is now very stale, so remove it. -+ */ -+ -+ iproc_dma_data_finish(ep); -+ /** @todo Move set of ep->dma.usb_req to iproc_dma_data_init() and iproc_dma_data_finish() routines. */ -+ ep->dma.usb_req = NULL; -+ iproc_udc_req_xfer_done(ep, list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node), -EREMOTEIO); -+ } -+ -+ /** @todo Current transfer is always the queue head. Do we need a separate pointer? Maybe just a pointer to usb_request -+ * need to know if the queue head has already been loaded. Maybe that's the point of the "stopped". -+ */ -+ if (!ep->dma.usb_req) { -+ if ((ep->dir == USB_DIR_IN) && (ep->type == USB_ENDPOINT_XFER_ISOC) && -+ (ep->dma.frame_num == FRAME_NUM_INVALID)) { -+ /* -+ * Delay any ISOC IN DMA operations until it is known what frame number the host -+ * is going to start transfers with. Normally might just return requests until -+ * this event occurs. However, the zero gadget does not submit requests based on -+ * its own timer or similar, so if the request is returned right away things are -+ * going to thrash, as another request will be immediately submitted. -+ */ -+ ep->dma.usb_req = &(list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node))->usb_req; -+ iproc_dma_data_init(ep); -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); -+ iproc_usbd_ep_irq_en(udc->usbd_regs, ep->num, ep->dir); -+ } else { -+ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); -+ ep->dma.usb_req = &req->usb_req; -+ iproc_dma_data_init(ep); -+ iproc_dma_data_add_ready(ep); -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); -+ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, ep->dir); -+ -+ /* needed for gadget commands to complete correctly - possible locking issue */ -+ mdelay(3); -+ } -+ } -+} -+ -+static void iproc_udc_req_xfer_done(struct iproc_ep *ep, struct iproc_ep_req *req, int status) -+{ -+ struct iproc_udc *udc = ep->udc; -+ uint stopped; -+ -+ list_del_init(&req->list_node); -+ -+ if (req->usb_req.status == -EINPROGRESS) { -+ req->usb_req.status = status; -+ } -+ -+ if (req->dma_aligned) { -+ req->dma_aligned = 0; -+ } else if (req->dma_mapped) { -+ /* -+ * A physical address was not provided for the DMA buffer. Release any resources -+ * that were requested by the driver. -+ */ -+ dma_unmap_single(udc->gadget.dev.parent, req->usb_req.dma, req->usb_req.length, -+ (ep->dir == USB_DIR_IN ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); -+ -+ req->dma_mapped = 0; -+ req->usb_req.dma = DMA_ADDR_INVALID; -+ } -+ -+ /* -+ * Disable DMA operations during completion callback. The callback may cause requests to be -+ * added to the queue, but we don't want to change the state of the queue head. -+ */ -+ stopped = ep->stopped; -+ ep->stopped = 1; -+ spin_unlock(&udc->lock); -+ req->usb_req.complete(&ep->usb_ep, &req->usb_req); -+ spin_lock(&udc->lock); -+ ep->stopped = stopped; -+} -+ -+static void iproc_udc_req_xfer_error(struct iproc_ep *ep, int status) -+{ -+ struct iproc_udc *udc = ep->udc; -+ -+ if (!ep->dma.usb_req) { -+ dev_err(udc->dev, "%s: No request being transferred\n", ep->usb_ep.name); -+ return; -+ } -+ -+ /** @todo abort current DMA, start next transfer if there is one. */ -+ ep->dma.usb_req->status = status; -+ iproc_udc_req_xfer_process(ep); -+} -+ -+static void iproc_udc_req_xfer_process(struct iproc_ep *ep) -+{ -+ struct iproc_udc *udc = ep->udc; -+ struct iproc_ep_req *req; -+ -+ /** @todo Current transfer is always the queue head. Do we need a separate pointer? Maybe just a pointer to usb_request */ -+ if (!ep->dma.usb_req) { -+ dev_err(udc->dev, "%s: No request being transferred\n", ep->usb_ep.name); -+ return; -+ } -+ -+ iproc_usbd_ep_dma_dis(udc->usbd_regs, ep->num, ep->dir); -+ iproc_dma_data_rm_done(ep); -+ -+ if (ep->dma.usb_req->status != -EINPROGRESS) { -+ /* -+ * Current transfer stage has finished. This may or may not be with error. -+ * Complete the transfer as needed before starting the next one, if any. -+ */ -+ iproc_dma_data_finish(ep); -+ -+ if ((ep->type == USB_ENDPOINT_XFER_CONTROL) && (ep->dir == USB_DIR_IN) && (ep->dma.usb_req->status == ENOERROR)) { -+ /* -+ * For the status phase of control IN transfers, the hardware requires that an OUT DMA transfer -+ * actually takes place. This should be just an OUT ZLP, and we will re-use the IN buffer that -+ * just completed transfer for this purpose. There should be no harm in doing this, even if the -+ * OUT status is more than a ZLP. -+ */ -+ ep->dir = USB_DIR_OUT; -+ iproc_dma_data_init(ep); -+ } else { -+ /* -+ * All transfer stages have completed. Return the request to the gadget driver, and then -+ * setup for the next transfer. -+ */ -+ iproc_udc_req_xfer_done(ep, list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node), ENOERROR); -+ -+ if (ep->type == USB_ENDPOINT_XFER_CONTROL) { -+ iproc_ep_setup_init(ep, ENOERROR); -+ } -+ -+ if (list_empty(&ep->list_queue)) { -+ /** @todo Probably should more closely bind this to iproc_dma_data_finish. */ -+ ep->dma.usb_req = NULL; -+ } else { -+ req = list_first_entry(&ep->list_queue, struct iproc_ep_req, list_node); -+ ep->dma.usb_req = &req->usb_req; -+ iproc_dma_data_init(ep); -+ } -+ } -+ } -+ -+ if (ep->dma.usb_req != NULL) { -+ iproc_dma_data_add_ready(ep); -+ iproc_usbd_ep_dma_en(udc->usbd_regs, ep->num, ep->dir); -+ iproc_usbd_ep_nak_clear(udc->usbd_regs, ep->num, ep->dir); -+ } -+} -+ -+ -+/*************************************************************************** -+ * Linux proc file system functions -+ ***************************************************************************/ -+#ifdef CONFIG_USB_GADGET_DEBUG_FILES -+#include -+ -+static const char udc_proc_file_name[] = "driver/" XGS_IPROC_UDC_NAME; -+ -+static int proc_file_show(struct seq_file *s, void *_) -+{ -+ return(0); -+} -+ -+static int proc_file_open(struct inode *inode, struct file *file) -+{ -+ return(single_open(file, proc_file_show, NULL)); -+} -+ -+static struct file_operations udc_proc_file_ops = -+{ -+ .open = proc_file_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static void xgs_iproc_udc_proc_create(void) -+{ -+ struct proc_dir_entry *pde; -+ -+ pde = create_proc_entry (udc_proc_file_name, 0, NULL); -+ if (pde) { -+ pde->proc_fops = &udc_proc_file_ops; -+ } -+} -+ -+static void xgs_iproc_udc_proc_remove(void) -+{ -+ remove_proc_entry(udc_proc_file_name, NULL); -+} -+ -+#else -+ -+static void xgs_iproc_udc_proc_create(void) {} -+static void xgs_iproc_udc_proc_remove(void) {} -+ -+#endif -+ -+static const struct of_device_id xgs_iproc_udc_ids[] = { -+ { .compatible = "brcm,usbd,hx4", }, -+ { .compatible = "brcm,usbd,kt2", }, -+ { .compatible = "brcm,usbd,gh", }, -+ { .compatible = "brcm,usbd,sb2", }, -+ { .compatible = "brcm,usbd,hr3", }, -+ { .compatible = "brcm,usbd,gh2", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, xgs_iproc_udc_ids); -+ -+/**************************************************************************** -+ ***************************************************************************/ -+static int xgs_iproc_udc_probe(struct platform_device *pdev) -+{ -+ int ret = ENOERROR; -+ struct device *dev = &pdev->dev; -+ struct device_node *dn = dev->of_node; -+ const struct of_device_id *match; -+ struct iproc_udc *udc = NULL; -+ struct usb_phy *phy; -+ int irq; -+ -+ phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); -+ if (IS_ERR(phy)) { -+ dev_err(dev, "unable to find transceiver\n"); -+ return PTR_ERR(phy); -+ } -+ -+ if (phy->flags != IPROC_USB_MODE_DEVICE) -+ return -ENODEV; -+ -+ match = of_match_device(xgs_iproc_udc_ids, dev); -+ if (!match) { -+ dev_err(dev, "failed to find USBD in DT\n"); -+ return -ENODEV; -+ } -+ -+ irq = (uint)irq_of_parse_and_map(dn, 0); -+ -+ udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); -+ if (!udc) { -+ dev_err(dev, "devm_kzalloc() failed\n" ); -+ ret = -ENOMEM; -+ goto err1; -+ } -+ platform_set_drvdata(pdev, udc); -+ -+ udc->dev = dev; -+ spin_lock_init(&udc->lock); -+ -+ udc->usbd_regs = (struct iproc_usbd_regs *)of_iomap(dn, 0); -+ if (!udc->usbd_regs) { -+ dev_err(dev, "unable to iomap USB2D base address\n"); -+ ret = -ENXIO; -+ goto err1; -+ } -+ -+ ret = usb_phy_init(phy); -+ if (ret < 0) { -+ dev_err(dev, "initial usb transceiver failed.\n"); -+ goto err1; -+ } -+ -+ ret = iproc_platform_dma_alloc(pdev, udc); -+ if (ret < 0) { -+ dev_err(dev, "iproc_platform_dma_alloc() failed\n"); -+ goto err1; -+ } -+ -+ /* gadget init */ -+ udc->gadget.name = XGS_IPROC_UDC_NAME; -+ udc->gadget.speed = USB_SPEED_UNKNOWN; -+ udc->gadget.max_speed = USB_SPEED_HIGH; -+ udc->gadget.ops = &xgs_iproc_udc_ops; -+ -+ iproc_udc_ops_init(udc); -+ -+ iproc_usbd_irq_dis(udc->usbd_regs, IPROC_USBD_IRQ_ALL); -+ iproc_usbd_irq_clear(udc->usbd_regs, IPROC_USBD_IRQ_ALL); -+ -+ ret = devm_request_irq(dev, irq, xgs_iproc_udc_isr, 0, -+ XGS_IPROC_UDC_NAME, (void *)udc); -+ if (ret < 0) { -+ dev_err(dev, "error requesting IRQ #%d\n", irq); -+ goto err2; -+ } -+ -+ ret = usb_add_gadget_udc(dev, &udc->gadget); -+ if (ret < 0) { -+ dev_err(dev, "usb_add_gadget_udc() failed\n"); -+ goto err3; -+ } -+ -+ xgs_iproc_udc_proc_create(); -+ -+ return ENOERROR; -+ -+ -+err3: -+ devm_free_irq(dev, irq, udc); -+err2: -+ iproc_platform_dma_free(pdev, udc); -+err1: -+ if (udc->usbd_regs) { -+ iounmap(udc->usbd_regs); -+ udc->usbd_regs = NULL; -+ } -+ if (udc) { -+ kfree(udc); -+ } -+ -+ return ret; -+} -+ -+static int xgs_iproc_udc_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct iproc_udc *udc = platform_get_drvdata(pdev); -+ struct device_node *dn = pdev->dev.of_node; -+ int irq = (uint)irq_of_parse_and_map(dn, 0); -+ -+ if (udc) { -+ xgs_iproc_udc_proc_remove(); -+ -+ usb_del_gadget_udc(&udc->gadget); -+ iproc_udc_ops_finish(udc); -+ -+ platform_set_drvdata(pdev, NULL); -+ iproc_platform_dma_free(pdev, udc); -+ devm_free_irq(dev, irq, udc); -+ -+ if (udc->usbd_regs) { -+ iounmap(udc->usbd_regs); -+ udc->usbd_regs = NULL; -+ } -+ -+ kfree(udc); -+ } -+ -+ return ENOERROR; -+} -+ -+/* -+ * Generic platform device driver definition. -+ */ -+static struct platform_driver xgs_iproc_udc_driver = -+{ -+ .probe = xgs_iproc_udc_probe, -+ .remove = xgs_iproc_udc_remove, -+ .driver = { -+ .name = XGS_IPROC_UDC_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(xgs_iproc_udc_ids), -+ }, -+}; -+ -+module_platform_driver(xgs_iproc_udc_driver); -+ -+MODULE_DESCRIPTION("Broadcom USB Device Controller(UDC) driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.0.0"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_iproc_udc.h b/drivers/usb/gadget/udc/xgs_iproc_udc.h ---- a/drivers/usb/gadget/udc/xgs_iproc_udc.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/usb/gadget/udc/xgs_iproc_udc.h 2017-11-09 17:54:01.737429000 +0800 -@@ -0,0 +1,158 @@ -+/***************************************************************************** -+* Copyright 2006 - 2010 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+#ifndef _XGS_IPROC_UDC_H_ -+#define _XGS_IPROC_UDC_H_ -+ -+#include -+#include "xgs_usbd_regs.h" -+ -+#define IPROC_UDC_EP_CNT 7 -+#define IPROC_UDC_CTRL_MAX_PKG_SIZE 64 -+#define IPROC_UDC_EP_MAX_PKG_SIZE 512 -+ -+/* -+ * Some unsigned number trickery for indexing into DMA descriptor chain. If the -+ * decriptor count is some power of 2, then we can use the mask to extract -+ * an index and not worry about wrap around as the unsigned variables are -+ * incremented. E.g. in following, IDX(0), IDX(4), IDX(8), ..., IDX(0xffffc) -+ * all produce the same result, i.e. 0. -+ */ -+#define IPROC_EP_DMA_DESC_CNT 1 -+#define IPROC_EP_DMA_DESC_IDX_MASK (IPROC_EP_DMA_DESC_CNT - 1) -+#define IPROC_EP_DMA_DESC_IDX(_idx) ((_idx) & IPROC_EP_DMA_DESC_IDX_MASK) -+ -+/* Some DWC UDC DMA descriptor layout definitions. See datasheet for details. */ -+ -+struct iproc_udc_dma_setup { -+ unsigned int status; -+ unsigned int reserved; -+ unsigned int data1; -+ unsigned int data2; -+}; -+ -+struct iproc_udc_dma_desc { -+ unsigned int status; -+ unsigned int reserved; -+ unsigned int buf_addr; -+ unsigned int next_addr; -+}; -+ -+/* -+ * Common DMA descriptor layout used for all endpoints. Only control endpoints -+ * need the setup descriptor, but in order to simply things it is defined for -+ * all. It may be possible to omit this altogether, and just use one of data -+ * descriptors for setup instead. The control transfer protocol should allow -+ * this to be done. -+ */ -+struct iproc_ep_dma { -+ struct iproc_udc_dma_setup setup; -+ struct iproc_udc_dma_desc desc[IPROC_EP_DMA_DESC_CNT]; -+}; -+ -+/* Structure used for DMA descriptor allocation. Not really necessary but convenient. */ -+ -+struct iproc_udc_dma { -+ struct iproc_ep_dma ep[IPROC_UDC_EP_CNT]; -+}; -+ -+/* -+ * Structure used to hold endpoint specific information. There's one of these for -+ * each endpoint. -+ * -+ * The Rx/Tx FIFO sizes are used for RAM allocation purposes. Each transfer -+ * direction has its own RAM that is used for all the FIFOs in that direction. -+ * The RAM gets segmented (allocated) as each endpoint gets enabled. This dynamic -+ * allocation FIFO sizes gives flexibility, and does not require that an -+ * endpoint's size be fixed at run-time or during compilation. If there's not -+ * enough FIFO RAM as required by a gadget's endpoint definitions, then an -+ * error will occur for the enabling of any endpoints after the FIFO RAM has -+ * become exhausted. -+ * -+ * The DMA virtual address is used for all descriptor operations. The DMA -+ * physical address is for convenience (setting hardware registers, obtaining -+ * addresses for descriptor chaining, etc.). The DMA descriptors are not -+ * allocated on a per-endpoint basis. These are just pointers into the -+ * large block that was allocated for all endpoints. -+ */ -+struct iproc_ep { -+ struct usb_ep usb_ep; /* usb_gadget.h */ -+ const struct usb_endpoint_descriptor *desc; /* usb/ch9.h */ -+ struct list_head list_queue; /* active BCM_UDC_EP_REQ's for the endpoint */ -+ struct iproc_udc *udc; /* endpoint owner (UDC controller) */ -+ unsigned int num; -+ unsigned int dir; /* USB_DIR_xxx (direction) */ -+ unsigned int type; /* USB_ENDPOINT_XFER_xxx */ -+ unsigned int beq_addr; /* dirn | type */ -+ unsigned int stopped : 1; -+ struct { -+ struct iproc_ep_dma *vir_addr; -+ struct iproc_ep_dma *phy_addr; -+ struct usb_request *usb_req; /* Current request being DMA'd */ -+ -+ /** @todo Some of the below are duplicates of usb_request elements. Use usb_request instead. */ -+ unsigned int max_buf_len; /* Max buffer length to use with a descriptor */ -+ unsigned int done_len; /* Length of request DMA'd so far */ -+ unsigned int todo_len; /* Length of request left to DMA */ -+ unsigned int add_idx; /* descriptor chain index */ -+ unsigned int rm_idx; /* descriptor chain index */ -+ unsigned int buf_addr; /* Location in request to DMA */ -+ unsigned int frame_num; /* Frame number for ISOC transfers */ -+ unsigned int frame_incr; /* Frame number increment (period) */ -+ unsigned int status; -+ unsigned int done; /* DMA and USB transfer completion indication (IN_DMA_DONE and IN_XFER_DONE) */ -+ void *align_buff; /* Aligned buffer. Only used if usb_req buffer not aligned properly. */ -+ dma_addr_t align_addr; /* Aligned buffer physical address */ -+ unsigned int align_len; /* Aligned buffer length */ -+ } dma; -+}; -+ -+/* -+ * Structure used to hold controller information. There should be one of these -+ * for each controller. Most likely there's only one. -+ * -+ * The Rx/Tx FIFO space are used for RAM allocation purposes. These track how -+ * much RAM is available for use as a FIFO. When an endpoint is enabled, these -+ * are check to see if there's enough RAM for a FIFO of the desired length as -+ * implied by the max packet size. -+ */ -+struct iproc_udc { -+ struct usb_gadget gadget; /* usb_gadget.h */ -+ struct usb_gadget_driver *gadget_driver; /* usb_gadget.h */ -+ struct completion *dev_release; /* Used for coordination during device removal */ -+ spinlock_t lock; -+ struct device *dev; -+ unsigned int irq_num; -+ struct iproc_ep ep[IPROC_UDC_EP_CNT]; -+ struct iproc_usbd_regs *usbd_regs; -+ struct { -+ struct iproc_udc_dma *vir_addr; -+ struct iproc_udc_dma *phy_addr; -+ } dma; -+ unsigned int vbus_active : 1; /* Indicates if VBUS is present */ -+ unsigned int pullup_on : 1; /* Indicates if pull up is on */ -+}; -+ -+/* -+ * Structure used to hold an endpoint transfer request. Can be any number of -+ * these for an endpoint. -+ */ -+struct iproc_ep_req { -+ struct usb_request usb_req; /* usb_gadget.h */ -+ struct list_head list_node; /* For linking in the BCM_UDC_EP request queue */ -+ dma_addr_t orig_dma_addr; /* Original buffer DMA address (physical). */ -+ unsigned dma_mapped : 1; /* Indicates if address mapping req'd. See usb_gadget.h */ -+ unsigned dma_aligned : 1; /* Indicates if buffer duplication done for alignment. */ -+}; -+ -+#endif /* _XGS_IPROC_UDC_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/gadget/udc/xgs_usbd_regs.h b/drivers/usb/gadget/udc/xgs_usbd_regs.h ---- a/drivers/usb/gadget/udc/xgs_usbd_regs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/usb/gadget/udc/xgs_usbd_regs.h 2017-11-09 17:54:01.738446000 +0800 -@@ -0,0 +1,995 @@ -+/***************************************************************************** -+* Copyright 2003 - 2009 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+#ifndef _USBD_REGS_H_ -+#define _USBD_REGS_H_ -+ -+#include -+ -+#define IPROC_USBD_MULTI_RX_FIFO 0 -+ -+#define IPROC_USBD_EP_CFG_CNT 10 -+#define IPROC_USBD_REG_EP_CNT 16 -+ -+#define IPROC_USBD_SPEED_UNKNOWN 0 -+#define IPROC_USBD_SPEED_LOW 1 -+#define IPROC_USBD_SPEED_FULL 2 -+#define IPROC_USBD_SPEED_HIGH 3 -+ -+#define IPROC_USBD_EP_DIR_IN 0x80 -+#define IPROC_USBD_EP_DIR_OUT 0x00 -+ -+#define IPROC_USBD_EP_TYPE_CTRL 0 -+#define IPROC_USBD_EP_TYPE_ISOC 1 -+#define IPROC_USBD_EP_TYPE_BULK 2 -+#define IPROC_USBD_EP_TYPE_INTR 3 -+ -+#define IPROC_USBD_IRQ_REMOTEWAKEUP_DELTA IPROC_USBD_REG_INTR_REMOTE_WAKEUP_DELTA -+#define IPROC_USBD_IRQ_SPEED_ENUM_DONE IPROC_USBD_REG_INTR_SPD_ENUM_DONE -+#define IPROC_USBD_IRQ_SOF_DETECTED IPROC_USBD_REG_INTR_SOF_RX -+#define IPROC_USBD_IRQ_BUS_SUSPEND IPROC_USBD_REG_INTR_BUS_SUSPEND -+#define IPROC_USBD_IRQ_BUS_RESET IPROC_USBD_REG_INTR_BUS_RESET -+#define IPROC_USBD_IRQ_BUS_IDLE IPROC_USBD_REG_INTR_BUS_IDLE -+#define IPROC_USBD_IRQ_SET_INTF IPROC_USBD_REG_INTR_SET_INTF_RX -+#define IPROC_USBD_IRQ_SET_CFG IPROC_USBD_REG_INTR_SET_CFG_RX -+#define IPROC_USBD_IRQ_ALL (IPROC_USBD_IRQ_REMOTEWAKEUP_DELTA | \ -+ IPROC_USBD_IRQ_SPEED_ENUM_DONE | \ -+ IPROC_USBD_IRQ_SOF_DETECTED | \ -+ IPROC_USBD_IRQ_BUS_SUSPEND | \ -+ IPROC_USBD_IRQ_BUS_RESET | \ -+ IPROC_USBD_IRQ_BUS_IDLE | \ -+ IPROC_USBD_IRQ_SET_INTF | \ -+ IPROC_USBD_IRQ_SET_CFG) -+ -+#define IPROC_USBD_EP_STAT_DMA_ERROR IPROC_USBD_REG_EP_FIFO_STATUS_AHB_BUS_ERROR -+#define IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL IPROC_USBD_REG_EP_FIFO_STATUS_DMA_BUF_NOT_AVAIL -+#define IPROC_USBD_EP_STAT_IN_TOKEN_RX IPROC_USBD_REG_EP_FIFO_STATUS_IN_TOKEN_RX -+#define IPROC_USBD_EP_STAT_IN_DMA_DONE IPROC_USBD_REG_EP_FIFO_STATUS_IN_DMA_DONE -+#define IPROC_USBD_EP_STAT_IN_FIFO_EMPTY IPROC_USBD_REG_EP_FIFO_STATUS_IN_FIFO_EMPTY -+#define IPROC_USBD_EP_STAT_IN_XFER_DONE IPROC_USBD_REG_EP_FIFO_STATUS_IN_XFER_DONE -+#define IPROC_USBD_EP_STAT_OUT_DMA_DATA_DONE IPROC_USBD_REG_EP_FIFO_STATUS_OUT_DMA_DATA_DONE -+#define IPROC_USBD_EP_STAT_OUT_DMA_SETUP_DONE IPROC_USBD_REG_EP_FIFO_STATUS_OUT_DMA_SETUP_DONE -+#define IPROC_USBD_EP_STAT_ALL (IPROC_USBD_EP_STAT_DMA_ERROR | \ -+ IPROC_USBD_EP_STAT_DMA_BUF_UNAVAIL | \ -+ IPROC_USBD_EP_STAT_IN_TOKEN_RX | \ -+ IPROC_USBD_EP_STAT_IN_DMA_DONE | \ -+ IPROC_USBD_EP_STAT_IN_XFER_DONE | \ -+ IPROC_USBD_EP_STAT_OUT_DMA_DATA_DONE | \ -+ IPROC_USBD_EP_STAT_OUT_DMA_SETUP_DONE) -+ -+ -+#define REG8_RSVD(start, end) uint8_t rsvd_##start[(end - start) / sizeof(uint8_t)] -+#define REG16_RSVD(start, end) uint16_t rsvd_##start[(end - start) / sizeof(uint16_t)] -+#define REG32_RSVD(start, end) uint rsvd_##start[(end - start) / sizeof(uint)] -+ -+struct iproc_usbd_ep_fifo_regs { -+ uint ctrl; -+ uint status; -+ uint size1; -+ uint size2; /* Buf Size OUT/Max PKT SIZE */ -+ uint buf_addr; -+ uint desc_addr; -+ REG32_RSVD(0x18, 0x20); -+}; -+ -+struct iproc_usbd_regs { -+ struct iproc_usbd_ep_fifo_regs ep_fifo_in[IPROC_USBD_REG_EP_CNT]; -+ struct iproc_usbd_ep_fifo_regs ep_fifo_out[IPROC_USBD_REG_EP_CNT]; -+ uint dev_cfg; -+ uint dev_ctrl; -+ uint dev_status; -+ uint dev_irq_status; -+ uint dev_irq_mask; -+ uint ep_irq_status; -+ uint ep_irq_mask; -+ uint test_mode; -+ uint rel_num; -+ REG32_RSVD(0x424, 0x500); -+ REG32_RSVD(0x500, 0x504); -+ uint ep_cfg[IPROC_USBD_REG_EP_CNT]; -+ REG32_RSVD(0x544, 0x800); -+ uint rx_fifo[256]; -+ uint tx_fifo[256]; -+ uint strap; -+}; -+ -+ -+struct iproc_usbd_idm_regs { -+ REG32_RSVD(0x000, 0x408); -+ uint io_ctrl; -+ REG32_RSVD(0x40C, 0x500); -+ uint io_status; -+ REG32_RSVD(0x504, 0x800); -+ uint reset_ctrl; -+ uint reset_status; -+ REG32_RSVD(0x808, 0xA00); -+ uint irq_status; -+}; -+ -+/* -+ * The endpoint type field in the FIFO control register has the same enumeration -+ * as the USB protocol. Not going to define it here. -+ */ -+#define IPROC_USBD_REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE (1 << 12) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_OUT_CLOSE_DESC (1 << 11) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_IN_SEND_NULL (1 << 10) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_OUT_DMA_ENABLE (1 << 9) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_NAK_CLEAR (1 << 8) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET (1 << 7) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_NAK_IN_PROGRESS (1 << 6) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_TYPE_SHIFT 4 -+#define IPROC_USBD_REG_EP_FIFO_CTRL_TYPE_MASK (3 << IPROC_USBD_REG_EP_FIFO_CTRL_TYPE_SHIFT) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_IN_DMA_ENABLE (1 << 3) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_SNOOP_ENABLE (1 << 2) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE (1 << 1) -+#define IPROC_USBD_REG_EP_FIFO_CTRL_STALL_ENABLE (1 << 0) -+ -+#define IPROC_USBD_REG_EP_FIFO_STATUS_CLOSE_DESC_CLEAR (1 << 28) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_IN_XFER_DONE (1 << 27) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_STALL_SET_RX (1 << 26) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_STALL_CLEAR_RX (1 << 25) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_IN_FIFO_EMPTY (1 << 24) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_IN_DMA_DONE (1 << 10) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_AHB_BUS_ERROR (1 << 9) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY (1 << 8) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_DMA_BUF_NOT_AVAIL (1 << 7) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_IN_TOKEN_RX (1 << 6) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_OUT_DMA_SETUP_DONE (1 << 5) -+#define IPROC_USBD_REG_EP_FIFO_STATUS_OUT_DMA_DATA_DONE (1 << 4) -+ -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_ISOC_PID_SHIFT 16 -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_ISOC_PID_MASK (3 << IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_ISOC_PID_SHIFT) -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT 0 -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_IN_DEPTH_MASK (0xffff << IPROC_USBD_REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT) -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_SHIFT IPROC_USBD_REG_EP_FIFO_SIZE1_IN_DEPTH_SHIFT -+#define IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_MASK IPROC_USBD_REG_EP_FIFO_SIZE1_IN_DEPTH_MASK -+ -+#define IPROC_USBD_REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT 16 -+#define IPROC_USBD_REG_EP_FIFO_SIZE2_OUT_DEPTH_MASK (0xffff << IPROC_USBD_REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT) -+#define IPROC_USBD_REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT 0 -+#define IPROC_USBD_REG_EP_FIFO_SIZE2_PKT_MAX_MASK (0xffff << IPROC_USBD_REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT) -+ -+/* -+ * The endpoint type field in the config register has the same enumeration -+ * as the USB protocol. Not going to define it here. -+ */ -+#define IPROC_USBD_REG_EP_CFG_PKT_MAX_SHIFT 19 -+#define IPROC_USBD_REG_EP_CFG_PKT_MAX_MASK (0x7ff << IPROC_USBD_REG_EP_CFG_PKT_MAX_SHIFT) -+#define IPROC_USBD_REG_EP_CFG_ALT_NUM_SHIFT 15 -+#define IPROC_USBD_REG_EP_CFG_ALT_NUM_MASK (0xf << IPROC_USBD_REG_EP_CFG_ALT_NUM_SHIFT) -+#define IPROC_USBD_REG_EP_CFG_INTF_NUM_SHIFT 11 -+#define IPROC_USBD_REG_EP_CFG_INTF_NUM_MASK (0xf << IPROC_USBD_REG_EP_CFG_INTF_NUM_SHIFT) -+#define IPROC_USBD_REG_EP_CFG_CFG_NUM_SHIFT 7 -+#define IPROC_USBD_REG_EP_CFG_CFG_NUM_MASK (0xf << IPROC_USBD_REG_EP_CFG_CFG_NUM_SHIFT) -+#define IPROC_USBD_REG_EP_CFG_TYPE_SHIFT 5 -+#define IPROC_USBD_REG_EP_CFG_TYPE_MASK (0x3 << IPROC_USBD_REG_EP_CFG_TYPE_SHIFT) -+#define IPROC_USBD_REG_EP_CFG_DIRN_IN (1 << 4) -+#define IPROC_USBD_REG_EP_CFG_DIRN_OUT 0 -+#define IPROC_USBD_REG_EP_CFG_FIFO_NUM_SHIFT 0 -+#define IPROC_USBD_REG_EP_CFG_FIFO_NUM_MASK (0xf << IPROC_USBD_REG_EP_CFG_FIFO_NUM_SHIFT) -+ -+/* Endpoint Interrupt register definitions */ -+#define IPROC_USBD_REG_EP_INTR_OUT_SHIFT 16 -+#define IPROC_USBD_REG_EP_INTR_OUT_MASK (0xffff << IPROC_USBD_REG_EP_INTR_OUT_SHIFT) -+#define IPROC_USBD_REG_EP_INTR_IN_SHIFT 0 -+#define IPROC_USBD_REG_EP_INTR_IN_MASK (0xffff << IPROC_USBD_REG_EP_INTR_IN_SHIFT) -+ -+/* Device Controller register definitions */ -+#define IPROC_USBD_REG_CFG_ULPI_DDR_ENABLE (1 << 19) -+#define IPROC_USBD_REG_CFG_SET_DESCRIPTOR_ENABLE (1 << 18) -+#define IPROC_USBD_REG_CFG_CSR_PROGRAM_ENABLE (1 << 17) -+#define IPROC_USBD_REG_CFG_HALT_STALL_ENABLE (1 << 16) -+#define IPROC_USBD_REG_CFG_HS_TIMEOUT_CALIB_SHIFT 13 -+#define IPROC_USBD_REG_CFG_HS_TIMEOUT_CALIB_MASK (7 << IPROC_USBD_REG_CFG_HS_TIMEOUT_CALIB_SHIFT) -+#define IPROC_USBD_REG_CFG_FS_TIMEOUT_CALIB_SHIFT 10 -+#define IPROC_USBD_REG_CFG_FS_TIMEOUT_CALIB_MASK (7 << IPROC_USBD_REG_CFG_FS_TIMEOUT_CALIB_SHIFT) -+#define IPROC_USBD_REG_CFG_STATUS_1_ENABLE (1 << 8) -+#define IPROC_USBD_REG_CFG_STATUS_ENABLE (1 << 7) -+#define IPROC_USBD_REG_CFG_UTMI_BI_DIRN_ENABLE (1 << 6) -+#define IPROC_USBD_REG_CFG_UTMI_8BIT_ENABLE (1 << 5) -+#define IPROC_USBD_REG_CFG_SYNC_FRAME_ENABLE (1 << 4) -+#define IPROC_USBD_REG_CFG_SELF_PWR_ENABLE (1 << 3) -+#define IPROC_USBD_REG_CFG_REMOTE_WAKEUP_ENABLE (1 << 2) -+#define IPROC_USBD_REG_CFG_SPD_SHIFT 0 -+#define IPROC_USBD_REG_CFG_SPD_MASK (3 << IPROC_USBD_REG_CFG_SPD_SHIFT) -+#define IPROC_USBD_REG_CFG_SPD_HS (0 << IPROC_USBD_REG_CFG_SPD_SHIFT) -+#define IPROC_USBD_REG_CFG_SPD_FS (1 << IPROC_USBD_REG_CFG_SPD_SHIFT) -+#define IPROC_USBD_REG_CFG_SPD_LS (2 << IPROC_USBD_REG_CFG_SPD_SHIFT) -+#define IPROC_USBD_REG_CFG_SPD_FS_48MHZ (3 << IPROC_USBD_REG_CFG_SPD_SHIFT) -+ -+#define IPROC_USBD_REG_CTRL_DMA_OUT_THRESHOLD_LEN_SHIFT 24 -+#define IPROC_USBD_REG_CTRL_DMA_OUT_THRESHOLD_LEN_MASK (0xff << IPROC_USBD_REG_CTRL_DMA_OUT_THRESHOLD_LEN_SHIFT) -+#define IPROC_USBD_REG_CTRL_DMA_BURST_LEN_SHIFT 16 -+#define IPROC_USBD_REG_CTRL_DMA_BURST_LEN_MASK (0xff << IPROC_USBD_REG_CTRL_DMA_BURST_LEN_SHIFT) -+#define IPROC_USBD_REG_CTRL_OUT_FIFO_FLUSH_ENABLE (1 << 14) -+#define IPROC_USBD_REG_CTRL_CSR_DONE (1 << 13) -+#define IPROC_USBD_REG_CTRL_OUT_NAK_ALL_ENABLE (1 << 12) -+#define IPROC_USBD_REG_CTRL_DISCONNECT_ENABLE (1 << 10) -+#define IPROC_USBD_REG_CTRL_DMA_MODE_ENABLE (1 << 9) -+#define IPROC_USBD_REG_CTRL_DMA_BURST_ENABLE (1 << 8) -+#define IPROC_USBD_REG_CTRL_DMA_OUT_THRESHOLD_ENABLE (1 << 7) -+#define IPROC_USBD_REG_CTRL_DMA_BUFF_FILL_MODE_ENABLE (1 << 6) -+#define IPROC_USBD_REG_CTRL_ENDIAN_BIG_ENABLE (1 << 5) -+#define IPROC_USBD_REG_CTRL_DMA_DESC_UPDATE_ENABLE (1 << 4) -+#define IPROC_USBD_REG_CTRL_DMA_IN_ENABLE (1 << 3) /*TX DMA Enable */ -+#define IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE (1 << 2) /*RX DMA Enable */ -+#define IPROC_USBD_REG_CTRL_RESUME_SIGNAL_ENABLE (1 << 0) -+#define IPROC_USBD_REG_CTRL_LE_ENABLE 0 /*^BCM5892 */ -+ -+#define IPROC_USBD_REG_STAT_SOF_FRAME_NUM_SHIFT 18 -+#define IPROC_USBD_REG_STAT_SOF_FRAME_NUM_MASK (0x3ffff << IPROC_USBD_REG_STAT_SOF_FRAME_NUM_SHIFT) -+#define IPROC_USBD_REG_STAT_REMOTE_WAKEUP_ALLOWED (1 << 17) -+#define IPROC_USBD_REG_STAT_PHY_ERROR (1 << 16) -+#define IPROC_USBD_REG_STAT_OUT_FIFO_EMPTY (1 << 15) -+#define IPROC_USBD_REG_STAT_SPD_SHIFT 13 -+#define IPROC_USBD_REG_STAT_SPD_MASK (3 << IPROC_USBD_REG_STAT_SPD_SHIFT) -+#define IPROC_USBD_REG_STAT_SPD_HS (0 << IPROC_USBD_REG_STAT_SPD_SHIFT) -+#define IPROC_USBD_REG_STAT_SPD_FS (1 << IPROC_USBD_REG_STAT_SPD_SHIFT) -+#define IPROC_USBD_REG_STAT_SPD_LS (2 << IPROC_USBD_REG_STAT_SPD_SHIFT) -+#define IPROC_USBD_REG_STAT_SPD_FS_48MHZ (3 << IPROC_USBD_REG_STAT_SPD_SHIFT) -+#define IPROC_USBD_REG_STAT_BUS_SUSPENDED (1 << 12) -+#define IPROC_USBD_REG_STAT_ALT_NUM_SHIFT 8 -+#define IPROC_USBD_REG_STAT_ALT_NUM_MASK (0xf << IPROC_USBD_REG_STAT_ALT_NUM_SHIFT) -+#define IPROC_USBD_REG_STAT_INTF_NUM_SHIFT 4 -+#define IPROC_USBD_REG_STAT_INTF_NUM_MASK (0xf << IPROC_USBD_REG_STAT_INTF_NUM_SHIFT) -+#define IPROC_USBD_REG_STAT_CFG_NUM_SHIFT 0 -+#define IPROC_USBD_REG_STAT_CFG_NUM_MASK (0xf << IPROC_USBD_REG_STAT_CFG_NUM_SHIFT) -+ -+#define IPROC_USBD_REG_INTR_REMOTE_WAKEUP_DELTA (1 << 7) /*Remote Wakeup Delta*/ -+#define IPROC_USBD_REG_INTR_SPD_ENUM_DONE (1 << 6) /*ENUM Speed Completed*/ -+#define IPROC_USBD_REG_INTR_SOF_RX (1 << 5) /*SOF Token Detected */ -+#define IPROC_USBD_REG_INTR_BUS_SUSPEND (1 << 4) /*SUSPEND State Detected*/ -+#define IPROC_USBD_REG_INTR_BUS_RESET (1 << 3) /*RESET State Detected */ -+#define IPROC_USBD_REG_INTR_BUS_IDLE (1 << 2) /*IDLE State Detected*/ -+#define IPROC_USBD_REG_INTR_SET_INTF_RX (1 << 1) /*Received SET_INTERFACE CMD*/ -+#define IPROC_USBD_REG_INTR_SET_CFG_RX (1 << 0) /*Received SET_CONFIG CMD*/ -+ -+/* DMA Descriptor definitions */ -+#define IPROC_USBD_REG_DMA_STAT_BUF_SHIFT 30 -+#define IPROC_USBD_REG_DMA_STAT_BUF_HOST_READY (0 << IPROC_USBD_REG_DMA_STAT_BUF_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_BUF_DMA_BUSY (1 << IPROC_USBD_REG_DMA_STAT_BUF_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_BUF_DMA_DONE (2 << IPROC_USBD_REG_DMA_STAT_BUF_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_BUF_HOST_BUSY (3 << IPROC_USBD_REG_DMA_STAT_BUF_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_BUF_MASK (3 << IPROC_USBD_REG_DMA_STAT_BUF_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_RX_SHIFT 28 -+#define IPROC_USBD_REG_DMA_STAT_RX_SUCCESS (0 << IPROC_USBD_REG_DMA_STAT_RX_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_RX_ERR_DESC (1 << IPROC_USBD_REG_DMA_STAT_RX_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_RX_ERR_BUF (3 << IPROC_USBD_REG_DMA_STAT_RX_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_RX_MASK (3 << IPROC_USBD_REG_DMA_STAT_RX_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_CFG_NUM_SHIFT 24 -+#define IPROC_USBD_REG_DMA_STAT_CFG_NUM_MASK (0xf << IPROC_USBD_REG_DMA_STAT_CFG_NUM_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_INTF_NUM_SHIFT 20 -+#define IPROC_USBD_REG_DMA_STAT_INTF_NUM_MASK (0xf << IPROC_USBD_REG_DMA_STAT_INTF_NUM_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_ALT_NUM_SHIFT 16 -+#define IPROC_USBD_REG_DMA_STAT_ALT_NUM_MASK (0xf << IPROC_USBD_REG_DMA_STAT_ALT_NUM_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_LAST_DESC (1 << 27) -+#define IPROC_USBD_REG_DMA_STAT_FRAME_NUM_SHIFT 16 -+#define IPROC_USBD_REG_DMA_STAT_FRAME_NUM_MASK (0x7ff << IPROC_USBD_REG_DMA_STAT_FRAME_NUM_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_BYTE_CNT_SHIFT 0 -+#define IPROC_USBD_REG_DMA_STAT_ISO_PID_SHIFT 14 -+#define IPROC_USBD_REG_DMA_STAT_ISO_PID_MASK (0x3 << IPROC_USBD_REG_DMA_STAT_ISO_PID_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_ISO_BYTE_CNT_SHIFT IPROC_USBD_REG_DMA_STAT_BYTE_CNT_SHIFT -+#define IPROC_USBD_REG_DMA_STAT_ISO_BYTE_CNT_MASK (0x3fff << IPROC_USBD_REG_DMA_STAT_ISO_BYTE_CNT_SHIFT) -+#define IPROC_USBD_REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT IPROC_USBD_REG_DMA_STAT_BYTE_CNT_SHIFT -+#define IPROC_USBD_REG_DMA_STAT_NON_ISO_BYTE_CNT_MASK (0xffff << IPROC_USBD_REG_DMA_STAT_NON_ISO_BYTE_CNT_SHIFT) -+ -+/* USB2D IDM definitions */ -+#define IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE (1 << 0) -+#define IPROC_USB2D_IDM_REG_RESET_CTRL_RESET (1 << 0) -+ -+/* Inline Function Definitions */ -+static inline uint -+usbd_reg32_read(volatile uint *reg) -+{ -+ return (le32_to_cpu(*reg)); -+} -+ -+static inline void -+usbd_reg32_write(volatile uint *reg, uint value) -+{ -+ *reg = cpu_to_le32(value); -+} -+ -+static inline void -+usbd_reg32_bits_set(volatile uint *reg, uint bits) -+{ -+ uint tmp; -+ tmp = usbd_reg32_read(reg); -+ tmp |= bits; -+ usbd_reg32_write(reg, tmp); -+} -+ -+static inline void -+usbd_reg32_bits_clear(volatile uint *reg, uint bits) -+{ -+ uint tmp; -+ tmp = usbd_reg32_read(reg); -+ tmp &= ~bits; -+ usbd_reg32_write(reg, tmp); -+} -+ -+static inline void -+usbd_reg32_bits_modify(volatile uint *reg, uint mask, uint value) -+{ -+ uint tmp; -+ tmp = usbd_reg32_read(reg); -+ tmp &= ~mask; -+ tmp |= value; -+ usbd_reg32_write(reg, tmp); -+} -+ -+#define IPROC_USBD_READ(_r) usbd_reg32_read(&_r) -+#define IPROC_USBD_WRITE(_r, _v) usbd_reg32_write(&_r, _v) -+#define IPROC_USBD_BITS_SET(_r, _b) usbd_reg32_bits_set(&_r, _b) -+#define IPROC_USBD_BITS_CLEAR(_r, _b) usbd_reg32_bits_clear(&_r, _b) -+#define IPROC_USBD_BITS_MODIFY(_r, _m, _v) usbd_reg32_bits_modify(&_r, _m, _v) -+ -+/***************************************************************************** -+* @brief Connect / Disconnect to USB BUS -+*****************************************************************************/ -+static inline void iproc_usbd_bus_conn(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, IPROC_USBD_REG_CTRL_DISCONNECT_ENABLE); -+} -+ -+static inline void iproc_usbd_bus_disconn(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_DISCONNECT_ENABLE); -+} -+ -+/***************************************************************************** -+* @brief USB BUS suspend status -+* @return -+* true : BUS is in suspend state -+* false : BUS is not in suspend state -+*****************************************************************************/ -+static inline bool iproc_usbd_bus_suspend(struct iproc_usbd_regs *base) -+{ -+ return (IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_BUS_SUSPENDED) ? true : false; -+} -+ -+/***************************************************************************** -+* @brief Retrieve setting numbers from last Rx'd SET_CONFIGURATION or -+* SET_INTERFACE request -+* @return -+* Setting Number -+*****************************************************************************/ -+static inline uint iproc_usbd_alt_num(struct iproc_usbd_regs *base) -+{ -+ return ((IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_ALT_NUM_MASK) >> IPROC_USBD_REG_STAT_ALT_NUM_SHIFT); -+} -+ -+static inline uint iproc_usbd_cfg_num(struct iproc_usbd_regs *base) -+{ -+ return ((IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_CFG_NUM_MASK) >> IPROC_USBD_REG_STAT_CFG_NUM_SHIFT); -+} -+ -+static inline uint iproc_usbd_intf_num(struct iproc_usbd_regs *base) -+{ -+ return ((IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_INTF_NUM_MASK) >> IPROC_USBD_REG_STAT_INTF_NUM_SHIFT); -+} -+ -+ -+/***************************************************************************** -+* @brief Disable / Enable DMA operations at the device level (all endpoints) -+*****************************************************************************/ -+static inline void iproc_usbd_dma_dis(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, (IPROC_USBD_REG_CTRL_DMA_IN_ENABLE | IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE)); -+} -+ -+static inline void iproc_usbd_dma_en(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_ctrl, (IPROC_USBD_REG_CTRL_DMA_IN_ENABLE | IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE)); -+} -+ -+static inline bool iproc_usbd_dma_status(struct iproc_usbd_regs *base) -+{ -+ return (IPROC_USBD_READ(base->dev_ctrl) & IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE ? true : false); -+} -+ -+/***************************************************************************** -+* @brief Retrieve Frame number contained in last Rx'd SOF packet -+* @return -+* Frame Number in the following format. -+* bits[13:3] milli-second frame number -+* bits[2:0] micro-frame number -+* @note -+* For full and low speed connections, the microframe number will be zero. -+*****************************************************************************/ -+static inline uint iproc_usbd_last_rx_frame_num(struct iproc_usbd_regs *base) -+{ -+ return((IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_SOF_FRAME_NUM_MASK) >> IPROC_USBD_REG_STAT_SOF_FRAME_NUM_SHIFT); -+} -+ -+/***************************************************************************** -+* @brief Device level interrupt operations -+* @note -+* Use the IPROC_USBD_IRQ_xxx definitions with these routines. These -+* definitions are bit-wise, and allow operations on multiple interrupts -+* by OR'ing the definitions together. -+* DeviceIrqClear(), DeviceIrqDisable(), DeviceIrqEnable() use their mask -+* parameter to operate only on the interrupts set in the mask. E.g. -+* DeviceIrqEnable( DEVICE_IRQ_SET_INTF ); -+* DeviceIrqEnable( DEVICE_IRQ_SET_CFG ); -+* and -+* DeviceIrqEnable( DEVICE_IRQ_SET_INTF | DEVICE_IRQ_SET_CFG ); -+* are equivalent. -+* DeviceIrqMask() returns a mask of all the interrupts that are enabled. -+* DeviceIrqStatus() returns a mask of all the interrupts that have an active status. -+*****************************************************************************/ -+static inline uint iproc_usbd_irq_active(struct iproc_usbd_regs *base) -+{ -+ return(IPROC_USBD_READ(base->dev_irq_status)); -+} -+ -+static inline void iproc_usbd_irq_clear(struct iproc_usbd_regs *base, uint mask) -+{ -+ IPROC_USBD_WRITE(base->dev_irq_status, mask); -+} -+ -+static inline void iproc_usbd_irq_dis(struct iproc_usbd_regs *base, uint mask) -+{ -+ IPROC_USBD_BITS_SET(base->dev_irq_mask, mask); -+} -+ -+static inline void iproc_usbd_irq_en(struct iproc_usbd_regs *base, uint mask) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_irq_mask, mask); -+} -+static inline uint iproc_usbd_irq_mask(struct iproc_usbd_regs *base) -+{ -+ return((~IPROC_USBD_READ(base->dev_irq_mask)) & IPROC_USBD_IRQ_ALL); -+} -+ -+/***************************************************************************** -+* @brief Disable / Enable NAK responses for all OUT endpoints. -+*****************************************************************************/ -+static inline void iproc_usbd_nak_response_dis(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, IPROC_USBD_REG_CTRL_OUT_NAK_ALL_ENABLE); -+} -+ -+static inline void iproc_usbd_nak_response_en(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_OUT_NAK_ALL_ENABLE); -+} -+ -+/***************************************************************************** -+* @brief PHY error detected -+*****************************************************************************/ -+static inline bool iproc_usbd_phy_err_detect(struct iproc_usbd_regs *base) -+{ -+ return(IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_PHY_ERROR ? true : false); -+} -+ -+/***************************************************************************** -+* @brief Remote Wakeup operations. -+* DeviceRemoteWakeupEnable() and DeviceRemoteWakeupDisable() are used to -+* specify device if is going to attempt this. -+* DeviceRemoteWakeupAllowed() indicates if host has enabled this feature. -+* The associated DEVICE_IRQ_REMOTEWAKEUP_DELTA can be used to determine -+* changes to the status of this feature. -+* DeviceRemoteWakeupStart(); delayMsec(1); DeviceRemoteWakeupStop(); is -+* used for controlling the wakeup signalling. -+*****************************************************************************/ -+static inline bool iproc_usbd_wakeup_allow(struct iproc_usbd_regs *base) -+{ -+ return(IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_REMOTE_WAKEUP_ALLOWED ? true : false); -+} -+ -+static inline void iproc_usbd_wakeup_dis(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_cfg, IPROC_USBD_REG_CFG_REMOTE_WAKEUP_ENABLE); -+} -+ -+static inline void iproc_usbd_wakeup_en(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_REMOTE_WAKEUP_ENABLE); -+} -+ -+static inline void iproc_usbd_wakeup_start(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_RESUME_SIGNAL_ENABLE); -+} -+ -+static inline void iproc_usbd_wakeup_stop(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, IPROC_USBD_REG_CTRL_RESUME_SIGNAL_ENABLE); -+} -+ -+/***************************************************************************** -+* @brief Control whether or not device advertises itself as self-powered. -+*****************************************************************************/ -+static inline void iproc_usbd_self_pwr_dis(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_cfg, IPROC_USBD_REG_CFG_SELF_PWR_ENABLE); -+} -+ -+static inline void iproc_usbd_self_pwr_en(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_SELF_PWR_ENABLE); -+} -+ -+/***************************************************************************** -+* @brief Control whether or not device SET DESCRIPTOR support is enabled. -+* If disabled, STALL will be issued upon receipt of a SET DESCRIPTOR request. -+*****************************************************************************/ -+static inline void iproc_usbd_set_desc_dis(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_cfg, IPROC_USBD_REG_CFG_SET_DESCRIPTOR_ENABLE); -+} -+ -+static inline void iproc_usbd_set_desc_en(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_SET_DESCRIPTOR_ENABLE); -+} -+ -+/***************************************************************************** -+* @brief Device SET configuration or SET interface has completed. -+* If disabled, STALL will be issued upon receipt of a SET DESCRIPTOR request. -+*****************************************************************************/ -+static inline void iproc_usbd_setup_done(struct iproc_usbd_regs *base) -+{ -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_CSR_DONE); -+} -+ -+/***************************************************************************** -+* @brief Link speed routines. -+* Use the usbDevHw_DEVICE_SPEED_xxx definitions with these routines. These -+* DeviceSpeedRequested() indicates the desired link speed. -+* DeviceSpeedEnumerated() returns the speed negotiated with the host. -+* The associated DEVICE_IRQ_SPEED_ENUM_DONE can be used to determine -+* when speed negotiation has completed. -+*****************************************************************************/ -+static inline uint iproc_usbd_speed_get(struct iproc_usbd_regs *base) -+{ -+ switch(IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_SPD_MASK) { -+ case IPROC_USBD_REG_STAT_SPD_LS: -+ return(IPROC_USBD_SPEED_LOW); -+ -+ case IPROC_USBD_REG_STAT_SPD_HS: -+ return(IPROC_USBD_SPEED_HIGH); -+ -+ case IPROC_USBD_REG_STAT_SPD_FS: -+ case IPROC_USBD_REG_STAT_SPD_FS_48MHZ: -+ return(IPROC_USBD_SPEED_FULL); -+ } -+ -+ return IPROC_USBD_SPEED_FULL; -+} -+ -+static inline void iproc_usbd_speed_req(struct iproc_usbd_regs *base, uint speed) -+{ -+ IPROC_USBD_BITS_CLEAR(base->dev_cfg, IPROC_USBD_REG_CFG_SPD_MASK); -+ -+ switch(speed) { -+ case IPROC_USBD_SPEED_LOW: -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_SPD_LS); -+ break; -+ -+ case IPROC_USBD_SPEED_HIGH: -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_SPD_HS); -+ break; -+ -+ case IPROC_USBD_SPEED_FULL: -+ default: -+ IPROC_USBD_BITS_SET(base->dev_cfg, IPROC_USBD_REG_CFG_SPD_FS); -+ break; -+ } -+} -+ -+/***************************************************************************** -+* @brief Finalize (terminate) / Initialize Endpoint operations -+* @param num - Endpoint number -+* @param dirn - Endpoint direction. See ENDPT_DIRN_xxx definitions -+* @param dirn - Endpoint type. See ENDPT_TYPE_xxx definitions -+* @param dirn - Endpoint max packet size. -+*****************************************************************************/ -+static inline void iproc_usbd_ep_ops_finish(struct iproc_usbd_regs *base, uint num) -+{ -+} -+ -+static inline void iproc_usbd_ep_ops_init(struct iproc_usbd_regs *base, uint num, uint type, uint dirn, uint maxPktSize) -+{ -+ if ((type == IPROC_USBD_EP_TYPE_CTRL) || (dirn == IPROC_USBD_EP_DIR_OUT)) { -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].ctrl, (type << IPROC_USBD_REG_EP_FIFO_CTRL_TYPE_SHIFT)); -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].status, IPROC_USBD_READ(base->ep_fifo_out[num].status)); -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].size1, 0); -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].size2, ((maxPktSize >> 2) << 16) | maxPktSize); -+#if IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].size2, ((maxPktSize + 3) >> 2) << IPROC_USBD_REG_EP_FIFO_SIZE2_OUT_DEPTH_SHIFT)); -+#endif -+ } -+ if ((type == IPROC_USBD_EP_TYPE_CTRL) || (dirn == IPROC_USBD_EP_DIR_IN)) { -+ IPROC_USBD_WRITE(base->ep_fifo_in[num].ctrl, (type << IPROC_USBD_REG_EP_FIFO_CTRL_TYPE_SHIFT)); -+ IPROC_USBD_WRITE(base->ep_fifo_in[num].size2, (maxPktSize << IPROC_USBD_REG_EP_FIFO_SIZE2_PKT_MAX_SHIFT)); -+ IPROC_USBD_WRITE(base->ep_fifo_in[num].size1, (maxPktSize >> 2)); -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, (IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET | IPROC_USBD_REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE)); -+ } -+ IPROC_USBD_WRITE(base->ep_cfg[num], (num << IPROC_USBD_REG_EP_CFG_FIFO_NUM_SHIFT) | -+ (type << IPROC_USBD_REG_EP_CFG_TYPE_SHIFT) | -+ (maxPktSize << IPROC_USBD_REG_EP_CFG_PKT_MAX_SHIFT) | -+ (dirn == IPROC_USBD_EP_DIR_OUT ? IPROC_USBD_REG_EP_CFG_DIRN_OUT : IPROC_USBD_REG_EP_CFG_DIRN_IN)); -+} -+ -+/***************************************************************************** -+* @brief Endpoint Configuration / Interface / Alternate number operations -+* @param num - Endpoint number -+* @param cfg - Configuration number -+* @param intf - Interface number -+* @param alt - Alternate number -+*****************************************************************************/ -+static inline void iproc_usbd_ep_alt_set(struct iproc_usbd_regs *base, uint num, uint alt) -+{ -+ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], IPROC_USBD_REG_EP_CFG_ALT_NUM_MASK, (alt << IPROC_USBD_REG_EP_CFG_ALT_NUM_SHIFT)); -+} -+ -+static inline void iproc_usbd_ep_cfg_set(struct iproc_usbd_regs *base, uint num, uint cfg) -+{ -+ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], IPROC_USBD_REG_EP_CFG_CFG_NUM_MASK, (cfg << IPROC_USBD_REG_EP_CFG_CFG_NUM_SHIFT)); -+} -+ -+static inline void iproc_usbd_ep_intf_set(struct iproc_usbd_regs *base, uint num, uint intf) -+{ -+ IPROC_USBD_BITS_MODIFY(base->ep_cfg[num], IPROC_USBD_REG_EP_CFG_INTF_NUM_MASK, (intf << IPROC_USBD_REG_EP_CFG_INTF_NUM_SHIFT)); -+} -+ -+ -+/***************************************************************************** -+* @brief Endpoint DMA routines -+* @param num - Endpoint number -+* @param addr - physical address of buffer or descriptor -+*****************************************************************************/ -+static inline void iproc_usbd_ep_dma_dis(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+#if IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_OUT_DMA_ENABLE); -+#else -+ /* -+ * With a single RX FIFO, do not want to do anything, as there might be another OUT capable -+ * endpoint still active and wanting DMA enabled. If theory this should be OK, as long as -+ * the DMA descriptor buffer status fields are the last thing updated before being set to -+ * HOST ready, or the first thing updated when being set to HOST busy. Hopefully no -+ * situations arise such that there's contention with the hardware with doing this. -+ */ -+#endif -+ } else { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_IN_DMA_ENABLE); -+ } -+} -+ -+static inline void iproc_usbd_ep_dma_en(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+#if IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_OUT_DMA_ENABLE); -+#else -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE); -+#endif -+ } else { -+ /* Set the Poll bit in the control register */ -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_IN_DMA_ENABLE); -+ } -+} -+ -+static inline void iproc_usbd_ep_dma_buf_addr_set(struct iproc_usbd_regs *base, uint num, uint dirn, void *addr) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].buf_addr, (uint)addr); -+ } -+} -+ -+static inline void iproc_usbd_ep_dma_desc_addr_set(struct iproc_usbd_regs *base, uint num, uint dirn, void *addr) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].desc_addr, (uint)addr); -+ } -+ else { -+ IPROC_USBD_WRITE(base->ep_fifo_in[num].desc_addr, (uint)addr); -+ } -+} -+ -+/***************************************************************************** -+* @brief Endpoint FIFO routines -+* @param num - Endpoint number -+* @note The flush operation is a state. Once enabled, FIFO contents are discared -+* until disabled. Usually enable upon endpoint termination or error, and -+* then disable once operations are to resume normally. -+*****************************************************************************/ -+static inline bool iproc_usbd_ep_fifo_empty(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+#if IPROC_USBD_MULTI_RX_FIFO -+ return(base->ep_fifo_out[num].status & IPROC_USBD_REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY ? true : false); -+#else -+ return(base->dev_status & IPROC_USBD_REG_STAT_OUT_FIFO_EMPTY ? true : false); -+#endif -+ } -+ return(base->ep_fifo_in[num].status & IPROC_USBD_REG_EP_FIFO_STATUS_IN_FIFO_EMPTY ? true : false); -+} -+ -+static inline void iproc_usbd_ep_fifo_flush_dis(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+#if IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE); -+#else -+ IPROC_USBD_BITS_CLEAR(base->dev_ctrl, IPROC_USBD_REG_CTRL_OUT_FIFO_FLUSH_ENABLE); -+#endif -+ } -+ else { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); -+ } -+} -+ -+static inline void iproc_usbd_ep_fifo_flush_en(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+#if IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_OUT_FLUSH_ENABLE); -+#else -+ IPROC_USBD_BITS_SET(base->dev_ctrl, IPROC_USBD_REG_CTRL_OUT_FIFO_FLUSH_ENABLE); -+#endif -+ } else { -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_IN_FLUSH_ENABLE); -+ } -+} -+ -+/***************************************************************************** -+* @brief Endpoint Frame Number routines -+* @param num - Endpoint number -+* @return Frame number of last packet received on the endpoint, and in the following format. -+* bits[13:3] milli-second frame number -+* bits[2:0] micro-frame number -+* @note Really only applicable to OUT endpoints. IN will always return 0. -+*****************************************************************************/ -+static inline uint iproc_usbd_ep_frame_num(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ return((IPROC_USBD_READ(base->ep_fifo_out[num].size1) & IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_MASK) >> IPROC_USBD_REG_EP_FIFO_SIZE1_OUT_FRAME_NUM_SHIFT); -+ } -+ return(0); -+} -+ -+/***************************************************************************** -+* @brief Endpoint IRQ / status routines -+* @param num - Endpoint number -+* @note -+* Cannot set specific status for Endpoint interrupts. Can only do operations -+* in a global sense. Once an interrupt occurs for an endpoint, the endpoint -+* status has to be checked for the particular type of interrupt that occurred. -+* -+* The iproc_usbd_ep_irq_en() and iproc_usbd_ep_irq_dis() are used for -+* operations on a specific endpoint. These routines may or may not be used in -+* the context of interrupt processing. -+* -+* Use the usbDevHw_EndptIrqListXxx() routines for operations using a bit-wise -+* list of endpoints (bit 0 for endpoint 0, etc.). Typical use would be for -+* interrupt processing. -+* -+* Use the IPROC_USBD_EP_STAT_xxx definitions with the status routines. These -+* definitions are bit-wise, and allow operations on multiple conditions -+* by OR'ing the definitions together. -+*****************************************************************************/ -+static inline void iproc_usbd_ep_irq_clear(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_WRITE(base->ep_irq_status, (1 << num) << IPROC_USBD_REG_EP_INTR_OUT_SHIFT); -+ } else { -+ IPROC_USBD_WRITE(base->ep_irq_status, (1 << num) << IPROC_USBD_REG_EP_INTR_IN_SHIFT); -+ } -+} -+ -+static inline void iproc_usbd_ep_irq_dis(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_SET(base->ep_irq_mask, ((1 << num) << IPROC_USBD_REG_EP_INTR_OUT_SHIFT)); -+ } else { -+ IPROC_USBD_BITS_SET(base->ep_irq_mask, ((1 << num) << IPROC_USBD_REG_EP_INTR_IN_SHIFT)); -+ } -+} -+ -+static inline void iproc_usbd_ep_irq_en(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_CLEAR(base->ep_irq_mask, ((1 << num) << IPROC_USBD_REG_EP_INTR_OUT_SHIFT)); -+ } else { -+ IPROC_USBD_BITS_CLEAR(base->ep_irq_mask, ((1 << num) << IPROC_USBD_REG_EP_INTR_IN_SHIFT)); -+ } -+} -+ -+static inline uint iproc_usbd_ep_irq_list_active(struct iproc_usbd_regs *base, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ return((IPROC_USBD_READ(base->ep_irq_status) & IPROC_USBD_REG_EP_INTR_OUT_MASK) >> IPROC_USBD_REG_EP_INTR_OUT_SHIFT); -+ } -+ return((IPROC_USBD_READ(base->ep_irq_status) & IPROC_USBD_REG_EP_INTR_IN_MASK) >> IPROC_USBD_REG_EP_INTR_IN_SHIFT); -+} -+ -+static inline void iproc_usbd_ep_irq_list_clear(struct iproc_usbd_regs *base, uint dirn, uint mask) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_WRITE(base->ep_irq_status, (mask << IPROC_USBD_REG_EP_INTR_OUT_SHIFT)); /*strat from bit 16 */ -+ } else { -+ IPROC_USBD_WRITE(base->ep_irq_status, (mask << IPROC_USBD_REG_EP_INTR_IN_SHIFT)); /* start from bit 0 */ -+ } -+} -+ -+static inline uint iproc_usbd_ep_stat_active(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ return(IPROC_USBD_READ(base->ep_fifo_out[num].status)); /* End Point Status register */ -+ } -+ return(IPROC_USBD_READ(base->ep_fifo_in[num].status)); -+} -+ -+static inline void iproc_usbd_ep_stat_clear(struct iproc_usbd_regs *base, uint num, uint dirn, uint mask) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_WRITE(base->ep_fifo_out[num].status, mask); -+ } else { -+ IPROC_USBD_WRITE(base->ep_fifo_in[num].status, mask); -+ } -+} -+ -+/***************************************************************************** -+* @brief Endpoint NAK routines -+* @param num - Endpoint number -+* @note A NAK response can be enabled by the application by the EndptNakEnable(). -+* The EndptNakInProgress() is used to determine if the controller is -+* currently actively sending NAKs. This may have been a result of the -+* EndptNakEnable() or automatically by the controller under certain -+* conditions. The EndptNakClear() must be used to terminate the NAKs. -+*****************************************************************************/ -+static inline void iproc_usbd_ep_nak_clear(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_CLEAR); -+ } else { -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_CLEAR); -+ } -+} -+ -+static inline void iproc_usbd_ep_nak_en(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET); -+ } else { -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET); -+ } -+} -+ -+static inline void iproc_usbd_ep_nak_dis(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET); -+ } else { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_NAK_SET); -+ } -+} -+ -+static inline bool iproc_usbd_ep_nak_progress(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ return (IPROC_USBD_READ(base->ep_fifo_out[num].ctrl) & IPROC_USBD_REG_EP_FIFO_CTRL_NAK_IN_PROGRESS) ? true : false; -+ } -+ return (IPROC_USBD_READ(base->ep_fifo_in[num].ctrl) & IPROC_USBD_REG_EP_FIFO_CTRL_NAK_IN_PROGRESS) ? true : false; -+} -+ -+/***************************************************************************** -+* @brief Endpoint Stall routines -+* Disable / Enable STALL responses (halt feature) on a given endpoint. -+* @param num - Endpoint number -+*****************************************************************************/ -+static inline void iproc_usbd_ep_stall_dis(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_STALL_ENABLE); -+ } else { -+ IPROC_USBD_BITS_CLEAR(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_STALL_ENABLE); -+ } -+} -+ -+static inline void iproc_usbd_ep_stall_en(struct iproc_usbd_regs *base, uint num, uint dirn) -+{ -+#if IPROC_USBD_MULTI_RX_FIFO -+ if (!(IPROC_USBD_READ(base->ep_fifo_out[num].status) & IPROC_USBD_REG_EP_FIFO_STATUS_OUT_FIFO_EMPTY)) -+#else -+ if (!(IPROC_USBD_READ(base->dev_status) & IPROC_USBD_REG_STAT_OUT_FIFO_EMPTY)) -+#endif -+ return; -+ -+ if (dirn == IPROC_USBD_EP_DIR_OUT) { -+ IPROC_USBD_BITS_SET(base->ep_fifo_out[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_STALL_ENABLE); -+ } else { -+ IPROC_USBD_BITS_SET(base->ep_fifo_in[num].ctrl, IPROC_USBD_REG_EP_FIFO_CTRL_STALL_ENABLE); -+ } -+} -+ -+ -+/***************************************************************************** -+* @brief Initialize device controller operations -+*****************************************************************************/ -+static inline void iproc_usbd_ops_init(struct iproc_usbd_regs *base) -+{ -+ int idx; -+ -+ iproc_usbd_dma_dis(base); -+ iproc_usbd_irq_dis(base, IPROC_USBD_IRQ_ALL); -+ iproc_usbd_irq_clear(base, IPROC_USBD_IRQ_ALL); -+ -+ /* @todo Create and use usbDevHw_EndptIrqListDisable?? */ -+ for (idx = 0; idx < IPROC_USBD_EP_CFG_CNT; idx++) { -+ iproc_usbd_ep_irq_dis(base, idx, IPROC_USBD_EP_DIR_IN); -+ iproc_usbd_ep_irq_clear(base, idx, IPROC_USBD_EP_DIR_IN); -+ iproc_usbd_ep_stat_clear(base, idx, IPROC_USBD_EP_DIR_IN, iproc_usbd_ep_stat_active(base, idx, IPROC_USBD_EP_DIR_IN)); -+ -+ iproc_usbd_ep_irq_dis(base, idx, IPROC_USBD_EP_DIR_OUT); -+ iproc_usbd_ep_irq_clear(base, idx, IPROC_USBD_EP_DIR_OUT); -+ iproc_usbd_ep_stat_clear(base, idx, IPROC_USBD_EP_DIR_OUT, iproc_usbd_ep_stat_active(base, idx, IPROC_USBD_EP_DIR_OUT)); -+ } -+ -+ IPROC_USBD_WRITE(base->dev_cfg, (IPROC_USBD_REG_CFG_SET_DESCRIPTOR_ENABLE | -+ IPROC_USBD_REG_CFG_UTMI_8BIT_ENABLE | -+ IPROC_USBD_REG_CFG_CSR_PROGRAM_ENABLE | -+ IPROC_USBD_REG_CFG_SPD_HS)); -+ -+ IPROC_USBD_WRITE(base->dev_ctrl, (IPROC_USBD_REG_CTRL_LE_ENABLE | -+ IPROC_USBD_REG_CTRL_DISCONNECT_ENABLE | -+ IPROC_USBD_REG_CTRL_DMA_MODE_ENABLE | -+ IPROC_USBD_REG_CTRL_DMA_IN_ENABLE | -+ IPROC_USBD_REG_CTRL_DMA_OUT_ENABLE | -+ IPROC_USBD_REG_CTRL_DMA_DESC_UPDATE_ENABLE | -+ IPROC_USBD_REG_CTRL_OUT_NAK_ALL_ENABLE | -+ IPROC_USBD_REG_CTRL_DMA_OUT_THRESHOLD_LEN_MASK | -+ IPROC_USBD_REG_CTRL_DMA_BURST_LEN_MASK | -+#if !IPROC_USBD_MULTI_RX_FIFO -+ IPROC_USBD_REG_CTRL_OUT_FIFO_FLUSH_ENABLE | -+#endif -+ IPROC_USBD_REG_CTRL_DMA_BURST_ENABLE)); -+ -+ IPROC_USBD_WRITE(base->dev_irq_mask, (IPROC_USBD_REG_INTR_BUS_IDLE | -+ IPROC_USBD_REG_INTR_SOF_RX)); -+ IPROC_USBD_WRITE(base->ep_irq_mask,0); -+} -+ -+/***************************************************************************** -+* @brief Disable / Enable USB device -+*****************************************************************************/ -+static inline void iproc_usbd_dis(struct iproc_usbd_idm_regs *idm_base) -+{ -+ /* reset usb device */ -+ IPROC_USBD_BITS_SET(idm_base->reset_ctrl, IPROC_USB2D_IDM_REG_RESET_CTRL_RESET); -+ -+ /* disable usb device clock */ -+ IPROC_USBD_BITS_CLEAR(idm_base->io_ctrl, IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE); -+ mdelay(10); -+} -+ -+static inline void iproc_usbd_en(struct iproc_usbd_idm_regs *idm_base) -+{ -+ /* enable usb device clock */ -+ IPROC_USBD_BITS_SET(idm_base->io_ctrl, IPROC_USB2D_IDM_REG_IO_CTRL_DIRECT_CLK_ENABLE); -+ mdelay(10); -+ -+ /* get usb device out of reset */ -+ IPROC_USBD_BITS_CLEAR(idm_base->reset_ctrl, IPROC_USB2D_IDM_REG_RESET_CTRL_RESET); -+ mdelay(100); -+} -+ -+ -+ -+#endif /* _USBD_REGS_H_ */ -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig ---- a/drivers/usb/host/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/host/Kconfig 2017-11-09 17:54:01.760430000 +0800 -@@ -298,6 +298,13 @@ config USB_EHCI_HCD_PLATFORM - - If unsure, say N. - -+config USB_EHCI_XGS_IPROC -+ bool "BRCM XGS iProc EHCI patch" -+ depends on (ARCH_XGS_IPROC && USB_EHCI_HCD_PLATFORM) -+ default n -+ ---help--- -+ This option is for BRCM XGS iProc EHCI patch -+ - config USB_OCTEON_EHCI - bool "Octeon on-chip EHCI support (DEPRECATED)" - depends on CAVIUM_OCTEON_SOC -@@ -561,6 +568,13 @@ config USB_OHCI_HCD_PLATFORM - - If unsure, say N. - -+config USB_OHCI_XGS_IPROC -+ bool "BRCM XGS iProc OHCI patch" -+ depends on (ARCH_XGS_IPROC && USB_OHCI_HCD_PLATFORM) -+ default n -+ ---help--- -+ This option is for BRCM XGS iProc OHCI patch -+ - config USB_OCTEON_OHCI - bool "Octeon on-chip OHCI support (DEPRECATED)" - depends on CAVIUM_OCTEON_SOC -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c ---- a/drivers/usb/host/ehci-platform.c 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/host/ehci-platform.c 2017-11-09 17:54:01.791421000 +0800 -@@ -41,6 +41,14 @@ - #define EHCI_MAX_CLKS 3 - #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) - -+ -+#ifdef CONFIG_USB_EHCI_XGS_IPROC -+#include -+#include -+ -+#define BCM_USB_FIFO_THRESHOLD 0x00800040 -+#endif /* CONFIG_USB_EHCI_XGS_IPROC */ -+ - struct ehci_platform_priv { - struct clk *clks[EHCI_MAX_CLKS]; - struct reset_control *rst; -@@ -150,10 +158,24 @@ static int ehci_platform_probe(struct pl - struct ehci_platform_priv *priv; - struct ehci_hcd *ehci; - int err, irq, phy_num, clk = 0; -+#ifdef CONFIG_USB_EHCI_XGS_IPROC -+ struct usb_phy *phy; -+#endif /* CONFIG_USB_EHCI_XGS_IPROC */ - - if (usb_disabled()) - return -ENODEV; - -+#ifdef CONFIG_USB_EHCI_XGS_IPROC -+ phy = devm_usb_get_phy_by_phandle(&dev->dev, "usb-phy", 0); -+ if (IS_ERR(phy)) { -+ dev_err(&dev->dev, "unable to find transceiver\n"); -+ return PTR_ERR(phy); -+ } -+ -+ if (phy->flags != IPROC_USB_MODE_HOST) -+ return -ENODEV; -+#endif -+ - /* - * Use reasonable defaults so platforms don't have to provide these - * with DT probing on ARM. -@@ -292,6 +314,9 @@ static int ehci_platform_probe(struct pl - goto err_power; - - device_wakeup_enable(hcd->self.controller); -+#ifdef CONFIG_USB_EHCI_XGS_IPROC -+ ehci_writel(ehci, BCM_USB_FIFO_THRESHOLD, &ehci->regs->reserved4[6]); -+#endif - platform_set_drvdata(dev, hcd); - - return err; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c ---- a/drivers/usb/host/ohci-platform.c 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/host/ohci-platform.c 2017-11-09 17:54:01.874447000 +0800 -@@ -35,6 +35,14 @@ - #define OHCI_MAX_CLKS 3 - #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv) - -+#ifdef CONFIG_USB_OHCI_XGS_IPROC -+#include -+#include -+ -+#define UHCRHDA_REG_OFFSET 0x48 -+#define UHCRHDA_OCPM (1 << 11) -+#endif -+ - struct ohci_platform_priv { - struct clk *clks[OHCI_MAX_CLKS]; - struct reset_control *rst; -@@ -118,10 +126,24 @@ static int ohci_platform_probe(struct pl - struct ohci_platform_priv *priv; - struct ohci_hcd *ohci; - int err, irq, phy_num, clk = 0; -+#ifdef CONFIG_USB_OHCI_XGS_IPROC -+ struct usb_phy *phy; -+#endif /* CONFIG_USB_OHCI_XGS_IPROC */ - - if (usb_disabled()) - return -ENODEV; - -+#ifdef CONFIG_USB_OHCI_XGS_IPROC -+ phy = devm_usb_get_phy_by_phandle(&dev->dev, "usb-phy", 0); -+ if (IS_ERR(phy)) { -+ dev_err(&dev->dev, "unable to find transceiver\n"); -+ return PTR_ERR(phy); -+ } -+ -+ if (phy->flags != IPROC_USB_MODE_HOST) -+ return -ENODEV; -+#endif /* CONFIG_USB_OHCI_XGS_IPROC */ -+ - /* - * Use reasonable defaults so platforms don't have to provide these - * with DT probing on ARM. -@@ -251,6 +273,12 @@ static int ohci_platform_probe(struct pl - hcd->rsrc_start = res_mem->start; - hcd->rsrc_len = resource_size(res_mem); - -+#ifdef CONFIG_USB_OHCI_XGS_IPROC -+#if defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) || defined(CONFIG_MACH_GH2) -+ writel(readl(hcd->regs + UHCRHDA_REG_OFFSET) | UHCRHDA_OCPM, hcd->regs + UHCRHDA_REG_OFFSET); -+#endif -+#endif -+ - err = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (err) - goto err_power; -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig ---- a/drivers/usb/phy/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/phy/Kconfig 2017-11-09 17:54:02.191425000 +0800 -@@ -213,4 +213,11 @@ config USB_ULPI_VIEWPORT - Provides read/write operations to the ULPI phy register set for - controllers with a viewport register (e.g. Chipidea/ARC controllers). - -+config USBPHY_XGS_IPROC -+ tristate "BRCM iProc USB PHY" -+ depends on ARCH_XGS_IPROC -+ select USB_PHY -+ help -+ BRCM iProc USB PHY driver -+ - endmenu -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile ---- a/drivers/usb/phy/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/usb/phy/Makefile 2017-11-09 17:54:02.191443000 +0800 -@@ -27,3 +27,4 @@ obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar- - obj-$(CONFIG_USB_ULPI) += phy-ulpi.o - obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o - obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o -+obj-$(CONFIG_USBPHY_XGS_IPROC) += phy-xgs-iproc.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/usb/phy/phy-xgs-iproc.c b/drivers/usb/phy/phy-xgs-iproc.c ---- a/drivers/usb/phy/phy-xgs-iproc.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/usb/phy/phy-xgs-iproc.c 2017-11-09 17:54:02.236439000 +0800 -@@ -0,0 +1,745 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define USB2D_IDM_IDM_IO_CONTROL_DIRECT_ADDR(base) (base + 0x408) -+#define USB2D_IDM_IDM_RESET_CONTROL_ADDR(base) (base + 0x800) -+#define IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK 1 -+#define USB2D_IDM_IDM_RESET_CONTROL__RESET 0 -+#define USB2D_IDM_IDM_IO_CONTROL_DIRECT__clk_enable 0 -+ -+#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) -+ -+#define IPROC_CCB_MDIO_MII_CTRL_ADDR(base) (base + 0x0) -+#define IPROC_CCB_MDIO_MII_DATA_ADDR(base) (base + 0x4) -+#define IPROC_CCB_MDIO_COMPATIBLE "brcm,iproc-ccb-mdio" -+ -+#if defined(CONFIG_MACH_HX4) -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_ADDR(base) (base + 0x1c) -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_ADDR(base) (base + 0x2c) -+#define IPROC_WRAP_USBPHY_CTRL_ADDR(base) (base + 0x34) -+#define IPROC_WRAP_MISC_STATUS_ADDR(base) (base + 0x38) -+#define IPROC_CLK_NDIV_40 0x80 -+#define IPROC_CLK_NDIV_20 0x8C -+#define USB_CLK_NDIV_MASK 0xFE7FFE00 -+#define USB_CLK_PLL_RESET_MASK 0xFF7FFE00 -+#define USB_CLK_PHY_RESET_MASK 0xFFFFFE00 -+#define USB_CLK_NDIV_40 0x30 -+#define USB_CLK_NDIV_20 0x60 -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_R 0 -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_WIDTH 8 -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_R 8 -+#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_WIDTH 8 -+#else -+#define IPROC_DDR_PLL_CTRL_REGISTER_3_ADDR(base) (base + 0x0c) -+#define IPROC_DDR_PLL_CTRL_REGISTER_5_ADDR(base) (base + 0x14) -+#define IPROC_WRAP_USBPHY_CTRL_ADDR(base) (base + 0x20) -+#define IPROC_WRAP_MISC_STATUS_ADDR(base) (base + 0x28) -+#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_R 0 -+#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_WIDTH 10 -+#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_R 0 -+#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_WIDTH 8 -+#endif /* defined(CONFIG_MACH_HX4) */ -+ -+#else /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) */ -+ -+#define IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ 26 -+#define IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB 25 -+#define IPROC_WRAP_USBPHY_CTRL_0__RESETB 24 -+#define IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO 17 -+#define IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0 0 -+#define IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11 11 -+ -+#if defined(CONFIG_MACH_SB2) -+#define IPROC_WRAP_USBPHY_CTRL_0_ADDR(base) (base + 0x28) -+#define IPROC_WRAP_USBPHY_CTRL_2_ADDR(base) (base + 0x30) -+#define IPROC_WRAP_MISC_STATUS_ADDR(base) (base + 0x44) -+#define IPROC_WRAP_TOP_STRAP_CTRL_ADDR(base) (base + 0x70) -+#define IPROC_WRAP_TOP_STRAP_CTRL__USB_DEVICE 10 -+ -+#elif defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) || \ -+ defined(CONFIG_MACH_GH2) -+#define IPROC_WRAP_USBPHY_CTRL_0_ADDR(base) (base + 0x44) -+#define IPROC_WRAP_USBPHY_CTRL_2_ADDR(base) (base + 0x4c) -+#define IPROC_WRAP_MISC_STATUS_ADDR(base) (base + 0x58) -+#define IPROC_WRAP_TOP_STRAP_STATUS_ADDR(base) (base + 0xa4) -+#define IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL 17 -+#if defined(CONFIG_MACH_GH2) -+#define USBH_Utmi_p0Ctl(base) (base + 0x10) -+static void __iomem *USBH_Utmi_base = NULL; -+#endif /* defined(CONFIG_MACH_GH2) */ -+#endif -+ -+#endif /* defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) */ -+ -+struct iproc_usb_priv { -+ struct usb_phy phy; -+ struct device *dev; -+ struct device_node *dn; -+ void __iomem *wrap_base; -+ void __iomem *idm_base; -+ uint usb_mode; -+}; -+ -+extern void __iomem *get_iproc_wrap_ctrl_base(void); -+ -+/*************************************************************************** -+**************************************************************************** -+***************************************************************************/ -+static const struct of_device_id xgs_iproc_usb_phy_dt_ids[] = { -+ { .compatible = "brcm,usb-phy,hx4", }, -+ { .compatible = "brcm,usb-phy,kt2", }, -+ { .compatible = "brcm,usb-phy,gh", }, -+ { .compatible = "brcm,usb-phy,sb2", }, -+ { .compatible = "brcm,usb-phy,hr3", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, xgs_iproc_usb_phy_dt_ids); -+ -+ -+static int xgs_iproc_usb_phy_mode(struct iproc_usb_priv *iproc_usb_data) -+{ -+ void __iomem *wrap_base = iproc_usb_data->wrap_base; -+ struct device *dev = iproc_usb_data->dev; -+ int usb_mode = IPROC_USB_MODE_HOST; -+ ulong val; -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ int gpio_pin, ret; -+#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ -+ -+ if (!wrap_base) { -+ return -EINVAL; -+ } -+ -+#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) -+ /* gpio pin 4 to control host/device mode */ -+ gpio_pin = of_get_named_gpio(dev->of_node, "usbdev-gpio", 0); -+ -+ if (gpio_pin < 0) { -+ dev_warn(dev, "No gpio pin set for USB device detection(default to 4)\n"); -+ gpio_pin = 4; -+ } -+ -+ ret = gpio_request(gpio_pin, "usbdev-gpio"); -+ if (ret != 0) { -+ dev_err(dev, "request gpio #%d error.\n", gpio_pin); -+ return ret; -+ } -+ -+ val = __gpio_get_value(gpio_pin); -+ -+ gpio_free(gpio_pin); -+ -+ if (val & 1) { -+ usb_mode = IPROC_USB_MODE_DEVICE; -+ } -+#elif defined(CONFIG_MACH_SB2) -+ /* u-boot enable this bit to indicate usb in host mode */ -+ val = readl_relaxed(IPROC_WRAP_TOP_STRAP_CTRL_ADDR(wrap_base)); -+ if (!(val & (1 << IPROC_WRAP_TOP_STRAP_CTRL__USB_DEVICE))) { -+ usb_mode = IPROC_USB_MODE_DEVICE; -+ } -+#else -+ /* u-boot enable this bit to indicate usb in host mode */ -+ val = readl_relaxed(IPROC_WRAP_TOP_STRAP_STATUS_ADDR(wrap_base)); -+ if (!(val & (1 << IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL))) { -+ usb_mode = IPROC_USB_MODE_DEVICE; -+ } -+#endif -+ -+ dev_info(dev, "usb mode: %s\n", (usb_mode == IPROC_USB_MODE_DEVICE) ? "DEVICE" : "HOST"); -+ -+ return usb_mode; -+} -+ -+#if (defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_KT2)) -+/* Returns USB PHY PLL ref clock in MHz */ -+static uint _get_usb_clk(void __iomem *wrap_base) -+{ -+ uint ndiv, mdiv, refclk; -+ ulong val; -+ -+#if defined(CONFIG_MACH_HX4) -+ val = readl_relaxed(IPROC_WRAP_IPROC_XGPLL_CTRL_4_ADDR(wrap_base)); -+ ndiv = ((val >> IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_R) & -+ ~(0xFFFFFFFF << IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_WIDTH)); -+ -+ val = readl_relaxed(IPROC_WRAP_IPROC_XGPLL_CTRL_0_ADDR(wrap_base)); -+ mdiv = ((val >> IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_R) & -+ ~(0xFFFFFFFF << IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_WIDTH)); -+#else -+ val = readl_relaxed(IPROC_DDR_PLL_CTRL_REGISTER_3_ADDR(wrap_base)); -+ ndiv = ((val >> IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_R) & -+ ~(0xFFFFFFFF << IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_WIDTH)); -+ -+ /* read channel 1 mdiv */ -+ val = readl_relaxed(IPROC_DDR_PLL_CTRL_REGISTER_5_ADDR(wrap_base)); -+ mdiv = ((val >> IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_R) & -+ ~(0xFFFFFFFF << IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_WIDTH)); -+#endif -+ -+ refclk = (25 * ndiv) / mdiv; -+ -+ return refclk; -+} -+#endif /* (defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_KT2)) */ -+ -+static int iproc_usb_phy_hx4_config(struct iproc_usb_priv *iproc_usb_data) -+{ -+#if (defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_KT2)) -+ void __iomem *wrap_base = iproc_usb_data->wrap_base; -+ void __iomem *ccb_mdio_base = NULL; -+ struct device_node *np; -+ ulong ndiv, precmd, miicmd, miidata; -+ ulong val, mask; -+ uint count = 0; -+ -+ if (!wrap_base) -+ return -EINVAL; -+ -+ if (iproc_usb_data->usb_mode == IPROC_USB_MODE_DEVICE) { -+ np = of_find_compatible_node(NULL, NULL, IPROC_CCB_MDIO_COMPATIBLE); -+ if (!np) { -+ printk(KERN_ERR "Failed to find CCB MDIO defined in DT\n"); -+ return -ENODEV; -+ } -+ -+ ccb_mdio_base = of_iomap(np, 0); -+ if (!ccb_mdio_base) { -+ printk(KERN_ERR "Unable to iomap CCB MDIO base address\n"); -+ return -ENXIO; -+ } -+ -+ ndiv = 1920 / _get_usb_clk(wrap_base); -+ -+ /* Construct precmd with Start Bit, PHY address and turnaround time */ -+ /* SB | PA | TA */ -+ precmd = 1 << 30 | 6 << 23 | 2 << 16; -+ -+ /* Connect MDIO interface to onchip PHY */ -+ writel_relaxed(0x9A, IPROC_CCB_MDIO_MII_CTRL_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ /* Program NDIV and PDIV into 0x1C register */ -+ miicmd = precmd | (0x1 << 28) | (0x1C << 18); -+ miidata = 1 << 12 | ndiv; -+ /* 0x53721040 */ -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ /* Program other PLL parameters into 0x1D register, disable suspend and put PHY into reset */ -+ miicmd = precmd | (0x1 << 28) | (0x1D << 18); -+ miidata = 1 << 13 | 3 << 8 | 3 << 4 | 0xa; -+ /* 0x5376233a */ -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ /* Program register 0x15, USB device mode set and get PHY out of reset */ -+ miicmd = precmd | (0x1 << 28) | (0x15 << 18); -+ miidata = 1 << 2 | 1 << 1; -+ /* 0x53560006 */ -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ /* Program register 0x19, set mdio mode */ -+ miicmd = precmd | (0x1 << 28) | (0x19 << 18); -+ miidata = 1 << 7; -+ /* 0x53660080 */ -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ /* get the PLL out of reset */ -+ miicmd = precmd | (0x2 << 28) | (0x1D << 18); -+ miidata = 0; -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ miidata = readl_relaxed(IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ miicmd = precmd | (0x1 << 28) | (0x1D << 18); -+ miidata |= (1 << 12); -+ /* 0x5376333a */ -+ writel_relaxed(miicmd | miidata, IPROC_CCB_MDIO_MII_DATA_ADDR(ccb_mdio_base)); -+ mdelay(10); -+ -+ if (ccb_mdio_base) { -+ iounmap(ccb_mdio_base); -+ ccb_mdio_base = NULL; -+ } -+ } else { -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ val |= 0x01000000; /* 24:PLL_RESETB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ -+ mdelay(20); -+ -+ /* check pll_lock */ -+ mask = (1 << IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK); -+ do { -+ val = readl_relaxed(IPROC_WRAP_MISC_STATUS_ADDR(wrap_base)); -+ if ((val & mask) == mask) { -+ break; -+ } else { -+ udelay(10); -+ count ++; -+ } -+ } while(count <= 10); -+ if (count > 10) { -+ printk(KERN_WARNING "%s : PLL not lock! IPROC_WRAP_MISC_STATUS = 0x%08lx\n", -+ __FUNCTION__, val); -+ } -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ val &= ~0x00800000; /* 23:RESETB = 0 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ mdelay(100); -+ -+#if defined(CONFIG_MACH_HX4) -+ val = readl_relaxed(IPROC_WRAP_IPROC_XGPLL_CTRL_4_ADDR(wrap_base)); -+ ndiv = ((val >> IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_R) & -+ ~(0xFFFFFFFF << IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_WIDTH)); -+ if (ndiv == IPROC_CLK_NDIV_40) { -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ val = (val & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_40; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ val = (val & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_40; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ val = (val & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_40; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ } else if (ndiv == IPROC_CLK_NDIV_20) { -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ val = (val & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_20; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ val = (val & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_20; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ val = (val & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_20; -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(10); -+ } -+#endif /* CONFIG_MACH_HX4 */ -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ val |= 0x00800000; /* 23:RESETB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_ADDR(wrap_base)); -+ udelay(100); -+ } -+#endif /* (defined (CONFIG_MACH_HX4) || defined (CONFIG_MACH_KT2)) */ -+ -+ return 0; -+} -+ -+static int iproc_usb_phy_sb2_config(struct iproc_usb_priv *iproc_usb_data) -+{ -+#if defined(CONFIG_MACH_SB2) -+ void __iomem *wrap_base = iproc_usb_data->wrap_base; -+ ulong val, mask, count = 0; -+ -+ if (!wrap_base) { -+ return -EINVAL; -+ } -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val |= 0x0c000000; /* 27:PHY_ISO & 26:PLL_SUSPEND_EN = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val &= ~0x03000000; /* 25:PLL_RESETB & 24:RESETB = 0 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val &= ~0x03000000; /* 25:AFE_BG_PWRDWNB & 24:AFE_LDO_PWRDWNB = 0 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ udelay(10); -+ val |= 0x02000000; /* 25:AFE_BG_PWRDWNB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ udelay(150); -+ val |= 0x01000000; /* 24:AFE_LDO_PWRDWNB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ udelay(160); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val &= ~0x08000000; /* 27:PHY_ISO = 0 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ udelay(20); -+ val |= 0x02000000; /* 25:PLL_RESETB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ mdelay(20); -+ -+ /* check pll_lock */ -+ mask = (1 << IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK); -+ do { -+ val = readl_relaxed(IPROC_WRAP_MISC_STATUS_ADDR(wrap_base)); -+ if ((val & mask) == mask) { -+ break; -+ } else { -+ udelay(10); -+ count ++; -+ } -+ } while(count <= 10); -+ -+ if (count > 10) -+ printk(KERN_WARNING "%s : PLL not lock! IPROC_WRAP_MISC_STATUS = 0x%08lx\n", -+ __FUNCTION__, val); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val |= 0x01000000; /* 24:RESETB = 1 */ -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ udelay(2); -+#endif /* defined(CONFIG_MACH_SB2) */ -+ -+ return 0; -+} -+ -+static int iproc_usb_phy_gh_config(struct iproc_usb_priv *iproc_usb_data) -+{ -+#if defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) || \ -+ defined (CONFIG_MACH_GH2) -+ void __iomem *wrap_base = iproc_usb_data->wrap_base; -+ ulong val, mask, count = 0; -+ -+ if (!wrap_base) -+ return -EINVAL; -+ -+#if !defined(CONFIG_MACH_GH2) -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ -+ /* set phy_resetb to 0, pll_resetb to 0 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__RESETB); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ /* set p1ctl[11] to 0 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ -+ /* set phy_iso to 0 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_2__PHY_ISO); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ -+ /* set phy_iddq to 0 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_0__PHY_IDDQ); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ mdelay(1); -+ -+ /* set pll_resetb to 1, phy_resetb to 1 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__PLL_RESETB); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_0__RESETB); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_0_ADDR(wrap_base)); -+#else /* !defined(CONFIG_MACH_GH2) */ -+ /* This value is from the designer to set Internal Power Sequence Mode */ -+ val = readl_relaxed(IPROC_WRAP_TOP_STRAP_STATUS_ADDR(wrap_base)); -+ if (!(val & (1 << IPROC_WRAP_TOP_STRAP_STATUS__USB2_SEL))) { -+ /* device mode */ -+ writel_relaxed(0x0806, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ } else { -+ /* host mode */ -+ writel_relaxed(0x0802, USBH_Utmi_p0Ctl(USBH_Utmi_base)); -+ } -+#endif /* !defined(CONFIG_MACH_GH2) */ -+ mdelay(20); -+ -+ /* check pll_lock */ -+ mask = (1 << IPROC_WRAP_MISC_STATUS__USBPHY_PLL_LOCK); -+ do { -+ val = readl_relaxed(IPROC_WRAP_MISC_STATUS_ADDR(wrap_base)); -+ if ((val & mask) == mask) { -+ break; -+ } else { -+ udelay(10); -+ count ++; -+ } -+ } while(count <= 10); -+ -+ if (count > 10) { -+ printk(KERN_WARNING "%s : PLL not lock! IPROC_WRAP_MISC_STATUS = 0x%08lx\n", -+ __FUNCTION__, val); -+ } -+ -+#if !defined(CONFIG_MACH_GH2) -+ /* set non_drving to 0 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val &= ~(1 << IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B0); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ -+ /* set p1ctl[11] to 1 */ -+ val = readl_relaxed(IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+ val |= (1 << IPROC_WRAP_USBPHY_CTRL_2__P1CTL_B11); -+ writel_relaxed(val, IPROC_WRAP_USBPHY_CTRL_2_ADDR(wrap_base)); -+#endif /* !defined(CONFIG_MACH_GH2) */ -+#endif /* defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_HR3) || defined (CONFI -+G_MACH_GH2) */ -+ -+ return 0; -+} -+ -+static int iproc_usb_phy_init(struct usb_phy *phy) -+{ -+ struct iproc_usb_priv *iproc_usb_data = container_of(phy, struct iproc_usb_priv, phy); -+ struct device *dev = iproc_usb_data->dev; -+ const struct of_device_id *match; -+ int ret = 0; -+ uint val; -+ -+ if (!iproc_usb_data->wrap_base || !iproc_usb_data->idm_base) { -+ return -EINVAL; -+ } -+ -+ match = of_match_device(xgs_iproc_usb_phy_dt_ids, dev); -+ if (!match) { -+ dev_err(dev, "failed to find USB PHY in DT\n"); -+ return -ENODEV; -+ } -+ -+ /* Put USBD controller into reset state and disable clock via IDM registers */ -+ val = readl_relaxed(USB2D_IDM_IDM_RESET_CONTROL_ADDR(iproc_usb_data->idm_base)); -+ val |= (1 << USB2D_IDM_IDM_RESET_CONTROL__RESET); -+ writel_relaxed(val, USB2D_IDM_IDM_RESET_CONTROL_ADDR(iproc_usb_data->idm_base)); -+ -+ val = readl_relaxed(USB2D_IDM_IDM_IO_CONTROL_DIRECT_ADDR(iproc_usb_data->idm_base)); -+ val &= ~(1 << USB2D_IDM_IDM_IO_CONTROL_DIRECT__clk_enable); -+ writel_relaxed(val, USB2D_IDM_IDM_IO_CONTROL_DIRECT_ADDR(iproc_usb_data->idm_base)); -+ -+ if (strstr(match->compatible, "hx4") || -+ strstr(match->compatible, "kt2")) -+ ret = iproc_usb_phy_hx4_config(iproc_usb_data); -+ else if (strstr(match->compatible, "sb2")) -+ ret = iproc_usb_phy_sb2_config(iproc_usb_data); -+#if !defined(CONFIG_MACH_GH2) -+ else -+ ret = iproc_usb_phy_gh_config(iproc_usb_data); -+#endif -+ -+ /* Enable clock to USBD and get the USBD out of reset */ -+ val = readl_relaxed(USB2D_IDM_IDM_IO_CONTROL_DIRECT_ADDR(iproc_usb_data->idm_base)); -+ val |= (1 << USB2D_IDM_IDM_IO_CONTROL_DIRECT__clk_enable); -+ writel_relaxed(val, USB2D_IDM_IDM_IO_CONTROL_DIRECT_ADDR(iproc_usb_data->idm_base)); -+ -+ mdelay(10); -+ val = readl_relaxed(USB2D_IDM_IDM_RESET_CONTROL_ADDR(iproc_usb_data->idm_base)); -+ val &= ~(1 << USB2D_IDM_IDM_RESET_CONTROL__RESET); -+ writel_relaxed(val, USB2D_IDM_IDM_RESET_CONTROL_ADDR(iproc_usb_data->idm_base)); -+ -+#if defined(CONFIG_MACH_GH2) -+ /* In GH2, it must init PHY after RESET */ -+ mdelay(100); -+ ret = iproc_usb_phy_gh_config(iproc_usb_data); -+#endif -+ -+ return ret; -+} -+ -+static int xgs_iproc_usb_phy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *dn = pdev->dev.of_node; -+ struct iproc_usb_priv *iproc_usb_data; -+ int gpio_pin; -+ enum of_gpio_flags flags; -+ u32 gpio_active_low; -+ u32 __maybe_unused val; -+ int ret, usb_mode; -+ -+ if (!of_device_is_available(dn)) -+ return -ENODEV; -+ -+ iproc_usb_data = devm_kzalloc(dev, sizeof(*iproc_usb_data), GFP_KERNEL); -+ if (!iproc_usb_data) { -+ dev_err(dev, "devm_kzalloc() failed\n" ); -+ return -ENOMEM; -+ } -+ memset(iproc_usb_data, 0, sizeof(*iproc_usb_data)); -+ platform_set_drvdata(pdev, iproc_usb_data); -+ -+ iproc_usb_data->dev = dev; -+ iproc_usb_data->dn = dn; -+ -+ iproc_usb_data->wrap_base = get_iproc_wrap_ctrl_base(); -+ if (!iproc_usb_data->wrap_base) { -+ dev_err(&pdev->dev, "can't iomap usb phy base address\n"); -+ ret = -ENOMEM; -+ goto err1; -+ } -+ -+ gpio_pin = of_get_named_gpio_flags(dn, "vbus-gpio", 0, &flags); -+ -+ if (gpio_pin < 0) { -+ dev_err(&pdev->dev, "Error: no gpio pin set for USB power\n"); -+ return gpio_pin; -+ } -+ -+ gpio_active_low = flags & OF_GPIO_ACTIVE_LOW; -+ -+ ret = gpio_request(gpio_pin, "usbphy-vbus"); -+ if (ret != 0) { -+ dev_err(dev, "request gpio #%d error.\n", gpio_pin); -+ goto err1; -+ } -+ -+ usb_mode = xgs_iproc_usb_phy_mode(iproc_usb_data); -+ -+ iproc_usb_data->usb_mode = usb_mode; -+ iproc_usb_data->phy.dev = dev; -+ iproc_usb_data->phy.flags = usb_mode; -+ iproc_usb_data->phy.init = iproc_usb_phy_init; -+ iproc_usb_data->phy.type = USB_PHY_TYPE_USB2; -+ -+ if (usb_mode == IPROC_USB_MODE_DEVICE) { -+ iproc_usb_data->idm_base = (void *)of_iomap(dn, 1); -+ if (!iproc_usb_data->idm_base) { -+ dev_err(&pdev->dev, "can't iomap usb2d idm base address 1\n"); -+ ret = -ENOMEM; -+ goto err2; -+ } -+ -+ gpio_direction_input(gpio_pin); -+ } else { -+ -+#if defined(CONFIG_MACH_GH2) -+ USBH_Utmi_base = (void *)of_iomap(dn, 2); -+ if (!USBH_Utmi_base) { -+ dev_err(&pdev->dev, "can't iomap usb2h idm base address 2\n"); -+ ret = -ENOMEM; -+ goto err2; -+ } -+#endif -+ iproc_usb_data->idm_base = (void *)of_iomap(dn, 0); -+ if (!iproc_usb_data->idm_base) { -+ dev_err(&pdev->dev, "can't iomap usb2h idm base address 0\n"); -+ ret = -ENOMEM; -+ goto err2; -+ } -+ -+ gpio_direction_output(gpio_pin, 1); -+ -+ /*turn off the power: if active low for power, then set 1 to turn off*/ -+ if (gpio_active_low) -+ __gpio_set_value(gpio_pin, 1); -+ else -+ __gpio_set_value(gpio_pin, 0); -+ -+ /* -+ Initial usb phy for usb host mode. For the device mode, -+ the iproc_usb_phy_init will be called when usb udc start. -+ */ -+ ret = iproc_usb_phy_init(&iproc_usb_data->phy); -+ if (ret < 0) -+ goto err2; -+ } -+ -+ ret = usb_add_phy_dev(&iproc_usb_data->phy); -+ if (ret) -+ goto err2; -+ -+ /* supply power for USB device connected to the host */ -+ if (usb_mode != IPROC_USB_MODE_DEVICE) { -+ if (gpio_active_low) -+ __gpio_set_value(gpio_pin, 0); -+ else -+ __gpio_set_value(gpio_pin, 1); -+ } -+ gpio_free(gpio_pin); -+ -+ return 0; -+ -+err2: -+ gpio_free(gpio_pin); -+err1: -+ if (iproc_usb_data->idm_base) { -+ iounmap(iproc_usb_data->idm_base); -+ } -+ if (iproc_usb_data) { -+ iounmap(iproc_usb_data); -+ } -+#if defined(CONFIG_MACH_GH2) -+ if (USBH_Utmi_base) { -+ iounmap(USBH_Utmi_base); -+ USBH_Utmi_base = NULL; -+ } -+#endif -+ return ret; -+} -+ -+static int xgs_iproc_usb_phy_remove(struct platform_device *pdev) -+{ -+ struct iproc_usb_priv *iproc_usb_data = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ if (iproc_usb_data->idm_base) { -+ iounmap(iproc_usb_data->idm_base); -+ usb_remove_phy(&iproc_usb_data->phy); -+ } -+ -+ if (iproc_usb_data) -+ iounmap(iproc_usb_data); -+ -+#if defined(CONFIG_MACH_GH2) -+ if (USBH_Utmi_base) { -+ iounmap(USBH_Utmi_base); -+ USBH_Utmi_base = NULL; -+ } -+#endif -+ -+ return 0; -+} -+ -+static struct platform_driver xgs_iproc_usb_phy_driver = -+{ -+ .driver = { -+ .name = "usb-phy", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(xgs_iproc_usb_phy_dt_ids), -+ }, -+ .probe = xgs_iproc_usb_phy_probe, -+ .remove = xgs_iproc_usb_phy_remove, -+}; -+ -+module_platform_driver(xgs_iproc_usb_phy_driver); -+ -+MODULE_AUTHOR("Broadcom"); -+MODULE_DESCRIPTION("Broadcom USB phy driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig ---- a/drivers/watchdog/Kconfig 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/watchdog/Kconfig 2017-11-09 17:54:04.039439000 +0800 -@@ -578,6 +578,14 @@ config LPC18XX_WATCHDOG - To compile this driver as a module, choose M here: the - module will be called lpc18xx_wdt. - -+config XGS_IPROC_SP805_WDT -+ tristate "BRCM XGS iProc watchdog based on SP805" -+ depends on (ARCH_XGS_IPROC || COMPILE_TEST) -+ select WATCHDOG_CORE -+ help -+ Say Y here to include support for the watchdog timer -+ embedded in BRCM XGS iProc SoCs. -+ - # AVR32 Architecture - - config AT32AP700X_WDT -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile ---- a/drivers/watchdog/Makefile 2016-12-16 00:49:34.000000000 +0800 -+++ b/drivers/watchdog/Makefile 2017-11-09 17:54:04.040435000 +0800 -@@ -69,6 +69,7 @@ obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_w - obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o - obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o - obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o -+obj-$(CONFIG_XGS_IPROC_SP805_WDT) += xgs_iproc_sp805_wdt.o - - # AVR32 Architecture - obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/drivers/watchdog/xgs_iproc_sp805_wdt.c b/drivers/watchdog/xgs_iproc_sp805_wdt.c ---- a/drivers/watchdog/xgs_iproc_sp805_wdt.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/watchdog/xgs_iproc_sp805_wdt.c 2017-11-09 17:54:04.252451000 +0800 -@@ -0,0 +1,381 @@ -+/* -+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* default timeout in seconds */ -+#define DEFAULT_TIMEOUT 60 -+ -+#define MODULE_NAME "iproc-sp805-wdt" -+ -+/* watchdog register offsets and masks */ -+#define WDTLOAD 0x000 -+ #define LOAD_MIN 0x00000001 -+ #define LOAD_MAX 0xFFFFFFFF -+#define WDTVALUE 0x004 -+#define WDTCONTROL 0x008 -+ /* control register masks */ -+ #define INT_ENABLE (1 << 0) -+ #define RESET_ENABLE (1 << 1) -+#define WDTINTCLR 0x00C -+#define WDTRIS 0x010 -+#define WDTMIS 0x014 -+ #define INT_MASK (1 << 0) -+#define WDTLOCK 0xC00 -+ #define UNLOCK 0x1ACCE551 -+ #define LOCK 0x00000001 -+ -+/** -+ * struct sp805_wdt: sp805 wdt device structure -+ * @wdd: instance of struct watchdog_device -+ * @lock: spin lock protecting dev structure and io access -+ * @base: base address of wdt -+ * @clk: clock structure of wdt -+ * @adev: amba device structure of wdt -+ * @load_val: load value to be set for current timeout -+ */ -+struct sp805_wdt { -+ struct watchdog_device wdd; -+ spinlock_t lock; -+ void __iomem *base; -+ struct clk *clk; -+ struct amba_device *adev; -+ unsigned int load_val; -+}; -+ -+static bool nowayout = WATCHDOG_NOWAYOUT; -+module_param(nowayout, bool, 0); -+MODULE_PARM_DESC(nowayout, -+ "Set to 1 to keep watchdog running after device release"); -+ -+/* This routine get boot status to indicate if the last boot is from WDT */ -+static unsigned int wdt_get_clear_bootstatus( -+ void __iomem *wdt_bootstatus, -+ unsigned int wdt_bootstatus_bit) -+{ -+ unsigned int reg; -+ unsigned int bootstatus = 0; -+ -+ reg = readl_relaxed(wdt_bootstatus); -+ bootstatus = reg & (1 << wdt_bootstatus_bit); -+ -+ if (bootstatus) -+ /* write 1 to clear boot status bit */ -+ writel_relaxed(reg, wdt_bootstatus); -+ -+ return bootstatus; -+} -+ -+/* This routine finds load value that will reset system in required timout */ -+static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) -+{ -+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); -+ u64 load, rate; -+ -+ rate = clk_get_rate(wdt->clk); -+ -+ /* -+ * sp805 runs counter with given value twice, after the end of first -+ * counter it gives an interrupt and then starts counter again. If -+ * interrupt already occurred then it resets the system. This is why -+ * load is half of what should be required. -+ */ -+ load = div_u64(rate, 2) * timeout - 1; -+ -+ load = (load > LOAD_MAX) ? LOAD_MAX : load; -+ load = (load < LOAD_MIN) ? LOAD_MIN : load; -+ -+ spin_lock(&wdt->lock); -+ wdt->load_val = load; -+ /* roundup timeout to closest positive integer value */ -+ wdd->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); -+ spin_unlock(&wdt->lock); -+ -+ return 0; -+} -+ -+/* returns number of seconds left for reset to occur */ -+static unsigned int wdt_timeleft(struct watchdog_device *wdd) -+{ -+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); -+ u64 load, rate; -+ -+ rate = clk_get_rate(wdt->clk); -+ -+ spin_lock(&wdt->lock); -+ load = readl_relaxed(wdt->base + WDTVALUE); -+ -+ /* If the interrupt is inactive then time left is WDTValue + WDTLoad. */ -+ if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK)) -+ load += wdt->load_val + 1; -+ spin_unlock(&wdt->lock); -+ -+ return div_u64(load, rate); -+} -+ -+static int wdt_config(struct watchdog_device *wdd, bool ping) -+{ -+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); -+ int ret; -+ -+ if (!ping) { -+ ret = clk_prepare(wdt->clk); -+ if (ret) { -+ dev_err(&wdt->adev->dev, "clock prepare fail"); -+ return ret; -+ } -+ -+ ret = clk_enable(wdt->clk); -+ if (ret) { -+ dev_err(&wdt->adev->dev, "clock enable fail"); -+ clk_unprepare(wdt->clk); -+ return ret; -+ } -+ } -+ -+ spin_lock(&wdt->lock); -+ -+ writel_relaxed(UNLOCK, wdt->base + WDTLOCK); -+ writel_relaxed(wdt->load_val, wdt->base + WDTLOAD); -+ writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); -+ -+ if (!ping) -+ writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + -+ WDTCONTROL); -+ -+ writel_relaxed(LOCK, wdt->base + WDTLOCK); -+ -+ /* Flush posted writes. */ -+ readl_relaxed(wdt->base + WDTLOCK); -+ spin_unlock(&wdt->lock); -+ -+ return 0; -+} -+ -+static int wdt_ping(struct watchdog_device *wdd) -+{ -+ return wdt_config(wdd, true); -+} -+ -+/* enables watchdog timers reset */ -+static int wdt_enable(struct watchdog_device *wdd) -+{ -+ return wdt_config(wdd, false); -+} -+ -+/* disables watchdog timers reset */ -+static int wdt_disable(struct watchdog_device *wdd) -+{ -+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); -+ -+ spin_lock(&wdt->lock); -+ -+ writel_relaxed(UNLOCK, wdt->base + WDTLOCK); -+ writel_relaxed(0, wdt->base + WDTCONTROL); -+ writel_relaxed(LOCK, wdt->base + WDTLOCK); -+ -+ /* Flush posted writes. */ -+ readl_relaxed(wdt->base + WDTLOCK); -+ spin_unlock(&wdt->lock); -+ -+ clk_disable(wdt->clk); -+ clk_unprepare(wdt->clk); -+ -+ return 0; -+} -+ -+static const struct watchdog_info wdt_info = { -+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -+ .identity = MODULE_NAME, -+}; -+ -+static const struct watchdog_ops wdt_ops = { -+ .owner = THIS_MODULE, -+ .start = wdt_enable, -+ .stop = wdt_disable, -+ .ping = wdt_ping, -+ .set_timeout = wdt_setload, -+ .get_timeleft = wdt_timeleft, -+}; -+ -+static int sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) -+{ -+ struct sp805_wdt *wdt; -+ int ret; -+ struct device_node *dnode = adev->dev.of_node; -+ void __iomem *wdt_bootstatus = NULL; -+ unsigned int bootstatus_bit = 0; -+ -+ wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); -+ if (!wdt) { -+ dev_err(&adev->dev, "Kzalloc failed\n"); -+ ret = -ENOMEM; -+ goto error1; -+ } -+ -+ wdt->base = of_iomap(dnode, 0); -+ if (!wdt->base) { -+ ret = -ENOMEM; -+ dev_err(&adev->dev, "of_iomap failed\n"); -+ goto error2; -+ } -+ -+ wdt_bootstatus = of_iomap(dnode, 1); -+ if (!wdt_bootstatus) { -+ ret = -ENOMEM; -+ dev_err(&adev->dev, "of_iomap failed\n"); -+ goto error2; -+ } -+ -+ wdt->clk = of_clk_get(dnode, 0); -+ if (IS_ERR(wdt->clk)) { -+ dev_err(&adev->dev, "Clock not found\n"); -+ ret = PTR_ERR(wdt->clk); -+ goto error2; -+ } -+ -+ wdt->adev = adev; -+ wdt->wdd.info = &wdt_info; -+ wdt->wdd.ops = &wdt_ops; -+ -+ spin_lock_init(&wdt->lock); -+ watchdog_set_nowayout(&wdt->wdd, nowayout); -+ watchdog_set_drvdata(&wdt->wdd, wdt); -+ wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT); -+ -+ ret = watchdog_register_device(&wdt->wdd); -+ if (ret) { -+ dev_err(&adev->dev, "watchdog_register_device() failed: %d\n", -+ ret); -+ goto error3; -+ } -+ -+ amba_set_drvdata(adev, wdt); -+ -+ ret = of_property_read_u32(dnode, "wdt_boot_status_bit", -+ &bootstatus_bit); -+ if (ret) { -+ dev_err(&adev->dev, "failed getting DT bootstatus bit\n"); -+ goto error3; -+ } -+ -+ wdt->wdd.bootstatus = wdt_get_clear_bootstatus( -+ wdt_bootstatus, -+ bootstatus_bit); -+ -+ dev_info(&adev->dev, "registration successful\n"); -+ dev_info(&adev->dev, "timeout=%d sec, nowayout=%d\n", -+ DEFAULT_TIMEOUT, nowayout); -+ -+ return 0; -+ -+error3: -+ clk_put(wdt->clk); -+ -+error2: -+ if (wdt->base) -+ iounmap(wdt->base); -+ if (wdt_bootstatus) -+ iounmap(wdt_bootstatus); -+ kfree(wdt); -+ -+error1: -+ dev_err(&adev->dev, "Probe Failed!!!\n"); -+ -+ return ret; -+} -+ -+static int sp805_wdt_remove(struct amba_device *adev) -+{ -+ struct sp805_wdt *wdt = amba_get_drvdata(adev); -+ -+ watchdog_unregister_device(&wdt->wdd); -+ amba_set_drvdata(adev, NULL); -+ watchdog_set_drvdata(&wdt->wdd, NULL); -+ clk_put(wdt->clk); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int sp805_wdt_suspend(struct device *dev) -+{ -+ struct sp805_wdt *wdt = dev_get_drvdata(dev); -+ -+ if (watchdog_active(&wdt->wdd)) -+ return wdt_disable(&wdt->wdd); -+ -+ return 0; -+} -+ -+static int sp805_wdt_resume(struct device *dev) -+{ -+ struct sp805_wdt *wdt = dev_get_drvdata(dev); -+ -+ if (watchdog_active(&wdt->wdd)) -+ return wdt_enable(&wdt->wdd); -+ -+ return 0; -+} -+#endif /* CONFIG_PM */ -+ -+static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend, -+ sp805_wdt_resume); -+ -+static struct amba_id sp805_wdt_ids[] = { -+ { -+ .id = 0x00141805, -+ .mask = 0x00ffffff, -+ }, -+ { 0, 0 }, -+}; -+MODULE_DEVICE_TABLE(amba, sp805_wdt_ids); -+ -+static struct amba_driver sp805_wdt_driver = { -+ .drv = { -+ .name = MODULE_NAME, -+ .pm = &sp805_wdt_dev_pm_ops, -+ }, -+ .id_table = sp805_wdt_ids, -+ .probe = sp805_wdt_probe, -+ .remove = sp805_wdt_remove, -+}; -+ -+module_amba_driver(sp805_wdt_driver); -+ -+MODULE_AUTHOR("Viresh Kumar "); -+MODULE_DESCRIPTION("ARM SP805 Watchdog Driver"); -+MODULE_LICENSE("GPL"); -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h ---- a/include/linux/mtd/spi-nor.h 2016-12-16 00:49:34.000000000 +0800 -+++ b/include/linux/mtd/spi-nor.h 2017-11-09 17:54:11.415490000 +0800 -@@ -183,6 +183,9 @@ struct spi_nor { - int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); - - void *priv; -+#ifdef CONFIG_M25PXX_STAY_IN_3BYTE_MODE -+ void *priv1; -+#endif - }; - - /** -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/include/linux/soc/bcm/xgs-iproc-wrap-idm-dmu.h b/include/linux/soc/bcm/xgs-iproc-wrap-idm-dmu.h ---- a/include/linux/soc/bcm/xgs-iproc-wrap-idm-dmu.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/include/linux/soc/bcm/xgs-iproc-wrap-idm-dmu.h 2017-11-09 17:54:12.456502000 +0800 -@@ -0,0 +1,15 @@ -+/* -+ * $Copyright Open Broadcom Corporation$ -+ */ -+ -+#ifndef XGS_IPROC_WRAP_IDM_DMU_H -+#define XGS_IPROC_WRAP_IDM_DMU_H -+ -+extern int xgs_iproc_wrap_idm_dmu_base_reg_setup(void); -+extern void xgs_iproc_idm_timeout_handler_setup(void); -+extern void __iomem *get_iproc_wrap_ctrl_base(void); -+extern void __iomem *get_iproc_dmu_pcu_base(void); -+extern void __iomem *get_iproc_idm_base(int index); -+extern void __iomem *get_iproc_idm_base_phys(int index); -+ -+#endif -diff -uprN -EbwB --no-dereference -X /projects/ntsw-sw7/home/chena/TEMP/XLDK_releasebuild12/INTERNAL/release/tools/dontdiff a/include/linux/usb/iproc_usb.h b/include/linux/usb/iproc_usb.h ---- a/include/linux/usb/iproc_usb.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/include/linux/usb/iproc_usb.h 2017-11-09 17:54:12.826524000 +0800 -@@ -0,0 +1,20 @@ -+/* -+ * iproc_usb.h -- USB defines for XGS IPROC USB drivers -+ * -+ * Copyright (C) 2015 Broadcom Limited. -+ * -+ * This software is distributed under the terms of the GNU General -+ * Public License ("GPL") as published by the Free Software Foundation, -+ * version 2 of that License. -+ */ -+ -+#ifndef __LINUX_USB_IPROC_USB_H -+#define __LINUX_USB_IPROC_USB_H -+ -+/* USB Flags */ -+ -+#define IPROC_USB_MODE_HOST (0) -+#define IPROC_USB_MODE_DEVICE (1) -+ -+#endif /* __LINUX_USB_IPROC_USB_H */ -+ diff --git a/packages/base/any/kernels/4.4-lts/patches/series b/packages/base/any/kernels/4.4-lts/patches/series deleted file mode 100644 index db86ea76..00000000 --- a/packages/base/any/kernels/4.4-lts/patches/series +++ /dev/null @@ -1 +0,0 @@ -kernel-4.4-brcm-iproc.patch diff --git a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config index 4ad12b30..2a376cc8 100644 --- a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.9.75 Kernel Configuration +# Linux/x86 4.9.75 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -2273,7 +2273,7 @@ CONFIG_PTP_1588_CLOCK=y CONFIG_GPIOLIB=y CONFIG_GPIO_ACPI=y # CONFIG_DEBUG_GPIO is not set -# CONFIG_GPIO_SYSFS is not set +CONFIG_GPIO_SYSFS=y # # Memory mapped GPIO drivers @@ -2301,7 +2301,7 @@ CONFIG_GPIO_ACPI=y # CONFIG_GPIO_ADP5588 is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCA953X is not set +CONFIG_GPIO_PCA953X=m # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_TPIC2810 is not set @@ -2504,7 +2504,7 @@ CONFIG_SENSORS_UCD9200=y # CONFIG_SENSORS_THMC50 is not set CONFIG_SENSORS_TMP102=y # CONFIG_SENSORS_TMP103 is not set -# CONFIG_SENSORS_TMP401 is not set +CONFIG_SENSORS_TMP401=m # CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_VIA_CPUTEMP is not set # CONFIG_SENSORS_VIA686A is not set @@ -3880,7 +3880,7 @@ CONFIG_RAS=y # # CONFIG_ANDROID is not set # CONFIG_LIBNVDIMM is not set -CONFIG_NVMEM=m +CONFIG_NVMEM=y # CONFIG_STM is not set # CONFIG_INTEL_TH is not set diff --git a/packages/base/any/kernels/modules/accton_i2c_psu.c b/packages/base/any/kernels/modules/accton_i2c_psu.c new file mode 100755 index 00000000..89b54748 --- /dev/null +++ b/packages/base/any/kernels/modules/accton_i2c_psu.c @@ -0,0 +1,580 @@ +/* + * An hwmon driver for the Accton Redundant Power Module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" +/* PMBus Protocol. */ +#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 +#define PMBUS_REGISTER_VOUT_MODE 0x20 +#define PMBUS_REGISTER_STATUS_BYTE 0x78 +#define PMBUS_REGISTER_STATUS_WORD 0x79 +#define PMBUS_REGISTER_STATUS_FAN 0x81 +#define PMBUS_REGISTER_READ_VIN 0x88 +#define PMBUS_REGISTER_READ_IIN 0x89 +#define PMBUS_REGISTER_READ_VOUT 0x8B +#define PMBUS_REGISTER_READ_IOUT 0x8C +#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D +#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E +#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F +#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 +#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 + +#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A +#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B + +#define PMBUS_REGISTER_READ_POUT 0x96 +#define PMBUS_REGISTER_READ_PIN 0x97 +#define PMBUS_REGISTER_MFR_ID 0x99 +#define PMBUS_REGISTER_MFR_MODEL 0x9A +#define PMBUS_REGISTER_MFR_REVISION 0x9B +#define PMBUS_REGISTER_MFR_SERIAL 0x9E + + +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct accton_i2c_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u8 mfr_serial[26]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); + +enum accton_i2c_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_SERIAL, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + +static struct attribute *accton_i2c_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 0; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + if(!multiplier) + multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; + + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + int exponent, mantissa; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : + sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); +} + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + switch (attr->index) { + + case PSU_MFR_ID: + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: + ptr = data->mfr_revsion; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + + +static const struct attribute_group accton_i2c_psu_group = { + .attrs = accton_i2c_psu_attributes, +}; + +static int accton_i2c_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct accton_i2c_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int accton_i2c_psu_remove(struct i2c_client *client) +{ + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); + kfree(data); + + return 0; +} +/* Support psu moduel + */ +static const struct i2c_device_id accton_i2c_psu_id[] = { + { "acbel_fsh082", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); + +static struct i2c_driver accton_i2c_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_psu", + }, + .probe = accton_i2c_psu_probe, + .remove = accton_i2c_psu_remove, + .id_table = accton_i2c_psu_id, + .address_list = normal_i2c, +}; + +static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) +{ + int status = -EIO; + int length; + u8 buffer[128] = {0}, *ptr = buffer; + + status = accton_i2c_psu_read_byte(client, command); + if (status < 0) + { + dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + + status = (status & 0xFF) + 1; + if ( status > 128) + { + dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); + status = -EINVAL; + goto EXIT_READ_BLOCK_DATA; + } + + length = status; + status = accton_i2c_psu_read_block(client, command, buffer, length); + if (unlikely(status < 0)) + goto EXIT_READ_BLOCK_DATA; + if (unlikely(status != length)) { + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + /* The first byte is the count byte of string. */ + ptr++; + status--; + + length=status>(data_length-1)?(data_length-1):status; + memcpy(data, ptr, length); + data[length-1] = 0; + +EXIT_READ_BLOCK_DATA: + + return status; +} + + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status, length; + u8 command, buf; + struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, + {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, + {PMBUS_REGISTER_READ_VOUT, &data->v_out}, + {PMBUS_REGISTER_READ_IIN, &data->i_in}, + {PMBUS_REGISTER_READ_IOUT, &data->i_out}, + {PMBUS_REGISTER_READ_POUT, &data->p_out}, + {PMBUS_REGISTER_READ_PIN, &data->p_in}, + {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, + {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, + {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, + }; + + dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = accton_i2c_psu_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + + } + /* Read mfr_id */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, + ARRAY_SIZE(data->mfr_id)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); + goto exit; + } + /* Read mfr_model */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, + ARRAY_SIZE(data->mfr_model)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); + goto exit; + } + /* Read mfr_revsion */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); + goto exit; + } + /* Read mfr_serial */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, + ARRAY_SIZE(data->mfr_serial)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init accton_i2c_psu_init(void) +{ + return i2c_add_driver(&accton_i2c_psu_driver); +} + +static void __exit accton_i2c_psu_exit(void) +{ + i2c_del_driver(&accton_i2c_psu_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_psu_init); +module_exit(accton_i2c_psu_exit); diff --git a/packages/base/any/kernels/modules/dps850.c b/packages/base/any/kernels/modules/dps850.c new file mode 100755 index 00000000..41d742d7 --- /dev/null +++ b/packages/base/any/kernels/modules/dps850.c @@ -0,0 +1,509 @@ +/* + * An hwmon driver for the Delta DPS-850AB-4 Power Module + * + * 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 +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +enum chips { + DPS850 +}; + +/* Each client has this additional data + */ +struct dps850_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 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[3]; /* Register value */ + u16 fan_speed; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_serial[16]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_vout_by_mode(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 dps850_data *dps850_update_device(struct device *dev); +static int dps850_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum dps850_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out,S_IRUGO, show_vout_by_mode,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_temp2_input, S_IRUGO, show_linear, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, show_linear, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + +static struct attribute *dps850_attributes[] = { + &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_v_in.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_temp2_input.dev_attr.attr, + &sensor_dev_attr_psu_temp3_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.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 show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct dps850_data *data = dps850_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + case PSU_TEMP2_INPUT: + case PSU_TEMP3_INPUT: + value = data->temp_input[attr->index-PSU_TEMP1_INPUT]; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + 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_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct dps850_data *data = dps850_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model + 1; /* The first byte is the length of string. */ + break; + case PSU_MFR_SERIAL: /* psu_mfr_serial */ + ptr = data->mfr_serial + 1; /* The first byte is the length 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 dps850_data *data = dps850_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 const struct attribute_group dps850_group = { + .attrs = dps850_attributes, +}; + +static int dps850_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct dps850_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 dps850_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, &dps850_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, &dps850_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int dps850_remove(struct i2c_client *client) +{ + struct dps850_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps850_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id dps850_id[] = { + { "dps850", DPS850 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps850_id); + +static struct i2c_driver dps850_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps850", + }, + .probe = dps850_probe, + .remove = dps850_remove, + .id_table = dps850_id, + .address_list = normal_i2c, +}; + +static int dps850_read_byte(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 dps850_read_word(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_word_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int dps850_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_word_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int dps850_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps850_data *dps850_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps850_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[] = { {0x20, &data->vout_mode}}; + 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])}, + {0x8f, &(data->temp_input[2])}, + {0x90, &data->fan_speed}}; + + dev_dbg(&client->dev, "Starting dps850 update\n"); + data->valid = 0; + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps850_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 = dps850_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 mfr_model */ + command = 0x9a; + length = 1; + memset(data->mfr_model, 0, sizeof(data->mfr_model)); + + /* Read first byte to determine the length of data */ + status = dps850_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = dps850_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_serial */ + command = 0x9e; + length = 1; + memset(data->mfr_serial, 0, sizeof(data->mfr_serial)); + + /* Read first byte to determine the length of data */ + status = dps850_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = dps850_read_block(client, command, data->mfr_serial, buf+1); + data->mfr_serial[buf+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 dps850_init(void) +{ + return i2c_add_driver(&dps850_driver); +} + +static void __exit dps850_exit(void) +{ + i2c_del_driver(&dps850_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("DELTA DPS-850AB driver"); +MODULE_LICENSE("GPL"); + +module_init(dps850_init); +module_exit(dps850_exit); + diff --git a/packages/base/any/kernels/modules/optoe.c b/packages/base/any/kernels/modules/optoe.c index b3064f02..c22b92a2 100644 --- a/packages/base/any/kernels/modules/optoe.c +++ b/packages/base/any/kernels/modules/optoe.c @@ -660,6 +660,7 @@ static ssize_t optoe_read_write(struct optoe_data *optoe, ssize_t retval; size_t pending_len = 0, chunk_len = 0; loff_t chunk_offset = 0, chunk_start_offset = 0; + loff_t chunk_end_offset = 0; dev_dbg(&client->dev, "%s: off %lld len:%ld, opcode:%s\n", @@ -699,30 +700,30 @@ static ssize_t optoe_read_write(struct optoe_data *optoe, /* * 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 + * 1. start at an offset not equal to 0 (within the chunk) + * and read/write less than the rest of the chunk + * 2. 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) + * 3. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 4. start at offset 0 (within the chunk), and read/write + * the entire chunk */ chunk_start_offset = chunk * OPTOE_PAGE_SIZE; + chunk_end_offset = chunk_start_offset + OPTOE_PAGE_SIZE; if (chunk_start_offset < off) { chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) + if ((off + pending_len) < chunk_end_offset) chunk_len = pending_len; else - chunk_len = OPTOE_PAGE_SIZE - off; + chunk_len = chunk_end_offset - off; } else { chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_PAGE_SIZE; - else + if (pending_len < OPTOE_PAGE_SIZE) chunk_len = pending_len; + else + chunk_len = OPTOE_PAGE_SIZE; } dev_dbg(&client->dev, diff --git a/packages/base/any/kernels/modules/ym2651y.c b/packages/base/any/kernels/modules/ym2651y.c index 649200d2..8e8cc540 100644 --- a/packages/base/any/kernels/modules/ym2651y.c +++ b/packages/base/any/kernels/modules/ym2651y.c @@ -33,705 +33,716 @@ #include #include -#define MAX_FAN_DUTY_CYCLE 100 -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static int support_i2c_block = 1; // 1: support I2C_FUNC_SMBUS_I2C_BLOCK 0: not support /* Addresses scanned */ static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; enum chips { - YM2651, - YM2401, - YM2851, + YM2651, + YM2401, + YM2851, + YM1921, }; /* 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 */ - u8 mfr_serial[20]; /* 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 */ + 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 */ + u8 mfr_serial[20]; /* 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); + char *buf); static ssize_t show_word(struct device *dev, struct device_attribute *da, - char *buf); + char *buf); static ssize_t show_linear(struct device *dev, struct device_attribute *da, - char *buf); + 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); + char *buf); static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, - char *buf); + char *buf); static ssize_t show_ascii(struct device *dev, struct device_attribute *da, - char *buf); + 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); + 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_SERIAL, - 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 + 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_SERIAL, + 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_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_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_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); -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 SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); +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_serial.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 + &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_serial.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) + 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; - } + 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"); + 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) + 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; - } + 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; - } + 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); + 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); + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); - return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; + 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) + 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; + 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; + error = kstrtol(buf, 10, &speed); + if (error) + return error; - if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) - return -EINVAL; + 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); + 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; + return count; } static ssize_t show_linear(struct device *dev, struct device_attribute *da, - char *buf) + char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ym2651y_data *data = ym2651y_update_device(dev); + 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; + 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; - } + 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); + 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)); + 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) + char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ym2651y_data *data = ym2651y_update_device(dev); - u8 shift; + 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; + if (!data->valid) { + return 0; + } + + shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; - return sprintf(buf, "%d\n", data->fan_fault >> shift); + return sprintf(buf, "%d\n", data->fan_fault >> shift); } static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, - char *buf) + char *buf) { - struct ym2651y_data *data = ym2651y_update_device(dev); + struct ym2651y_data *data = ym2651y_update_device(dev); - if (!data->valid) { - return 0; - } - - return sprintf(buf, "%d\n", data->over_temp >> 7); + 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) + char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ym2651y_data *data = ym2651y_update_device(dev); - u8 *ptr = NULL; + 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; - case PSU_MFR_SERIAL: /* psu_mfr_serial */ - ptr = data->mfr_serial + 1; /* The first byte is the count byte of string. */ - break; - default: - return 0; - } + 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; + case PSU_MFR_SERIAL: /* psu_mfr_serial */ + ptr = data->mfr_serial + 1; /* The first byte is the count byte of string. */ + break; + default: + return 0; + } - return sprintf(buf, "%s\n", ptr); + 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; + struct ym2651y_data *data = ym2651y_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; - if (!data->valid) { - return 0; - } + if (!data->valid) { + return 0; + } - exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); - mantissa = data->v_out; + 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)); + 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); + 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); - } + if (data->chip == YM2401) { + return show_vout_by_mode(dev, da, buf); + } - return show_linear(dev, da, buf); + return show_linear(dev, da, buf); } static const struct attribute_group ym2651y_group = { - .attrs = ym2651y_attributes, + .attrs = ym2651y_attributes, }; static int ym2651y_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) + const struct i2c_device_id *dev_id) { - struct ym2651y_data *data; - int status; + 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; - } + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA )) { + status = -EIO; + goto exit; + } + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) { + support_i2c_block = 0; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + 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"); - 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; + } - /* 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; + } - 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); - dev_info(&client->dev, "%s: psu '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; + return 0; exit_remove: - sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); exit_free: - kfree(data); + kfree(data); exit: - return status; + return status; } static int ym2651y_remove(struct i2c_client *client) { - struct ym2651y_data *data = i2c_get_clientdata(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); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); - return 0; + return 0; } static const struct i2c_device_id ym2651y_id[] = { - { "ym2651", YM2651 }, - { "ym2401", YM2401 }, - { "ym2851", YM2851 }, - {} + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + { "ym2851", YM2851 }, + { "ym1921", YM1921 }, + {} }; 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, + .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) { - int status = 0, retry = I2C_RW_RETRY_COUNT; + 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; - } + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } - break; - } + break; + } return status; } static int ym2651y_read_word(struct i2c_client *client, u8 reg) { - int status = 0, retry = I2C_RW_RETRY_COUNT; + int status = 0, retry = I2C_RW_RETRY_COUNT; - while (retry) { - status = i2c_smbus_read_word_data(client, reg); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } + while (retry) { + status = i2c_smbus_read_word_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } - break; - } + break; + } return status; } static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) { - int status = 0, retry = I2C_RW_RETRY_COUNT; + int status = 0, retry = I2C_RW_RETRY_COUNT; - while (retry) { - status = i2c_smbus_write_word_data(client, reg, value); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } + while (retry) { + status = i2c_smbus_write_word_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } - break; - } + break; + } return status; } static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, - int data_len) + int data_len) { - int status = 0, retry = I2C_RW_RETRY_COUNT; + int status = 0, retry = I2C_RW_RETRY_COUNT; - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } + 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; - } + break; + } return status; } struct reg_data_byte { - u8 reg; - u8 *value; + u8 reg; + u8 *value; }; struct reg_data_word { - u8 reg; - u16 *value; + 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); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); - mutex_lock(&data->update_lock); + 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}}; + 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; + 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); + /* 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; - } - } + 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); + /* 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; - } - } + 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 (support_i2c_block) { + + /* 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; - } + 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; - } - - /* Read mfr_serial */ - command = 0x9e; - status = ym2651y_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); - goto exit; - } - - data->last_updated = jiffies; - data->valid = 1; - } + /* 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; + } + + /* Read mfr_serial */ + command = 0x9e; + status = ym2651y_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); + goto exit; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } exit: - mutex_unlock(&data->update_lock); + mutex_unlock(&data->update_lock); - return data; + return data; } static int __init ym2651y_init(void) { - return i2c_add_driver(&ym2651y_driver); + return i2c_add_driver(&ym2651y_driver); } static void __exit ym2651y_exit(void) { - i2c_del_driver(&ym2651y_driver); + i2c_del_driver(&ym2651y_driver); } MODULE_AUTHOR("Brandon Chuang "); diff --git a/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h b/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h index 7a3c92e1..66184704 100644 --- a/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h +++ b/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h @@ -206,7 +206,7 @@ void onlp_api_unlock(void); ONLP_API_T1(_name); \ ONLP_LOCKED_API_NAME(_name) (_v1, _v2, _v3); \ ONLP_API_UNLOCK(); \ - ONLP_API_T2_(name); \ + ONLP_API_T2(name); \ } #define ONLP_LOCKED_VAPI4(_name, _t1, _v1, _t2, _v2, _t3, _v3, _t4, _v4) \ diff --git a/packages/base/any/onlp/src/onlplib/module/src/file.c b/packages/base/any/onlp/src/onlplib/module/src/file.c index df73165c..622295a3 100644 --- a/packages/base/any/onlp/src/onlplib/module/src/file.c +++ b/packages/base/any/onlp/src/onlplib/module/src/file.c @@ -62,12 +62,12 @@ ds_connect__(const char* path) if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { /* - * Set blocking with a 1 second timeout on all domain socket read/write operations. + * Set blocking with a 5 second timeout on all domain socket read/write operations. */ struct timeval tv; fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); - tv.tv_sec = 1; + tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); return fd; diff --git a/packages/base/any/templates/platform-config-platform.yml b/packages/base/any/templates/platform-config-platform.yml index a053373f..ece4c088 100644 --- a/packages/base/any/templates/platform-config-platform.yml +++ b/packages/base/any/templates/platform-config-platform.yml @@ -18,6 +18,7 @@ common: maintainer: support@bigswitch.com support: opennetworklinux@googlegroups.com changelog: None + dists: $DISTS packages: - name: onl-platform-config-$PLATFORM diff --git a/packages/base/armel/kernels/kernel-3.2-lts-arm-iproc-all/PKG.yml b/packages/base/armel/kernels/kernel-3.2-lts-arm-iproc-all/PKG.yml index 45503a7f..ab016a9f 100644 --- a/packages/base/armel/kernels/kernel-3.2-lts-arm-iproc-all/PKG.yml +++ b/packages/base/armel/kernels/kernel-3.2-lts-arm-iproc-all/PKG.yml @@ -5,6 +5,7 @@ common: copyright: Copyright 2013, 2014, 2015 Big Switch Networks maintainer: support@bigswitch.com support: opennetworklinux@googlegroups.com + dists: jessie packages: - name: onl-kernel-3.2-lts-arm-iproc-all diff --git a/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/Makefile b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/PKG.yml b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/PKG.yml new file mode 100644 index 00000000..4ff5b41f --- /dev/null +++ b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/kernels/lts/APKG.yml VERSION=4.14 ARCH=armel CONFIG=armel-iproc-all diff --git a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/builds/.gitignore b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/builds/.gitignore similarity index 100% rename from packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/builds/.gitignore rename to packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/builds/.gitignore diff --git a/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/builds/Makefile b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/builds/Makefile new file mode 100644 index 00000000..023ecdb6 --- /dev/null +++ b/packages/base/armel/kernels/kernel-4.14-lts-armel-iproc-all/builds/Makefile @@ -0,0 +1,5 @@ +KERNEL_BUILD_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +KERNEL_ARCH := arm +KERNEL_LTS_VERSION := 4.14 +KERNEL_CONFIG := armel-iproc-all +include $(ONL)/packages/base/any/kernels/lts/builds/Makefile diff --git a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/PKG.yml b/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/PKG.yml deleted file mode 100644 index 1d1f5758..00000000 --- a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/PKG.yml +++ /dev/null @@ -1,18 +0,0 @@ - -common: - arch: armel - version: 1.0.0 - copyright: Copyright 2013, 2014, 2015 Big Switch Networks - maintainer: support@bigswitch.com - support: opennetworklinux@googlegroups.com - -packages: - - name: onl-kernel-4.4-lts-arm-iproc-all - version: 1.0.0 - summary: Open Network Linux Kernel 4.4-LTS for ARM Integrated Processor Platforms. - - files: - builds/kernel-4.4-lts-arm-iproc-all.bin.gz : $$PKG_INSTALL/ - builds/linux-4.4.*-mbuild : $$PKG_INSTALL/mbuilds - - changelog: Change changes changes., diff --git a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/builds/Makefile b/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/builds/Makefile deleted file mode 100644 index 642762a8..00000000 --- a/packages/base/armel/kernels/kernel-4.4-lts-arm-iproc-all/builds/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -*- Makefile -*- -############################################################ -# -# -# Copyright 2013, 2014 BigSwitch Networks, Inc. -# -# -# -# -############################################################ -THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) - -include $(ONL)/make/config.mk - -#export MODSYNCLIST_EXTRA := arch/arm/plat-iproc/include - -kernel: - $(MAKE) -C $(ONL)/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all K_TARGET_DIR=$(THIS_DIR) $(ONL_MAKE_PARALLEL) - -clean: - rm -rf kernel-* linux-4.4.* diff --git a/packages/base/armhf/Makefile b/packages/base/armhf/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/faultd/.gitignore b/packages/base/armhf/faultd/.gitignore new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/base/armhf/faultd/.gitignore @@ -0,0 +1 @@ + diff --git a/packages/base/armhf/faultd/Makefile b/packages/base/armhf/faultd/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/faultd/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/faultd/PKG.yml b/packages/base/armhf/faultd/PKG.yml new file mode 100644 index 00000000..847a0e9f --- /dev/null +++ b/packages/base/armhf/faultd/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/faultd/APKG.yml ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/base/armhf/faultd/builds/.gitignore b/packages/base/armhf/faultd/builds/.gitignore new file mode 100644 index 00000000..d3be4daa --- /dev/null +++ b/packages/base/armhf/faultd/builds/.gitignore @@ -0,0 +1,2 @@ +faultd.mk +faultd-module.mk diff --git a/packages/base/armhf/faultd/builds/Makefile b/packages/base/armhf/faultd/builds/Makefile new file mode 100644 index 00000000..9f2057ae --- /dev/null +++ b/packages/base/armhf/faultd/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/faultd/builds/Makefile diff --git a/packages/base/armhf/fit/Makefile b/packages/base/armhf/fit/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/fit/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/fit/buildroot/Makefile b/packages/base/armhf/fit/buildroot/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/fit/buildroot/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/fit/buildroot/PKG.yml b/packages/base/armhf/fit/buildroot/PKG.yml new file mode 100644 index 00000000..e56b52b5 --- /dev/null +++ b/packages/base/armhf/fit/buildroot/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/fit/buildroot/APKG.yml ARCH=armhf diff --git a/packages/base/armhf/fit/buildroot/builds/.gitignore b/packages/base/armhf/fit/buildroot/builds/.gitignore new file mode 100644 index 00000000..30c50fb1 --- /dev/null +++ b/packages/base/armhf/fit/buildroot/builds/.gitignore @@ -0,0 +1,4 @@ +kernel-* +*.itb +*.its +loader-initrd-armhf diff --git a/packages/base/armhf/fit/buildroot/builds/Makefile b/packages/base/armhf/fit/buildroot/builds/Makefile new file mode 100644 index 00000000..c39db3c0 --- /dev/null +++ b/packages/base/armhf/fit/buildroot/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/fit/buildroot/builds/Makefile diff --git a/packages/base/armhf/fit/loader/Makefile b/packages/base/armhf/fit/loader/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/fit/loader/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/fit/loader/PKG.yml b/packages/base/armhf/fit/loader/PKG.yml new file mode 100644 index 00000000..ff84f2e1 --- /dev/null +++ b/packages/base/armhf/fit/loader/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/fit/loader/APKG.yml ARCH=armhf diff --git a/packages/base/armhf/fit/loader/builds/.gitignore b/packages/base/armhf/fit/loader/builds/.gitignore new file mode 100644 index 00000000..dcbf6e8c --- /dev/null +++ b/packages/base/armhf/fit/loader/builds/.gitignore @@ -0,0 +1,5 @@ +kernel-* +*.itb +*.its +loader-initrd-armhf +manifest.json diff --git a/packages/base/armhf/fit/loader/builds/Makefile b/packages/base/armhf/fit/loader/builds/Makefile new file mode 100644 index 00000000..ae30040b --- /dev/null +++ b/packages/base/armhf/fit/loader/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/fit/loader/builds/Makefile diff --git a/packages/base/armhf/initrds/Makefile b/packages/base/armhf/initrds/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/initrds/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/initrds/buildroot/Makefile b/packages/base/armhf/initrds/buildroot/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/initrds/buildroot/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/initrds/buildroot/PKG.yml b/packages/base/armhf/initrds/buildroot/PKG.yml new file mode 100644 index 00000000..6c047536 --- /dev/null +++ b/packages/base/armhf/initrds/buildroot/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/initrds/buildroot/APKG.yml ARCH=armhf diff --git a/packages/base/armhf/initrds/buildroot/builds/.gitignore b/packages/base/armhf/initrds/buildroot/builds/.gitignore new file mode 100644 index 00000000..b821812a --- /dev/null +++ b/packages/base/armhf/initrds/buildroot/builds/.gitignore @@ -0,0 +1 @@ +makedevs diff --git a/packages/base/any/kernels/4.4-lts/kconfig.mk b/packages/base/armhf/initrds/buildroot/builds/Makefile similarity index 70% rename from packages/base/any/kernels/4.4-lts/kconfig.mk rename to packages/base/armhf/initrds/buildroot/builds/Makefile index 4262cad1..ea9590d7 100644 --- a/packages/base/any/kernels/4.4-lts/kconfig.mk +++ b/packages/base/armhf/initrds/buildroot/builds/Makefile @@ -1,7 +1,8 @@ +# -*- Makefile -*- ############################################################ -# +# # -# Copyright 2015 Big Switch Networks, Inc. +# Copyright 2013, 2014 Big Switch Networks, Inc. # # Licensed under the Eclipse Public License, Version 1.0 (the # "License"); you may not use this file except in compliance @@ -18,9 +19,9 @@ # # ############################################################ -THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -K_MAJOR_VERSION := 4 -K_PATCH_LEVEL := 4 -K_SUB_LEVEL := 39 -K_SUFFIX := -K_PATCH_DIR := $(THIS_DIR)/patches +# +# +############################################################ +include $(ONL)/make/config.armhf.mk +export BUILDROOT_ARCH := arm +include $(ONL)/packages/base/any/initrds/buildroot/Makefile.any diff --git a/packages/base/armhf/initrds/loader/Makefile b/packages/base/armhf/initrds/loader/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/initrds/loader/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/initrds/loader/PKG.yml b/packages/base/armhf/initrds/loader/PKG.yml new file mode 100644 index 00000000..9abc3bcd --- /dev/null +++ b/packages/base/armhf/initrds/loader/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/initrds/loader/APKG.yml ARCH=armhf diff --git a/packages/base/armhf/initrds/loader/builds/.gitignore b/packages/base/armhf/initrds/loader/builds/.gitignore new file mode 100644 index 00000000..1b4a5fd6 --- /dev/null +++ b/packages/base/armhf/initrds/loader/builds/.gitignore @@ -0,0 +1,3 @@ +loader-rootfs +buildroot-makedevs +manifest.json diff --git a/packages/base/armhf/initrds/loader/builds/Makefile b/packages/base/armhf/initrds/loader/builds/Makefile new file mode 100644 index 00000000..cf6d9fd5 --- /dev/null +++ b/packages/base/armhf/initrds/loader/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/initrds/loader/builds/Makefile diff --git a/packages/base/armhf/kernels/Makefile b/packages/base/armhf/kernels/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/kernels/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/Makefile b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/PKG.yml b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/PKG.yml new file mode 100644 index 00000000..432c4ea3 --- /dev/null +++ b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/kernels/lts/APKG.yml VERSION=4.14 ARCH=armhf CONFIG=armhf-iproc-all diff --git a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/.gitignore b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/.gitignore similarity index 100% rename from packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/.gitignore rename to packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/.gitignore index 5540b78d..9a71a737 100644 --- a/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all/.gitignore +++ b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/.gitignore @@ -1,3 +1,3 @@ -kernel-* linux-* +kernel-* lib/ diff --git a/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/Makefile b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/Makefile new file mode 100644 index 00000000..4a449bc0 --- /dev/null +++ b/packages/base/armhf/kernels/kernel-4.14-lts-armhf-iproc-all/builds/Makefile @@ -0,0 +1,5 @@ +KERNEL_BUILD_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +KERNEL_ARCH := arm +KERNEL_LTS_VERSION := 4.14 +KERNEL_CONFIG := armhf-iproc-all +include $(ONL)/packages/base/any/kernels/lts/builds/Makefile diff --git a/packages/base/armhf/onlp-snmpd/Makefile b/packages/base/armhf/onlp-snmpd/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/onlp-snmpd/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/onlp-snmpd/PKG.yml b/packages/base/armhf/onlp-snmpd/PKG.yml new file mode 100644 index 00000000..9d992129 --- /dev/null +++ b/packages/base/armhf/onlp-snmpd/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/onlp-snmpd/APKG.yml ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/base/armhf/onlp-snmpd/builds/.gitignore b/packages/base/armhf/onlp-snmpd/builds/.gitignore new file mode 100644 index 00000000..d2838356 --- /dev/null +++ b/packages/base/armhf/onlp-snmpd/builds/.gitignore @@ -0,0 +1 @@ +onlp-snmpd.mk diff --git a/packages/base/armhf/onlp-snmpd/builds/Makefile b/packages/base/armhf/onlp-snmpd/builds/Makefile new file mode 100644 index 00000000..6ecb3d67 --- /dev/null +++ b/packages/base/armhf/onlp-snmpd/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/onlp-snmpd/builds/Makefile diff --git a/packages/base/armhf/onlp/Makefile b/packages/base/armhf/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/base/armhf/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/base/armhf/onlp/PKG.yml b/packages/base/armhf/onlp/PKG.yml new file mode 100644 index 00000000..f07f4fd9 --- /dev/null +++ b/packages/base/armhf/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/onlp/APKG.yml ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/base/armhf/onlp/builds/.gitignore b/packages/base/armhf/onlp/builds/.gitignore new file mode 100644 index 00000000..d850afd1 --- /dev/null +++ b/packages/base/armhf/onlp/builds/.gitignore @@ -0,0 +1 @@ +libonlp-module.mk diff --git a/packages/base/armhf/onlp/builds/Makefile b/packages/base/armhf/onlp/builds/Makefile new file mode 100644 index 00000000..34328f0e --- /dev/null +++ b/packages/base/armhf/onlp/builds/Makefile @@ -0,0 +1,3 @@ +DIRECTORIES := onlp-platform-defaults onlp-platform onlp onlpd +include $(ONL)/make/subdirs.mk + diff --git a/packages/base/armhf/onlp/builds/onlp-platform-defaults/.gitignore b/packages/base/armhf/onlp/builds/onlp-platform-defaults/.gitignore new file mode 100644 index 00000000..4e86ab53 --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlp-platform-defaults/.gitignore @@ -0,0 +1 @@ +libonlp-platform-defaults-module.mk diff --git a/packages/base/armhf/onlp/builds/onlp-platform-defaults/Makefile b/packages/base/armhf/onlp/builds/onlp-platform-defaults/Makefile new file mode 100644 index 00000000..6c0ec687 --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlp-platform-defaults/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/onlp/builds/onlp-platform-defaults/Makefile diff --git a/packages/base/armhf/onlp/builds/onlp-platform/.gitignore b/packages/base/armhf/onlp/builds/onlp-platform/.gitignore new file mode 100644 index 00000000..8979873a --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlp-platform/.gitignore @@ -0,0 +1 @@ +libonlp-platform-module.mk diff --git a/packages/base/armhf/onlp/builds/onlp-platform/Makefile b/packages/base/armhf/onlp/builds/onlp-platform/Makefile new file mode 100644 index 00000000..9a1cd816 --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlp-platform/Makefile @@ -0,0 +1,3 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/onlp/builds/onlp-platform/Makefile + diff --git a/packages/base/armhf/onlp/builds/onlp/Makefile b/packages/base/armhf/onlp/builds/onlp/Makefile new file mode 100644 index 00000000..d4f085ee --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlp/Makefile @@ -0,0 +1,3 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/onlp/builds/onlp/Makefile + diff --git a/packages/base/armhf/onlp/builds/onlpd/.gitignore b/packages/base/armhf/onlp/builds/onlpd/.gitignore new file mode 100644 index 00000000..d4e7f470 --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlpd/.gitignore @@ -0,0 +1 @@ +onlpd-module.mk diff --git a/packages/base/armhf/onlp/builds/onlpd/Makefile b/packages/base/armhf/onlp/builds/onlpd/Makefile new file mode 100644 index 00000000..6acd0322 --- /dev/null +++ b/packages/base/armhf/onlp/builds/onlpd/Makefile @@ -0,0 +1,3 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/onlp/builds/onlpd/Makefile + diff --git a/packages/base/armhf/oom-shim/Makefile b/packages/base/armhf/oom-shim/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/base/armhf/oom-shim/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/base/armhf/oom-shim/PKG.yml b/packages/base/armhf/oom-shim/PKG.yml new file mode 100644 index 00000000..8dd57642 --- /dev/null +++ b/packages/base/armhf/oom-shim/PKG.yml @@ -0,0 +1 @@ +!include $ONL/packages/base/any/oom-shim/APKG.yml ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/base/armhf/oom-shim/builds/Makefile b/packages/base/armhf/oom-shim/builds/Makefile new file mode 100644 index 00000000..523d3db7 --- /dev/null +++ b/packages/base/armhf/oom-shim/builds/Makefile @@ -0,0 +1,2 @@ +include $(ONL)/make/config.armhf.mk +include $(ONL)/packages/base/any/oom-shim/builds/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml index c2f59267..44a0e946 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-30 +!include $ONL_TEMPLATES/platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-30 KERNELS="onl-kernel-4.14-lts-armel-iproc-all:armel" diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile new file mode 100644 index 00000000..c784eedb --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.14-lts-armel-iproc-all:armel +KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.c) +KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.h) +VENDOR := accton +BASENAME := arm-accton-as4610-30 +ARCH := arm +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore index 7ac7a04f..f9450b8b 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore @@ -1,2 +1,3 @@ *.dtb dts +include diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile index 2956bc6e..ddb50093 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile @@ -1,10 +1,15 @@ +INCLUDES=include . +KERNEL := onl-kernel-4.14-lts-armel-iproc-all:armel +DTS_LIST := arm-accton-as4610.dts +VPATH := $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610 include $(ONL)/make/dtbs.mk # # The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package. # setup:: - onlpm --link-dir onl-kernel-3.2-lts-arm-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-3.2-lts-arm-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/include include -clean:: - rm -rf fsl +setup-clean:: + rm -f dts include diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts deleted file mode 100644 index 0e7a33c0..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Accton AS4610 54 Device Tree Source - * - * Copyright 2015, Cumulus 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. - * - */ -/dts-v1/; -/include/ "dts/helix4.dtsi" - -/ { - model = "accton,as4610_54"; - compatible = "accton,as4610_54"; - - aliases { - serial0 = &uart0; - i2c-controller0 = &i2c0; - i2c-controller1 = &i2c1; - }; - - memory { - reg = <0x61000000 0x7f000000>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x00>; - }; - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x01>; - }; - }; - - localbus@1c000000 { - #address-cells = <0x2>; - #size-cells = <0x1>; - /* NAND Flash */ - ranges = < - 0x0 0x0 0x0 0x1c000000 0x00120000 - 0x1 0x0 0x0 0x1c120000 0x00040000 - >; - - flash@0,0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "cfi-flash"; - reg = <0x0 0x0 0x02000000>; - byteswap; - - partition@0 { - /* uboot */ - reg = <0x00000000 0x00100000>; - label = "uboot"; - }; - partition@1 { - /* uboot-env */ - reg = <0x00100000 0x00100000>; - label = "uboot-env"; - env_size = <0x2000>; - }; - partition@2 { - /* board_eeprom */ - reg = <0x00200000 0x00100000>; - label = "board_eeprom"; - }; - partition@3 { - /* shmoo */ - reg = <0x00300000 0x00100000>; - label = "shmoo"; - }; - partition@4 { - /* onie */ - reg = <0x00400000 0x00800000>; - label = "onie"; - }; - partition@5 { - /* open */ - reg = <0x00c00000 0x03c00000>; - label = "open"; - }; - partition@6 { - /* open2 */ - reg = <0x04800000 0x7d000000>; - label = "open2"; - }; - partition@7 { - /* diag */ - reg = <0xfec00000 0x01000000>; - label = "diag"; - }; - }; - }; - - i2c0: i2c@18038000 { - compatible = "iproc-smb"; - reg = <0x18038000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = < 127 >; - clock-frequency = <400000>; - cpld@1,0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "accton,as4610_54_cpld"; - label = "cpld"; - reg = <0x30>; - }; - }; - - i2c1: i2c@1803b000 { - compatible = "iproc-smb"; - reg = <0x1803b000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = < 128 >; - clock-frequency = <100000>; - mux@70 { - compatible = "ti,pca9548"; - reg = <0x70>; - #address-cells = <1>; - #size-cells = <0>; - deselect-on-exit; - - // SFP+ 1 - i2c@0 { - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; - sfp_eeprom@50 { - compatible = "at,as4610_sfp1"; - reg = <0x50>; - label = "port49"; - }; - }; - - // SFP+ 2 - i2c@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp2"; - reg = <0x50>; - label = "port50"; - }; - }; - - // SFP+ 3 - i2c@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp3"; - reg = <0x50>; - label = "port51"; - }; - }; - - // SFP+ 4 - i2c@3 { - #address-cells = <1>; - #size-cells = <0>; - reg = <3>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp4"; - reg = <0x50>; - label = "port52"; - }; - }; - - // QSFP+ STK1 - i2c@4 { - #address-cells = <1>; - #size-cells = <0>; - reg = <4>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp5"; - reg = <0x50>; - }; - }; - - // QSFP+ STK2 - i2c@5 { - #address-cells = <1>; - #size-cells = <0>; - reg = <5>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp6"; - reg = <0x50>; - }; - }; - - // PSU EEPROM - i2c@6 { - #address-cells = <1>; - #size-cells = <0>; - reg = <6>; - psu1_eeprom@50 { - compatible = "accton,as4610_psu1"; - reg = <0x50>; - }; - psu1_pmbus@58 { - compatible = "3y-power,ym1921"; - reg = <0x58>; - }; - psu2_eeprom@51 { - compatible = "accton,as4610_psu2"; - reg = <0x51>; - }; - psu2_pmbus@59 { - compatible = "3y-power,ym1921"; - reg = <0x59>; - }; - }; - - i2c@7 { - #address-cells = <1>; - #size-cells = <0>; - reg = <7>; - - temp@48 { - compatible = "nxp,lm77"; - reg = <0x48>; - }; - - rtc@68 { - /* Actually M41T11 */ - compatible = "dallas,ds1307"; - reg = <0x68>; - }; - - board_eeprom@50 { - compatible = "at,24c04"; - reg = <0x50>; - label = "board_eeprom"; - }; - }; - }; - }; -}; diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml index 937774e8..7848df7e 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml @@ -9,13 +9,13 @@ arm-accton-as4610-30-r0: flat_image_tree: kernel: - <<: *arm-iproc-kernel + <<: *armel-iproc-4-14-kernel dtb: - =: arm-accton-as4610-54-r0.dtb + =: arm-accton-as4610.dtb package: onl-platform-build-arm-accton-as4610-30-r0:armel itb: - <<: *arm-itb + <<: *armel-itb loader: device: /dev/sda diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py index e43c847e..c0bcd1ad 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py @@ -6,3 +6,20 @@ class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton, PLATFORM='arm-accton-as4610-30-r0' MODEL="AS4610-30" SYS_OBJECT_ID=".4610.30" + + def baseconfig(self): + self.insmod("accton_as4610_cpld") + self.insmod("accton_as4610_psu") + self.insmod("accton_as4610_fan") + self.insmod("accton_as4610_leds") + self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port25 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + + return True diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml index 0ddb1ebe..edaa8ee6 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-54 +!include $ONL_TEMPLATES/platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-54 KERNELS="onl-kernel-4.14-lts-armel-iproc-all:armel" diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile new file mode 100644 index 00000000..93050af0 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.14-lts-armel-iproc-all:armel +KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.c) +KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.h) +VENDOR := accton +BASENAME := arm-accton-as4610-54 +ARCH := arm +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore index 7ac7a04f..f9450b8b 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore @@ -1,2 +1,3 @@ *.dtb dts +include diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile index 2956bc6e..ddb50093 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile @@ -1,10 +1,15 @@ +INCLUDES=include . +KERNEL := onl-kernel-4.14-lts-armel-iproc-all:armel +DTS_LIST := arm-accton-as4610.dts +VPATH := $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610 include $(ONL)/make/dtbs.mk # # The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package. # setup:: - onlpm --link-dir onl-kernel-3.2-lts-arm-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-3.2-lts-arm-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/include include -clean:: - rm -rf fsl +setup-clean:: + rm -f dts include diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts deleted file mode 100644 index 0e7a33c0..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Accton AS4610 54 Device Tree Source - * - * Copyright 2015, Cumulus 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. - * - */ -/dts-v1/; -/include/ "dts/helix4.dtsi" - -/ { - model = "accton,as4610_54"; - compatible = "accton,as4610_54"; - - aliases { - serial0 = &uart0; - i2c-controller0 = &i2c0; - i2c-controller1 = &i2c1; - }; - - memory { - reg = <0x61000000 0x7f000000>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x00>; - }; - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x01>; - }; - }; - - localbus@1c000000 { - #address-cells = <0x2>; - #size-cells = <0x1>; - /* NAND Flash */ - ranges = < - 0x0 0x0 0x0 0x1c000000 0x00120000 - 0x1 0x0 0x0 0x1c120000 0x00040000 - >; - - flash@0,0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "cfi-flash"; - reg = <0x0 0x0 0x02000000>; - byteswap; - - partition@0 { - /* uboot */ - reg = <0x00000000 0x00100000>; - label = "uboot"; - }; - partition@1 { - /* uboot-env */ - reg = <0x00100000 0x00100000>; - label = "uboot-env"; - env_size = <0x2000>; - }; - partition@2 { - /* board_eeprom */ - reg = <0x00200000 0x00100000>; - label = "board_eeprom"; - }; - partition@3 { - /* shmoo */ - reg = <0x00300000 0x00100000>; - label = "shmoo"; - }; - partition@4 { - /* onie */ - reg = <0x00400000 0x00800000>; - label = "onie"; - }; - partition@5 { - /* open */ - reg = <0x00c00000 0x03c00000>; - label = "open"; - }; - partition@6 { - /* open2 */ - reg = <0x04800000 0x7d000000>; - label = "open2"; - }; - partition@7 { - /* diag */ - reg = <0xfec00000 0x01000000>; - label = "diag"; - }; - }; - }; - - i2c0: i2c@18038000 { - compatible = "iproc-smb"; - reg = <0x18038000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = < 127 >; - clock-frequency = <400000>; - cpld@1,0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "accton,as4610_54_cpld"; - label = "cpld"; - reg = <0x30>; - }; - }; - - i2c1: i2c@1803b000 { - compatible = "iproc-smb"; - reg = <0x1803b000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = < 128 >; - clock-frequency = <100000>; - mux@70 { - compatible = "ti,pca9548"; - reg = <0x70>; - #address-cells = <1>; - #size-cells = <0>; - deselect-on-exit; - - // SFP+ 1 - i2c@0 { - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; - sfp_eeprom@50 { - compatible = "at,as4610_sfp1"; - reg = <0x50>; - label = "port49"; - }; - }; - - // SFP+ 2 - i2c@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp2"; - reg = <0x50>; - label = "port50"; - }; - }; - - // SFP+ 3 - i2c@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp3"; - reg = <0x50>; - label = "port51"; - }; - }; - - // SFP+ 4 - i2c@3 { - #address-cells = <1>; - #size-cells = <0>; - reg = <3>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp4"; - reg = <0x50>; - label = "port52"; - }; - }; - - // QSFP+ STK1 - i2c@4 { - #address-cells = <1>; - #size-cells = <0>; - reg = <4>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp5"; - reg = <0x50>; - }; - }; - - // QSFP+ STK2 - i2c@5 { - #address-cells = <1>; - #size-cells = <0>; - reg = <5>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp6"; - reg = <0x50>; - }; - }; - - // PSU EEPROM - i2c@6 { - #address-cells = <1>; - #size-cells = <0>; - reg = <6>; - psu1_eeprom@50 { - compatible = "accton,as4610_psu1"; - reg = <0x50>; - }; - psu1_pmbus@58 { - compatible = "3y-power,ym1921"; - reg = <0x58>; - }; - psu2_eeprom@51 { - compatible = "accton,as4610_psu2"; - reg = <0x51>; - }; - psu2_pmbus@59 { - compatible = "3y-power,ym1921"; - reg = <0x59>; - }; - }; - - i2c@7 { - #address-cells = <1>; - #size-cells = <0>; - reg = <7>; - - temp@48 { - compatible = "nxp,lm77"; - reg = <0x48>; - }; - - rtc@68 { - /* Actually M41T11 */ - compatible = "dallas,ds1307"; - reg = <0x68>; - }; - - board_eeprom@50 { - compatible = "at,24c04"; - reg = <0x50>; - label = "board_eeprom"; - }; - }; - }; - }; -}; diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml index 542fac0c..9655f560 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml @@ -2,20 +2,20 @@ ###################################################################### # -# platform-config for AS4610 +# platform-config for AS4610-54 # ###################################################################### arm-accton-as4610-54-r0: flat_image_tree: kernel: - <<: *arm-iproc-kernel + <<: *armel-iproc-4-14-kernel dtb: - =: arm-accton-as4610-54-r0.dtb + =: arm-accton-as4610.dtb package: onl-platform-build-arm-accton-as4610-54-r0:armel itb: - <<: *arm-itb + <<: *armel-itb loader: device: /dev/sda diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py index a4cf2289..5a32e574 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py @@ -6,3 +6,38 @@ class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton, PLATFORM='arm-accton-as4610-54-r0' MODEL="AS4610-54" SYS_OBJECT_ID=".4610.54" + + def baseconfig(self): + self.insmod("accton_as4610_cpld") + self.insmod("accton_as4610_psu") + self.insmod("accton_as4610_fan") + self.insmod("accton_as4610_leds") + self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port49 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + +# self.new_i2c_devices( +# [ +# ("pca9548", 0x70, 1), +# ("as4610_sfp1", 0x50, 2), +# ("as4610_sfp2", 0x50, 3), +# ("as4610_sfp3", 0x50, 4), +# ("as4610_sfp4", 0x50, 5), +# ("as4610_sfp5", 0x50, 6), +# ("as4610_sfp6", 0x50, 7), +# ("as4610_psu1", 0x50, 8), +# ("as4610_psu2", 0x51, 8), +# ("ym1921", 0x58, 8), +# ("ym1921", 0x59, 8), +# ("lm77", 0x48, 9), +# ("ds1307", 0x68, 9), +# ("24c04", 0x50, 9), +# ] +# ) + return True diff --git a/packages/platforms/accton/armhf/Makefile b/packages/platforms/accton/armhf/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/.gitignore new file mode 100644 index 00000000..4d978b36 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/.gitignore @@ -0,0 +1,2 @@ +*x86*64*cel*redstone*xp*.mk +onlpdump.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml new file mode 100644 index 00000000..13254b29 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml ARCH=armhf VENDOR=accton BASENAME=arm-accton-as4610-30 KERNELS="onl-kernel-4.14-lts-armhf-iproc-all:armhf" diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile new file mode 100644 index 00000000..13a4e194 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.14-lts-armhf-iproc-all:armhf +KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.c) +KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.h) +VENDOR := accton +BASENAME := arm-accton-as4610-30 +ARCH := arm +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml new file mode 100644 index 00000000..8d42f5a0 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=arm-accton-as4610-30 ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile new file mode 100644 index 00000000..5456c2da --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile @@ -0,0 +1,44 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.armhf.mk + +MODULE := libonlp-arm-accton-as4610-30 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF arm_accton_as4610 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-arm-accton-as4610-30.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk new file mode 100644 index 00000000..3c9f70fa --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-arm-accton-as4610-30 module. +# +# Autogenerated 2016-07-20 18:29:31.706331 +# +############################################################################### +libonlp-arm-accton-as4610-30_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..64d98aca --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.armhf.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp arm_accton_as4610 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml new file mode 100644 index 00000000..712d53eb --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armhf VENDOR=accton BASENAME=arm-accton-as4610-30 REVISION=r0 diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/Makefile new file mode 100644 index 00000000..f57d6248 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore new file mode 100644 index 00000000..f9450b8b --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/.gitignore @@ -0,0 +1,3 @@ +*.dtb +dts +include diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile new file mode 100644 index 00000000..5e17f4e4 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/Makefile @@ -0,0 +1,15 @@ +INCLUDES=include . +KERNEL := onl-kernel-4.14-lts-armhf-iproc-all:armhf +DTS_LIST := arm-accton-as4610.dts +VPATH := $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610 +include $(ONL)/make/dtbs.mk + +# +# The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package. +# +setup:: + onlpm --link-dir onl-kernel-4.14-lts-armhf-iproc-all:armhf /usr/share/onl/packages/armhf/onl-kernel-4.14-lts-armhf-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armhf-iproc-all:armhf /usr/share/onl/packages/armhf/onl-kernel-4.14-lts-armhf-iproc-all/mbuilds/include include + +setup-clean:: + rm -f dts include diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml new file mode 100644 index 00000000..178dc9fb --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AS4610-30 +# +###################################################################### + +arm-accton-as4610-30-r0: + flat_image_tree: + kernel: + <<: *armhf-iproc-4-14-kernel + dtb: + =: arm-accton-as4610.dtb + package: onl-platform-build-arm-accton-as4610-30-r0:armhf + + itb: + <<: *armhf-itb + + loader: + device: /dev/sda + ##partition: /dev/sda1 + loadaddr: 0x70000000 + nos_bootcmds: *usb2_bootcmds + + environment: + - device: /dev/mtd2 + env_offset: 0x00000000 + env_size: 0x00002000 + sector_size: 0x00010000 diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py new file mode 100644 index 00000000..c0bcd1ad --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py @@ -0,0 +1,25 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton, + OnlPlatformPortConfig_24x1_4x10): + PLATFORM='arm-accton-as4610-30-r0' + MODEL="AS4610-30" + SYS_OBJECT_ID=".4610.30" + + def baseconfig(self): + self.insmod("accton_as4610_cpld") + self.insmod("accton_as4610_psu") + self.insmod("accton_as4610_fan") + self.insmod("accton_as4610_leds") + self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port25 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + + return True diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/.gitignore new file mode 100644 index 00000000..4d978b36 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/.gitignore @@ -0,0 +1,2 @@ +*x86*64*cel*redstone*xp*.mk +onlpdump.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml new file mode 100644 index 00000000..a0ecfdea --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml ARCH=armhf VENDOR=accton BASENAME=arm-accton-as4610-54 KERNELS="onl-kernel-4.14-lts-armhf-iproc-all:armhf" diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile new file mode 100644 index 00000000..f8b3dc00 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.14-lts-armhf-iproc-all:armhf +KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.c) +KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610/modules/*.h) +VENDOR := accton +BASENAME := arm-accton-as4610-54 +ARCH := arm +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/PKG.yml new file mode 100644 index 00000000..95388927 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=arm-accton-as4610-54 ARCH=armhf TOOLCHAIN=arm-linux-gnueabihf diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile new file mode 100644 index 00000000..3781c17c --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile @@ -0,0 +1,44 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.armhf.mk + +MODULE := libonlp-arm-accton-as4610-54 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF arm_accton_as4610 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-arm-accton-as4610-54.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk new file mode 100644 index 00000000..71f6d993 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-arm-accton-as4610-54 module. +# +# Autogenerated 2016-07-20 18:27:47.344268 +# +############################################################################### +libonlp-arm-accton-as4610-54_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..64d98aca --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.armhf.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp arm_accton_as4610 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/PKG.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/PKG.yml new file mode 100644 index 00000000..a0f879a1 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armhf VENDOR=accton BASENAME=arm-accton-as4610-54 REVISION=r0 diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/Makefile new file mode 100644 index 00000000..f57d6248 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore new file mode 100644 index 00000000..f9450b8b --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/.gitignore @@ -0,0 +1,3 @@ +*.dtb +dts +include diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile new file mode 100644 index 00000000..5e17f4e4 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/Makefile @@ -0,0 +1,15 @@ +INCLUDES=include . +KERNEL := onl-kernel-4.14-lts-armhf-iproc-all:armhf +DTS_LIST := arm-accton-as4610.dts +VPATH := $(ONL)/packages/platforms/accton/armxx/arm-accton-as4610 +include $(ONL)/make/dtbs.mk + +# +# The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package. +# +setup:: + onlpm --link-dir onl-kernel-4.14-lts-armhf-iproc-all:armhf /usr/share/onl/packages/armhf/onl-kernel-4.14-lts-armhf-iproc-all/mbuilds/arch/arm/boot/dts dts + onlpm --link-dir onl-kernel-4.14-lts-armhf-iproc-all:armhf /usr/share/onl/packages/armhf/onl-kernel-4.14-lts-armhf-iproc-all/mbuilds/include include + +setup-clean:: + rm -f dts include diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml new file mode 100644 index 00000000..de1dfff4 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AS4610-54 +# +###################################################################### + +arm-accton-as4610-54-r0: + flat_image_tree: + kernel: + <<: *armhf-iproc-4-14-kernel + dtb: + =: arm-accton-as4610.dtb + package: onl-platform-build-arm-accton-as4610-54-r0:armhf + + itb: + <<: *armhf-itb + + loader: + device: /dev/sda + ##partition: /dev/sda1 + loadaddr: 0x70000000 + nos_bootcmds: *usb2_bootcmds + + environment: + - device: /dev/mtd2 + env_offset: 0x00000000 + env_size: 0x00002000 + sector_size: 0x00010000 diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py new file mode 100644 index 00000000..5a32e574 --- /dev/null +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py @@ -0,0 +1,43 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x1_4x10): + PLATFORM='arm-accton-as4610-54-r0' + MODEL="AS4610-54" + SYS_OBJECT_ID=".4610.54" + + def baseconfig(self): + self.insmod("accton_as4610_cpld") + self.insmod("accton_as4610_psu") + self.insmod("accton_as4610_fan") + self.insmod("accton_as4610_leds") + self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port49 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + +# self.new_i2c_devices( +# [ +# ("pca9548", 0x70, 1), +# ("as4610_sfp1", 0x50, 2), +# ("as4610_sfp2", 0x50, 3), +# ("as4610_sfp3", 0x50, 4), +# ("as4610_sfp4", 0x50, 5), +# ("as4610_sfp5", 0x50, 6), +# ("as4610_sfp6", 0x50, 7), +# ("as4610_psu1", 0x50, 8), +# ("as4610_psu2", 0x51, 8), +# ("ym1921", 0x58, 8), +# ("ym1921", 0x59, 8), +# ("lm77", 0x48, 9), +# ("ds1307", 0x68, 9), +# ("24c04", 0x50, 9), +# ] +# ) + return True diff --git a/packages/platforms/accton/armhf/modules/Makefile b/packages/platforms/accton/armhf/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armhf/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armhf/modules/PKG.yml b/packages/platforms/accton/armhf/modules/PKG.yml new file mode 100644 index 00000000..3764a280 --- /dev/null +++ b/packages/platforms/accton/armhf/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/no-arch-vendor-modules.yml ARCH=armhf VENDOR=accton diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts b/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts new file mode 100644 index 00000000..476b04e4 --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts @@ -0,0 +1,248 @@ +/* + * Accton AS4610 54 Device Tree Source + * + * Copyright 2015, Cumulus 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. + * + */ +/dts-v1/; +#include "dts/bcm-helix4.dtsi" + +/ { + model = "accton,as4610_54"; + compatible = "accton,as4610_54","brcm,helix4"; + + aliases { + serial0 = &uart1; + serial1 = &uart2; + ethernet0 = &gmac0; + i2c-controller0 = &i2c0; + i2c-controller1 = &i2c1; + }; +/* + chosen { + bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=2000M"; + }; +*/ + memory { + reg = <0x61000000 0x7f000000>; + }; +}; + +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&gmac0 { + status = "okay"; + phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */ +}; + +&usbphy0 { + status = "okay"; + usb-phy-mode = "host"; /* "host", "device" */ +/* mdio-phy-handle = <&usb_phy>; +*/ +}; + +&ehci0 { + status = "okay"; +}; + +&gpio_cca { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <400000>; + cpld@30 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "accton,as4610_54_cpld"; + label = "cpld"; + reg = <0x30>; + }; +}; + +&i2c1 { + status = "okay"; + mux@70 { + compatible = "ti,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + deselect-on-exit; + + // SFP+ 1 + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + optoe@50 { + compatible = "optoe2"; + reg = <0x50>; + label = "port49"; + }; + }; + + // SFP+ 2 + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + optoe@50 { + compatible = "optoe2"; + reg = <0x50>; + label = "port50"; + }; + }; + + // SFP+ 3 + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + optoe@50 { + compatible = "optoe2"; + reg = <0x50>; + label = "port51"; + }; + }; + + // SFP+ 4 + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + optoe@50 { + compatible = "optoe2"; + reg = <0x50>; + label = "port52"; + }; + }; + + // QSFP+ STK1 + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + optoe@50 { + compatible = "optoe1"; + reg = <0x50>; + label = "port53"; + }; + }; + + // QSFP+ STK2 + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + optoe@50 { + compatible = "optoe1"; + reg = <0x50>; + label = "port54"; + }; + }; + + // PSU EEPROM + i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + psu1_eeprom@50 { + compatible = "accton,as4610_psu1"; + reg = <0x50>; + }; + psu1_pmbus@58 { + compatible = "3y-power,ym1921"; + reg = <0x58>; + }; + psu2_eeprom@51 { + compatible = "accton,as4610_psu2"; + reg = <0x51>; + }; + psu2_pmbus@59 { + compatible = "3y-power,ym1921"; + reg = <0x59>; + }; + }; + + i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + + temp@48 { + compatible = "nxp,lm77"; + reg = <0x48>; + }; + + rtc@68 { + /* Actually M41T11 */ + compatible = "dallas,ds1307"; + reg = <0x68>; + }; + + board_eeprom@50 { + compatible = "at,24c04"; + reg = <0x50>; + label = "board_eeprom"; + }; + }; + }; +}; + +&hwrng { + status = "okay"; +}; + +&iproc_wdt { + status = "okay"; +}; + +&dmac0 { + status = "okay"; +}; + +&iproc_cmicd { + status = "okay"; +}; + +&qspi { + status = "okay"; + flash: m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p80"; + m25p,fast-read = <1>; + spi-max-frequency = <62500000>; + reg = <0x0>; + partition@0 { + label = "uboot"; + reg = <0x00000000 0x000e0000>; + /*read-only;*/ + }; + partition@1 { + label = "shmoo"; + reg = <0x000e0000 0x00010000>; + }; + partition@2 { + label = "uboot-env"; + reg = <0x000f0000 0x00010000>; + }; + partition@3 { + label = "onie"; + reg = <0x00100000 0x00700000>; + }; + }; +}; diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.gitignore b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/.gitignore similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.gitignore rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/.gitignore diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.module b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/.module similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.module rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/.module diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/Makefile b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/Makefile rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/arm_accton_as4610.doxy b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/arm_accton_as4610.doxy similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/arm_accton_as4610.doxy rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/arm_accton_as4610.doxy diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/arm_accton_as4610.yml b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/auto/arm_accton_as4610.yml similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/arm_accton_as4610.yml rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/auto/arm_accton_as4610.yml diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/make.mk b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/auto/make.mk similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/make.mk rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/auto/make.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/make.mk b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/make.mk similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/make.mk rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/make.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/Makefile b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/Makefile rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_config.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_config.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_config.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_config.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_enums.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_enums.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_enums.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_enums.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_int.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_int.h similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_int.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_int.h diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_log.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_log.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_log.h similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_log.h diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_module.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_module.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_module.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_module.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/fani.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/fani.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/fani.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/fani.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/ledi.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/ledi.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/ledi.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/ledi.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/make.mk b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/make.mk similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/make.mk rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/make.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/platform_lib.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/platform_lib.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/platform_lib.h similarity index 94% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/platform_lib.h index 873e74ad..c40b0aaf 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/platform_lib.h @@ -28,8 +28,8 @@ #include "arm_accton_as4610_log.h" -#define CHASSIS_THERMAL_COUNT 1 -#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_THERMAL_COUNT 1 +#define CHASSIS_PSU_COUNT 2 #define PSU1_ID 1 #define PSU2_ID 2 @@ -46,7 +46,7 @@ #define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node #define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node -#define IDPROM_PATH "/sys/devices/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom" +#define IDPROM_PATH "/sys/devices/platform/axi/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom" int deviceNodeWriteInt(char *filename, int value, int data_len); int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len); @@ -97,4 +97,3 @@ typedef enum platform_id_e { extern platform_id_t platform_id; #endif /* __PLATFORM_LIB_H__ */ - diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/psui.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/psui.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/psui.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/psui.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c similarity index 61% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c index 7199a31a..41379f73 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c @@ -24,50 +24,31 @@ * ***********************************************************/ #include +#include #include "platform_lib.h" #include #include "arm_accton_as4610_log.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; -#define FRONT_PORT_MUX_INDEX(port) (port-46) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0030/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0030/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0030/module_tx_fault_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_rx_los_all" -static int -sfp_node_read_int(char *node_path, int *value, int data_len) +static int front_port_bus_index(int port) { - int ret = 0; - char buf[8]; - *value = 0; - - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); - } - - return ret; + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 22) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 46) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } -static char* -sfp_get_port_path_addr(int port, int addr, char *node_name) +static int front_port_to_cpld_port(int port) { - int front_port_mux_id; - - if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) - front_port_mux_id = port - 22; - else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ - front_port_mux_id = port - 46; - - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - front_port_mux_id, addr, node_name); - return sfp_node_path; -} - -static char* -sfp_get_port_path(int port, char *node_name) -{ - return sfp_get_port_path_addr(port, 50, node_name); + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 23) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 47) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } /************************************************************ @@ -115,9 +96,9 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - - if (sfp_node_read_int(path, &present, 0) != 0) { + int cpld_port = front_port_to_cpld_port(port); + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -129,7 +110,6 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -140,18 +120,18 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of each port */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -173,7 +153,6 @@ int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -182,16 +161,18 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of each port */ + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -212,32 +193,51 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - /* * Read the SFP eeprom into data[] * * Return MISSING if SFP is missing. * Return OK if eeprom is read */ + int size = 0; memset(data, 0, 256); - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return ONLP_STATUS_OK; } int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); - memset(data, 0, 256); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); return ONLP_STATUS_E_INTERNAL; } @@ -247,45 +247,24 @@ onlp_sfpi_dom_read(int port, uint8_t data[256]) int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { - int rv; - - switch(control) - { - case ONLP_SFP_CONTROL_TX_DISABLE: - { - char* path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - - default: - rv = ONLP_STATUS_E_UNSUPPORTED; - break; - } - - return rv; + return ONLP_STATUS_E_UNSUPPORTED; } int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; + int cpld_port = front_port_to_cpld_port(port); + + if (cpld_port > 4) { + return ONLP_STATUS_E_UNSUPPORTED; + } switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = sfp_get_port_path(port, "sfp_rx_los"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -297,9 +276,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = sfp_get_port_path(port, "sfp_tx_fault"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -309,20 +286,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) break; } - case ONLP_SFP_CONTROL_TX_DISABLE: - { - path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (sfp_node_read_int(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - default: rv = ONLP_STATUS_E_UNSUPPORTED; } @@ -330,9 +293,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) return rv; } - int onlp_sfpi_denit(void) { return ONLP_STATUS_OK; } + diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sysi.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sysi.c similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sysi.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sysi.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/thermali.c similarity index 90% rename from packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c rename to packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/thermali.c index d9beebec..ddfbce3f 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/thermali.c @@ -63,11 +63,11 @@ enum onlp_thermal_id static char* last_path[] = /* must map with onlp_thermal_id */ { "reserved", - "9-0048/temp1_input", - "8-0058/psu_temp1_input", - "8-0059/psu_temp1_input", + "9-0048*temp1_input", + "8-0058*psu_temp1_input", + "8-0059*psu_temp1_input", }; - + /* Static values */ static onlp_thermal_info_t linfo[] = { { }, /* Not used */ @@ -107,9 +107,7 @@ onlp_thermali_init(void) int onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) { - int fd, len, nbytes = 10, temp_base=1, local_id; - char r_data[10] = {0}; - char fullpath[50] = {0}; + int local_id; VALIDATE(id); local_id = ONLP_OID_ID_GET(id); @@ -119,12 +117,12 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) *info = linfo[local_id]; /* get fullpath */ - sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); - - OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); - info->mcelsius = atoi(r_data) / temp_base; + onlp_file_read_int(&info->mcelsius, "%s%s", prefix_path, last_path[local_id]); + //sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); + //AIM_LOG_MSG("%s", fullpath); + //OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + //info->mcelsius = atoi(r_data) / temp_base; DEBUG_PRINT("\n[Debug][%s][%d][save data: %d]\n", __FUNCTION__, __LINE__, info->mcelsius); return ONLP_STATUS_OK; } - diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c new file mode 100644 index 00000000..2ee2d163 --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c @@ -0,0 +1,627 @@ +/* + * 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 as4610_54 CPLD + * + * 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 */ +#define AS4610_CPLD_SLAVE_ADDR 0x30 +#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ + +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 { + as4610_54_cpld +}; + +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + +struct as4610_54_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as4610_54_cpld_id[] = { + { "as4610_54_cpld", as4610_54_cpld }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as4610_54_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 + +enum as4610_54_cpld1_sysfs_attributes { + CPLD_VERSION, + PRODUCT_ID, + 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_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), +}; + +/* 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 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 show_product_id(struct device *dev, struct device_attribute *attr, + char *buf); +static int as4610_54_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as4610_54_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_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_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); +static SENSOR_DEVICE_ATTR(product_id, S_IRUGO, show_product_id, NULL, PRODUCT_ID); +/* 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_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); + +static struct attribute *as4610_54_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + &sensor_dev_attr_product_id.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_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + NULL +}; + +static const struct attribute_group as4610_54_cpld_group = { + .attrs = as4610_54_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, present = 0; + u8 regs[] = {0x2, 0x3, 0x21}; + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as4610_54_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + switch (i) { + case 0: + present |= (status & BIT(6)) >> 6; /* port 25/49 */ + present |= (status & BIT(2)) >> 1; /* port 26/50 */ + break; + case 1: + present |= (status & BIT(6)) >> 4; /* port 27/51 */ + present |= (status & BIT(2)) << 1; /* port 28/52 */ + break; + case 2: + present |= (status & BIT(0)) << 4; /* port 29/53 */ + present |= (status & BIT(4)) << 1; /* port 30/54 */ + break; + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%.2x\n", present); + +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, rx_los = 0; + u8 regs[] = {0x2, 0x3}; + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as4610_54_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + switch (i) { + case 0: + rx_los |= (status & BIT(4)) >> 4; /* port 25/49 rx_los */ + rx_los |= (status & BIT(0)) << 1; /* port 26/50 rx_los */ + break; + case 1: + rx_los |= (status & BIT(4)) >> 2; /* port 27/51 rx_los */ + rx_los |= (status & BIT(0)) << 3; /* port 28/52 rx_los */ + break; + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + /* Return values 25/49 -> 28/52 in order */ + return sprintf(buf, "%.2x\n", rx_los); + +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 as4610_54_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1: + reg = 0x2; + mask = 0x40; + break; + case MODULE_PRESENT_2: + reg = 0x2; + mask = 0x4; + break; + case MODULE_PRESENT_3: + reg = 0x3; + mask = 0x40; + break; + case MODULE_PRESENT_4: + reg = 0x3; + mask = 0x4; + break; + case MODULE_PRESENT_5: + reg = 0x21; + mask = 0x1; + break; + case MODULE_PRESENT_6: + reg = 0x21; + mask = 0x10; + break; + case MODULE_TXFAULT_1: + reg = 0x2; + mask = 0x20; + break; + case MODULE_TXFAULT_2: + reg = 0x2; + mask = 0x2; + break; + case MODULE_TXFAULT_3: + reg = 0x3; + mask = 0x20; + break; + case MODULE_TXFAULT_4: + reg = 0x3; + mask = 0x2; + break; + case MODULE_RXLOS_1: + reg = 0x2; + mask = 0x10; + break; + case MODULE_RXLOS_2: + reg = 0x2; + mask = 0x1; + break; + case MODULE_RXLOS_3: + reg = 0x3; + mask = 0x10; + break; + case MODULE_RXLOS_4: + reg = 0x3; + mask = 0x1; + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as4610_54_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 as4610_54_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 = as4610_54_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 as4610_54_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 as4610_54_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_product_id(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 & 0xF)); +} + +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, 0xB); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* I2C init/probing/exit functions */ +static int as4610_54_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as4610_54_cpld_data *data; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as4610_54_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; + /* Bring QSFPs out of reset */ + as4610_54_cpld_write_internal(client, 0x2A, 0); + + ret = sysfs_create_group(&client->dev.kobj, &as4610_54_cpld_group); + if (ret) { + goto exit_free; + } + + as4610_54_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as4610_54_cpld_remove(struct i2c_client *client) +{ + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + as4610_54_cpld_remove_client(client); + + /* Remove sysfs hooks */ + sysfs_remove_group(&client->dev.kobj, &as4610_54_cpld_group); + kfree(data); + + return 0; +} + +static int as4610_54_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 as4610_54_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 as4610_54_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 = as4610_54_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4610_54_cpld_read); + +int as4610_54_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 = as4610_54_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4610_54_cpld_write); + +int as4610_product_id(void) +{ + int pid = as4610_54_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); + pid &= 0xF; + + if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { + return PID_UNKNOWN; + } + + return pid; +} +EXPORT_SYMBOL(as4610_product_id); + +int as4610_is_poe_system(void) +{ + int pid = as4610_product_id(); + return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); +} +EXPORT_SYMBOL(as4610_is_poe_system); + +static struct i2c_driver as4610_54_cpld_driver = { + .driver = { + .name = "as4610_54_cpld", + .owner = THIS_MODULE, + }, + .probe = as4610_54_cpld_probe, + .remove = as4610_54_cpld_remove, + .id_table = as4610_54_cpld_id, +}; + +static int __init as4610_54_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as4610_54_cpld_driver); +} + +static void __exit as4610_54_cpld_exit(void) +{ + i2c_del_driver(&as4610_54_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as4610_54_cpld_init); +module_exit(as4610_54_cpld_exit); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c new file mode 100644 index 00000000..ab69fb19 --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c @@ -0,0 +1,377 @@ +/* + * A hwmon driver for the Accton as4610 fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4610_fan" + +static struct as4610_fan_data *as4610_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); +extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as4610_product_id(void); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x2B, /* fan PWM(for all fan) */ + 0x2D, /* fan 1 speed(rpm) */ + 0x2C, /* fan 2 speed(rpm) */ + 0x11, /* fan1-2 operating status */ +}; + +static struct as4610_fan_data *fan_data = NULL; + +/* Each client has this additional data */ +struct as4610_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID +}; + +enum sysfs_fan_attributes { + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_SPEED_RPM, + FAN2_SPEED_RPM, + FAN_FAULT, + FAN1_FAULT, + FAN2_FAULT +}; + +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.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_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_speed_rpm.dev_attr.attr + +/* fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +/* fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +static struct attribute *as4610_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_DUTY_CYCLE_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 as4610_fan_read_value(u8 reg) +{ + return as4610_54_cpld_read(0x30, reg); +} + +static int as4610_fan_write_value(u8 reg, u8 value) +{ + return as4610_54_cpld_write(0x30, 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 * 125 + 5)/10); +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 10 / 125); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + /* Count Frequency is 1.515KHz= 0.66ms + * Count Period = 400 cycle = 400*0.66ms = 264ms + * R.P.M value = read value x3.79*60/2 + * 3.79 = 1000ms/264ms + * 60 = 1min =60s + * 2 = 1 rotation of fan has two pulses. + */ + return (u32)reg_val * 379 * 60 / 2 / 100; +} + +static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id) +{ + u8 mask = (id == FAN1_ID) ? 0x20 : 0x10; + + return !(data->reg_val[FAN_FAULT] & mask); +} + +static ssize_t 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 < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as4610_fan_write_value(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 as4610_fan_data *data = as4610_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[attr->index]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_SPEED_RPM: + case FAN2_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_FAULT: + case FAN2_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as4610_fan_group = { + .attrs = as4610_fan_attributes, +}; + +static struct as4610_fan_data *as4610_fan_update_device(struct device *dev) +{ + mutex_lock(&fan_data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || + !fan_data->valid) { + int i; + + dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n"); + fan_data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) { + int status = as4610_fan_read_value(fan_reg[i]); + + if (status < 0) { + fan_data->valid = 0; + mutex_unlock(&fan_data->update_lock); + dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status); + return fan_data; + } + else { + fan_data->reg_val[i] = status; + } + } + + fan_data->last_updated = jiffies; + fan_data->valid = 1; + } + + mutex_unlock(&fan_data->update_lock); + + return fan_data; +} + +static int as4610_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as4610_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_as4610_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); +exit: + return status; +} + +static int as4610_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); + + return 0; +} + +static const struct i2c_device_id as4610_fan_id[] = { + { "as4610_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as4610_fan_id); + +static struct platform_driver as4610_fan_driver = { + .probe = as4610_fan_probe, + .remove = as4610_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int as4610_number_of_system_fan(void) +{ + int nFan = 0; + int pid = as4610_product_id(); + + switch (pid) { + case PID_AS4610_30P: + case PID_AS4610_54P: + nFan = 1; + break; + case PID_AS4610_54T_B: + nFan = 2; + break; + default: + nFan = 0; + break; + } + + return nFan; +} + +static int __init as4610_fan_init(void) +{ + int ret; + + if (as4610_number_of_system_fan() == 0) { + return -ENODEV; + } + + ret = platform_driver_register(&as4610_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&as4610_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(&as4610_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit as4610_fan_exit(void) +{ + if (!fan_data) { + return; + } + + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&as4610_fan_driver); + kfree(fan_data); +} + +late_initcall(as4610_fan_init); +module_exit(as4610_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4610_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c new file mode 100644 index 00000000..5771b0a5 --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c @@ -0,0 +1,685 @@ +/* + * A LED driver for the accton_as4610_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as4610_54_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as4610_product_id(void); + +#define DRVNAME "as4610_led" + +struct as4610_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int led_map; + u8 reg_val[5]; /* Register value, 0 = (0x1A) Blinking function + 1 = (0x30) 7-seg 2 + 2 = (0x31) 7-seg 1 + 3 = (0x32) SYS/PRI/PSU1-2 LED + 4 = (0x33) STK1-2/Fan/PoE/Alarm LED */ +}; + +static struct as4610_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_7SEG_REG_MASK 0x0F +#define LED_7SEG_POINT_REG_MASK 0x10 + +#define LED_NORMAL_MASK 0x03 +#define LED_NORMAL_GREEN_VALUE 0x02 +#define LED_NORMAL_AMBER_VALUE 0x01 +#define LED_NORMAL_OFF_VALUE 0x00 + +#define LED_TYPE_SYS_REG_MASK 0xC0 +#define LED_MODE_SYS_BLINK_MASK 0x80 + +#define LED_TYPE_PRI_REG_MASK 0x30 +#define LED_MODE_PRI_BLINK_MASK 0x40 + +#define LED_TYPE_PSU1_REG_MASK 0x0C +#define LED_MODE_PSU1_BLINK_MASK 0x20 + +#define LED_TYPE_PSU2_REG_MASK 0x03 +#define LED_MODE_PSU2_BLINK_MASK 0x10 + +#define LED_TYPE_STK1_REG_MASK 0xC0 +#define LED_MODE_STK1_BLINK_MASK 0x08 + +#define LED_TYPE_STK2_REG_MASK 0x30 +#define LED_MODE_STK2_BLINK_MASK 0x04 + +#define LED_TYPE_FAN_REG_MASK 0x0C +#define LED_MODE_FAN_BLINK_MASK 0x02 + +#define LED_TYPE_POE_ALARM_REG_MASK 0x03 +#define LED_MODE_POE_ALARM_BLINK_MASK 0x01 + +static const u8 led_reg[] = { + 0x1A, /* Blinking function */ + 0x30, /* 7-seg 1 */ + 0x31, /* 7-seg 2 */ + 0x32, /* SYS/PRI/PSU1-2 LED */ + 0x33, /* STK1-2/Fan/PoE/Alarm LED */ +}; + +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_PRI, + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_STK1, + LED_TYPE_STK2, + LED_TYPE_7SEG_TENS, + LED_TYPE_7SEG_TENS_POINT, + LED_TYPE_7SEG_DIGITS, + LED_TYPE_7SEG_DIGITS_POINT, + LED_TYPE_FAN, + LED_TYPE_POE, + LED_TYPE_ALARM, + NUM_OF_LED +}; + +#define AS4610_COMMON_LED_MAP (BIT(LED_TYPE_SYS) | BIT(LED_TYPE_PRI) | BIT(LED_TYPE_PSU1) | \ + BIT(LED_TYPE_PSU2)| BIT(LED_TYPE_STK1)| BIT(LED_TYPE_STK2)) +#define AS4610_NPOE_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_7SEG_TENS) | \ + BIT(LED_TYPE_7SEG_TENS_POINT) | BIT(LED_TYPE_7SEG_DIGITS) | \ + BIT(LED_TYPE_7SEG_DIGITS_POINT)) +#define AS4610_POE_LED_MAP (AS4610_NPOE_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_POE)) +#define AS4610_54T_B_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_ALARM)) + +static int as4610_ledmaps[] = { + [PID_AS4610_30T] = AS4610_NPOE_LED_MAP, + [PID_AS4610_30P] = AS4610_POE_LED_MAP, + [PID_AS4610_54T] = AS4610_NPOE_LED_MAP, + [PID_AS4610_54P] = AS4610_POE_LED_MAP, + [PID_AS4610_54T_B] = AS4610_54T_B_LED_MAP, + [PID_RESERVED] = 0, +}; + +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_AUTO_BLINKING, + LED_MODE_UNKNOWN, + LED_MODE_SEVEN_SEGMENT_MAX = 9, +}; + +static int as4610_led_read_value(u8 reg) +{ + return as4610_54_cpld_read(0x30, reg); +} + +static int as4610_led_write_value(u8 reg, u8 value) +{ + return as4610_54_cpld_write(0x30, reg, value); +} + +static void as4610_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 as4610_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as4610_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 enum led_brightness seven_segment_get(struct led_classdev *cdev, u8 reg_id) +{ + as4610_led_update(); + return (ledctl->reg_val[reg_id] & LED_7SEG_REG_MASK); +} + +static void seven_segment_set(struct led_classdev *cdev, enum led_brightness mode, u8 reg_id) +{ + if (mode > cdev->max_brightness) { + return; + } + + ledctl->reg_val[reg_id] &= 0xF0; + ledctl->reg_val[reg_id] |= mode; + as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); +} + +static enum led_brightness seven_segment_digits_get(struct led_classdev *cdev) +{ + return seven_segment_get(cdev, 1); +} + +static void seven_segment_digits_set(struct led_classdev *cdev, enum led_brightness mode) +{ + seven_segment_set(cdev, mode, 1); +} + +static enum led_brightness seven_segment_tens_get(struct led_classdev *cdev) +{ + return seven_segment_get(cdev, 2); +} + +static void seven_segment_tens_set(struct led_classdev *cdev, enum led_brightness mode) +{ + seven_segment_set(cdev, mode, 2); +} + +static enum led_brightness seven_segment_point_get(struct led_classdev *cdev, u8 reg_id) +{ + as4610_led_update(); + return (ledctl->reg_val[reg_id] & LED_7SEG_POINT_REG_MASK) ? LED_MODE_GREEN : LED_MODE_OFF; +} + +static void seven_segment_point_set(struct led_classdev *cdev, + enum led_brightness mode, u8 reg_id) +{ + /* Validate brightness */ + if ((int)mode < LED_MODE_OFF || mode > cdev->max_brightness) { + return; + } + + if ((int)mode == (int)LED_MODE_OFF) { + ledctl->reg_val[reg_id] &= ~LED_7SEG_POINT_REG_MASK; + } + else { /* LED_MODE_GREEN */ + ledctl->reg_val[reg_id] |= LED_7SEG_POINT_REG_MASK; + } + + as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); +} + +static enum led_brightness seven_segment_tens_point_get(struct led_classdev *cdev) +{ + return seven_segment_point_get(cdev, 2); +} + +static void seven_segment_tens_point_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + seven_segment_point_set(cdev, mode, 2); +} + +static enum led_brightness seven_segment_digits_point_get(struct led_classdev *cdev) +{ + return seven_segment_point_get(cdev, 1); +} + +static void seven_segment_digits_point_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + seven_segment_point_set(cdev, mode, 1); +} + +static u8 led_is_blinking_mode(enum led_brightness mode) +{ + return ((int)mode == (int)LED_MODE_GREEN_BLINK || + (int)mode == (int)LED_MODE_AMBER_BLINK || + (int)mode == (int)LED_MODE_AUTO_BLINKING); +} + +static enum led_brightness as4610_led_auto_get(u8 blink_mask) +{ + as4610_led_update(); + return (ledctl->reg_val[0] & blink_mask) ? LED_MODE_AUTO_BLINKING : LED_MODE_AUTO; +} + +static void as4610_led_auto_set(struct led_classdev *cdev, + enum led_brightness mode, u8 blink_mask) +{ + /* Validate brightness */ + if ((int)mode < (int)LED_MODE_AUTO || mode > cdev->max_brightness) { + return; + } + + /* Set blinking */ + if (led_is_blinking_mode(mode)) { + ledctl->reg_val[0] |= blink_mask; + } + else { + ledctl->reg_val[0] &= ~blink_mask; + } + as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); +} + +static enum led_brightness as4610_led_psu1_get(struct led_classdev *cdev) +{ + return as4610_led_auto_get(LED_MODE_PSU1_BLINK_MASK); +} + +static void as4610_led_psu1_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_auto_set(cdev, mode, LED_MODE_PSU1_BLINK_MASK); +} + +static enum led_brightness as4610_led_psu2_get(struct led_classdev *cdev) +{ + return as4610_led_auto_get(LED_MODE_PSU2_BLINK_MASK); +} + +static void as4610_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness mode) +{ + as4610_led_auto_set(led_cdev, mode, LED_MODE_PSU2_BLINK_MASK); +} + +static enum led_brightness as4610_led_fan_get(struct led_classdev *cdev) +{ + return as4610_led_auto_get(LED_MODE_FAN_BLINK_MASK); +} + +static void as4610_led_fan_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_auto_set(cdev, mode, LED_MODE_FAN_BLINK_MASK); +} + +static u8 led_normal_light_mode_to_reg_val(enum led_brightness mode) +{ + if (led_is_blinking_mode(mode)) { + mode -= 1; /* convert blinking mode to non-blinking mode */ + } + + if ((int)mode == (int)LED_MODE_GREEN) { + return LED_NORMAL_GREEN_VALUE; + } + else if ((int)mode == (int)LED_MODE_AMBER) { + return LED_NORMAL_AMBER_VALUE; + } + + return LED_NORMAL_OFF_VALUE; +} + +static enum led_brightness led_normal_reg_val_to_light_mode(u8 reg_val) +{ + reg_val &= LED_NORMAL_MASK; + + if (reg_val & LED_NORMAL_GREEN_VALUE) { + return LED_MODE_GREEN; + } + else if (reg_val & LED_NORMAL_AMBER_VALUE) { + return LED_MODE_AMBER; + } + + return LED_MODE_OFF; +} + +static void as4610_led_normal_set(struct led_classdev *cdev, + enum led_brightness mode, u8 blink_mask, u8 reg_id, u8 reg_mask, u8 shift) +{ + /* Validate brightness */ + if (mode > cdev->max_brightness) { + return; + } + + /* Set blinking */ + if (led_is_blinking_mode(mode)) { + ledctl->reg_val[0] |= blink_mask; + } + else { + ledctl->reg_val[0] &= ~blink_mask; + } + as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); + + /* Set color */ + ledctl->reg_val[reg_id] &= ~reg_mask; + ledctl->reg_val[reg_id] |= (led_normal_light_mode_to_reg_val(mode) << shift); + as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); +} + +static enum led_brightness as4610_led_normal_get(u8 reg_id, u8 blink_mask, u8 shift) +{ + u8 blinking = 0; + enum led_brightness mode; + + as4610_led_update(); + + mode = led_normal_reg_val_to_light_mode(ledctl->reg_val[reg_id] >> shift); + if ((int)mode == (int)LED_MODE_OFF) { + return mode; + } + + /* Checking blinking */ + if (ledctl->reg_val[0] & blink_mask) { + blinking = 1; + } + + return blinking ? (mode+1) : mode; +} + +static void as4610_led_sys_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_normal_set(cdev, mode, LED_MODE_SYS_BLINK_MASK, + 3, LED_TYPE_SYS_REG_MASK, 6); +} + +static enum led_brightness as4610_led_sys_get(struct led_classdev *cdev) +{ + return as4610_led_normal_get(3, LED_MODE_SYS_BLINK_MASK, 6); +} + +static void as4610_led_pri_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_normal_set(cdev, mode, LED_MODE_PRI_BLINK_MASK, + 3, LED_TYPE_PRI_REG_MASK, 4); +} + +static enum led_brightness as4610_led_pri_get(struct led_classdev *cdev) +{ + return as4610_led_normal_get(3, LED_MODE_PRI_BLINK_MASK, 4); +} + +static void as4610_led_poe_alarm_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_normal_set(cdev, mode, LED_MODE_POE_ALARM_BLINK_MASK, + 4, LED_TYPE_POE_ALARM_REG_MASK, 0); +} + +static enum led_brightness as4610_led_poe_alarm_get(struct led_classdev *cdev) +{ + return as4610_led_normal_get(4, LED_MODE_POE_ALARM_BLINK_MASK, 0); +} + +static void as4610_led_stk1_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_normal_set(cdev, mode, LED_MODE_STK1_BLINK_MASK, + 4, LED_TYPE_STK1_REG_MASK, 6); +} + +static enum led_brightness as4610_led_stk1_get(struct led_classdev *cdev) +{ + return as4610_led_normal_get(4, LED_MODE_STK1_BLINK_MASK, 6); +} + +static void as4610_led_stk2_set(struct led_classdev *cdev, + enum led_brightness mode) +{ + as4610_led_normal_set(cdev, mode, LED_MODE_STK2_BLINK_MASK, + 4, LED_TYPE_STK2_REG_MASK, 4); +} + +static enum led_brightness as4610_led_stk2_get(struct led_classdev *cdev) +{ + return as4610_led_normal_get(4, LED_MODE_STK2_BLINK_MASK, 4); +} + +static struct led_classdev as4610_leds[] = { + [LED_TYPE_SYS] = { + .name = "as4610::sys", + .default_trigger = "unused", + .brightness_set = as4610_led_sys_set, + .brightness_get = as4610_led_sys_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_PRI] = { + .name = "as4610::pri", + .default_trigger = "unused", + .brightness_set = as4610_led_pri_set, + .brightness_get = as4610_led_pri_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_PSU1] = { + .name = "as4610::psu1", + .default_trigger = "unused", + .brightness_set = as4610_led_psu1_set, + .brightness_get = as4610_led_psu1_get, + .max_brightness = LED_MODE_AUTO_BLINKING, + }, + [LED_TYPE_PSU2] = { + .name = "as4610::psu2", + .default_trigger = "unused", + .brightness_set = as4610_led_psu2_set, + .brightness_get = as4610_led_psu2_get, + .max_brightness = LED_MODE_AUTO_BLINKING, + }, + [LED_TYPE_STK1] = { + .name = "as4610::stk1", + .default_trigger = "unused", + .brightness_set = as4610_led_stk1_set, + .brightness_get = as4610_led_stk1_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_STK2] = { + .name = "as4610::stk2", + .default_trigger = "unused", + .brightness_set = as4610_led_stk2_set, + .brightness_get = as4610_led_stk2_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_7SEG_TENS] = { + .name = "as4610::7seg_tens", + .default_trigger = "unused", + .brightness_set = seven_segment_tens_set, + .brightness_get = seven_segment_tens_get, + .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, + }, + [LED_TYPE_7SEG_TENS_POINT] = { + .name = "as4610::7seg_tens_point", + .default_trigger = "unused", + .brightness_set = seven_segment_tens_point_set, + .brightness_get = seven_segment_tens_point_get, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_7SEG_DIGITS] = { + .name = "as4610::7seg_digits", + .default_trigger = "unused", + .brightness_set = seven_segment_digits_set, + .brightness_get = seven_segment_digits_get, + .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, + }, + [LED_TYPE_7SEG_DIGITS_POINT] = { + .name = "as4610::7seg_digits_point", + .default_trigger = "unused", + .brightness_set = seven_segment_digits_point_set, + .brightness_get = seven_segment_digits_point_get, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_FAN] = { + .name = "as4610::fan", + .default_trigger = "unused", + .brightness_set = as4610_led_fan_set, + .brightness_get = as4610_led_fan_get, + .max_brightness = LED_MODE_AUTO_BLINKING, + }, + [LED_TYPE_POE] = { + .name = "as4610::poe", + .default_trigger = "unused", + .brightness_set = as4610_led_poe_alarm_set, + .brightness_get = as4610_led_poe_alarm_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_ALARM] = { + .name = "as4610::alarm", + .default_trigger = "unused", + .brightness_set = as4610_led_poe_alarm_set, + .brightness_get = as4610_led_poe_alarm_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, +}; + +static int as4610_led_probe(struct platform_device *pdev) +{ + int ret = 0, i; + + for (i = 0; i < NUM_OF_LED; i++) { + if (!(ledctl->led_map & BIT(i))) { + continue; + } + + ret = led_classdev_register(&pdev->dev, &as4610_leds[i]); + if (ret < 0) { + goto error; + } + } + + return 0; + +error: + for (i = i-1; i >= 0; i--) { + /* only unregister the LEDs that were successfully registered */ + if (!(ledctl->led_map & BIT(i))) { + continue; + } + + led_classdev_unregister(&as4610_leds[i]); + } + + return ret; +} + +static int as4610_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < NUM_OF_LED; i++) { + if (!(ledctl->led_map & BIT(i))) { + continue; + } + + led_classdev_unregister(&as4610_leds[i]); + } + + return 0; +} + +static struct platform_driver as4610_led_driver = { + .probe = as4610_led_probe, + .remove = as4610_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as4610_led_init(void) +{ + int ret, pid; + + if (as4610_product_id() == PID_UNKNOWN) { + return -ENODEV; + } + + ret = platform_driver_register(&as4610_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as4610_led_driver); + goto exit; + } + + pid = as4610_product_id(); + if (pid == PID_UNKNOWN) { + return -ENODEV; + } + + ledctl->led_map = as4610_ledmaps[pid]; + 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(&as4610_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit as4610_led_exit(void) +{ + if (!ledctl) { + return; + } + + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as4610_led_driver); + kfree(ledctl); +} + +late_initcall(as4610_led_init); +module_exit(as4610_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4610_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c new file mode 100644 index 00000000..68f0348d --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c @@ -0,0 +1,286 @@ +/* + * An hwmon driver for accton as4610 Power Module + * + * Copyright (C) 2016 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 as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as4610_54_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 as4610_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 as4610_psu_data *as4610_psu_update_device(struct device *dev); + +enum as4610_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 *as4610_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 as4610_psu_data *data = as4610_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = (data->status >> (data->index*2) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (data->index*2 + 1) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as4610_psu_data *data = as4610_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as4610_psu_group = { + .attrs = as4610_psu_attributes, +}; + +static int as4610_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as4610_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as4610_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, &as4610_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, &as4610_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as4610_psu_remove(struct i2c_client *client) +{ + struct as4610_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as4610_psu1, + as4610_psu2 +}; + +static const struct i2c_device_id as4610_psu_id[] = { + { "as4610_psu1", as4610_psu1 }, + { "as4610_psu2", as4610_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as4610_psu_id); + +static struct i2c_driver as4610_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as4610_psu", + }, + .probe = as4610_psu_probe, + .remove = as4610_psu_remove, + .id_table = as4610_psu_id, + .address_list = normal_i2c, +}; + +static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data, + int count) +{ + int status = 0; + + while (count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + break; + } + + *data = (u8)status; + data += 1; + command += 1; + count -= 1; + } + + return status; +} + +static struct as4610_psu_data *as4610_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4610_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 present = 0; + + data->valid = 0; + data->status = 0; + dev_dbg(&client->dev, "Starting as4610 update\n"); + + /* Read psu status */ + status = as4610_54_cpld_read(0x30, 0x11); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); + goto exit; + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + present = (data->status >> (data->index*2) & 0x1); + + if (present) { + int len = ARRAY_SIZE(data->model_name)-1; + + status = as4610_psu_read_data(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); + goto exit; + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as4610_psu_init(void) +{ + return i2c_add_driver(&as4610_psu_driver); +} + +static void __exit as4610_psu_exit(void) +{ + i2c_del_driver(&as4610_psu_driver); +} + +module_init(as4610_psu_init); +module_exit(as4610_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4610_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/modules/builds/optoe.c b/packages/platforms/accton/x86-64/modules/builds/optoe.c deleted file mode 100755 index b3064f02..00000000 --- a/packages/platforms/accton/x86-64/modules/builds/optoe.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * optoe.c - A driver to read and write the EEPROM on optical transceivers - * (SFP, QSFP and similar I2C based devices) - * - * Copyright (C) 2014 Cumulus networks Inc. - * Copyright (C) 2017 Finisar 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 Freeoftware Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/* - * Description: - * a) Optical transceiver EEPROM read/write transactions are just like - * the at24 eeproms managed by the at24.c i2c driver - * b) The register/memory layout is up to 256 128 byte pages defined by - * a "pages valid" register and switched via a "page select" - * register as explained in below diagram. - * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 - * bytes of address space, and always references the same - * location, independent of the page select register. - * All mapped pages are mapped into the upper 128 bytes - * (offset 128-255) of the i2c address. - * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 - * (A0h in the spec), and map all pages in the upper 128 bytes - * of that address. - * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data - * at I2C address 0x50, and 256 bytes of data at I2C address - * 0x51 (A2h in the spec). Page selection and paged access - * only apply to this second I2C address (0x51). - * e) The address space is presented, by the driver, as a linear - * address space. For devices with one I2C client at address - * 0x50 (eg QSFP), offset 0-127 are in the lower - * half of address 50/A0h/client[0]. Offset 128-255 are in - * page 0, 256-383 are page 1, etc. More generally, offset - * 'n' resides in page (n/128)-1. ('page -1' is the lower - * half, offset 0-127). - * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), - * the address space places offset 0-127 in the lower - * half of 50/A0/client[0], offset 128-255 in the upper - * half. Offset 256-383 is in the lower half of 51/A2/client[1]. - * Offset 384-511 is in page 0, in the upper half of 51/A2/... - * Offset 512-639 is in page 1, in the upper half of 51/A2/... - * Offset 'n' is in page (n/128)-3 (for n > 383) - * - * One I2c addressed (eg QSFP) Memory Map - * - * 2-Wire Serial Address: 1010000x - * - * Lower Page 00h (128 bytes) - * ===================== - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * |Page Select Byte(127)| - * ===================== - * | - * | - * | - * | - * V - * ------------------------------------------------------------ - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * V V V V - * ------------ -------------- --------------- -------------- - * | | | | | | | | - * | Upper | | Upper | | Upper | | Upper | - * | Page 00h | | Page 01h | | Page 02h | | Page 03h | - * | | | (Optional) | | (Optional) | | (Optional | - * | | | | | | | for Cable | - * | | | | | | | Assemblies) | - * | ID | | AST | | User | | | - * | Fields | | Table | | EEPROM Data | | | - * | | | | | | | | - * | | | | | | | | - * | | | | | | | | - * ------------ -------------- --------------- -------------- - * - * The SFF 8436 (QSFP) spec only defines the 4 pages described above. - * In anticipation of future applications and devices, this driver - * supports access to the full architected range, 256 pages. - * - **/ - -/* #define DEBUG 1 */ - -#undef EEPROM_CLASS -#ifdef CONFIG_EEPROM_CLASS -#define EEPROM_CLASS -#endif -#ifdef CONFIG_EEPROM_CLASS_MODULE -#define EEPROM_CLASS -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef EEPROM_CLASS -#include -#endif - -#include - -/* The maximum length of a port name */ -#define MAX_PORT_NAME_LEN 20 - -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - void *dummy1; /* backward compatibility */ - void *dummy2; /* backward compatibility */ - -#ifdef EEPROM_CLASS - struct eeprom_platform_data *eeprom_data; -#endif - char port_name[MAX_PORT_NAME_LEN]; -}; - -/* fundamental unit of addressing for EEPROM */ -#define OPTOE_PAGE_SIZE 128 -/* - * Single address devices (eg QSFP) have 256 pages, plus the unpaged - * low 128 bytes. If the device does not support paging, it is - * only 2 'pages' long. - */ -#define OPTOE_ARCH_PAGES 256 -#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) -/* - * Dual address devices (eg SFP) have 256 pages, plus the unpaged - * low 128 bytes, plus 256 bytes at 0x50. If the device does not - * support paging, it is 4 'pages' long. - */ -#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) -#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define OPTOE_PAGE_SELECT_REG 0x7F -#define ONE_ADDR_PAGEABLE_REG 0x02 -#define ONE_ADDR_NOT_PAGEABLE (1<<2) -#define TWO_ADDR_PAGEABLE_REG 0x40 -#define TWO_ADDR_PAGEABLE (1<<4) -#define TWO_ADDR_0X51_REG 92 -#define TWO_ADDR_0X51_SUPP (1<<6) -#define OPTOE_ID_REG 0 -#define OPTOE_READ_OP 0 -#define OPTOE_WRITE_OP 1 -#define OPTOE_EOF 0 /* used for access beyond end of device */ - -struct optoe_data { - struct optoe_platform_data chip; - int use_smbus; - char port_name[MAX_PORT_NAME_LEN]; - - /* - * Lock protects against activities from other Linux tasks, - * but not from changes by other I2C masters. - */ - struct mutex lock; - struct bin_attribute bin; - struct attribute_group attr_group; - - u8 *writebuf; - unsigned int write_max; - - unsigned int num_addresses; - -#ifdef EEPROM_CLASS - struct eeprom_device *eeprom_dev; -#endif - - /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ - int dev_class; - - 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 int io_limit = OPTOE_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned int write_timeout = 25; - -/* - * flags to distinguish one-address (QSFP family) from two-address (SFP family) - * If the family is not known, figure it out when the device is accessed - */ -#define ONE_ADDR 1 -#define TWO_ADDR 2 - -static const struct i2c_device_id optoe_ids[] = { - { "optoe1", ONE_ADDR }, - { "optoe2", TWO_ADDR }, - { "sff8436", ONE_ADDR }, - { "24c04", TWO_ADDR }, - { /* END OF LIST */ } -}; -MODULE_DEVICE_TABLE(i2c, optoe_ids); - -/*-------------------------------------------------------------------------*/ -/* - * 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 single address (eg QSFP) and two address (eg SFP). - * 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 optoe_translate_offset(struct optoe_data *optoe, - loff_t *offset, struct i2c_client **client) -{ - unsigned int page = 0; - - *client = optoe->client[0]; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (optoe->dev_class == TWO_ADDR) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = optoe->client[1]; - *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 < OPTOE_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 = OPTOE_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t optoe_eeprom_read(struct optoe_data *optoe, - struct i2c_client *client, - char *buf, unsigned int 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 (optoe->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 (optoe->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 */ - usleep_range(1000, 2000); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t optoe_eeprom_write(struct optoe_data *optoe, - struct i2c_client *client, - const char *buf, - unsigned int offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned int next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > optoe->write_max) - count = optoe->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (optoe->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 = optoe->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 (optoe->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 */ - usleep_range(1000, 2000); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, - char *buf, loff_t off, - size_t count, int opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - uint8_t page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = optoe_translate_offset(optoe, &phy_offset, &client); - dev_dbg(&client->dev, - "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - __func__, off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_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 == OPTOE_READ_OP) { - status = optoe_eeprom_read(optoe, client, - buf, phy_offset, count); - } else { - status = optoe_eeprom_write(optoe, 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 = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to 0 failed:%d!\n", ret); - /* error only if nothing has been transferred */ - if (retval == 0) - retval = 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 OPTOE_EOF (zero) - */ -static ssize_t optoe_page_legal(struct optoe_data *optoe, - loff_t off, size_t len) -{ - struct i2c_client *client = optoe->client[0]; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) - return -EINVAL; - if (optoe->dev_class == TWO_ADDR) { - /* SFP case */ - /* if only using addr 0x50 (first 256 bytes) we're good */ - if ((off + len) <= TWO_ADDR_NO_0X51_SIZE) - return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= TWO_ADDR_EEPROM_SIZE) - return OPTOE_EOF; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_PAGEABLE_REG, 1); - if (status < 0) - return status; /* error out (no module?) */ - if (regval & TWO_ADDR_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = TWO_ADDR_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) - return OPTOE_EOF; - - /* will be accessing addr 0x51, is that supported? */ - /* byte 92, bit 6 implies DDM support, 0x51 support */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_0X51_REG, 1); - if (status < 0) - return status; - if (regval & TWO_ADDR_0X51_SUPP) { - /* addr 0x51 is OK */ - maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* addr 0x51 NOT supported, trim to 256 max */ - if (off >= TWO_ADDR_NO_0X51_SIZE) - return OPTOE_EOF; - maxlen = TWO_ADDR_NO_0X51_SIZE - off; - } - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } else { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) - return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= ONE_ADDR_EEPROM_SIZE) - return OPTOE_EOF; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - ONE_ADDR_PAGEABLE_REG, 1); - if (status < 0) - return status; /* error out (no module?) */ - if (regval & ONE_ADDR_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) - return OPTOE_EOF; - maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = ONE_ADDR_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - return len; -} - -static ssize_t optoe_read_write(struct optoe_data *optoe, - char *buf, loff_t off, size_t len, int opcode) -{ - struct i2c_client *client = optoe->client[0]; - 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; - - dev_dbg(&client->dev, - "%s: off %lld len:%ld, opcode:%s\n", - __func__, off, (long int) len, - (opcode == OPTOE_READ_OP) ? "r" : "w"); - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&optoe->lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - status = optoe_page_legal(optoe, off, len); - if ((status == OPTOE_EOF) || (status < 0)) { - mutex_unlock(&optoe->lock); - return status; - } - len = status; - - /* - * 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 * OPTOE_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = OPTOE_PAGE_SIZE - off; - } else { - chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_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 = optoe_eeprom_update_client(optoe, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - if (status > 0) - retval += status; - if (retval == 0) - retval = status; - break; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&optoe->lock); - - return retval; -} - -static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); -} - - -static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); -} - -static int optoe_remove(struct i2c_client *client) -{ - struct optoe_data *optoe; - int i; - - optoe = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); - - for (i = 1; i < optoe->num_addresses; i++) - i2c_unregister_device(optoe->client[i]); - -#ifdef EEPROM_CLASS - eeprom_device_unregister(optoe->eeprom_dev); -#endif - - kfree(optoe->writebuf); - kfree(optoe); - return 0; -} - -static ssize_t show_dev_class(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%d\n", optoe->dev_class); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_dev_class(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - int dev_class; - - /* - * dev_class is actually the number of i2c addresses used, thus - * legal values are "1" (QSFP class) and "2" (SFP class) - */ - - if (kstrtoint(buf, 0, &dev_class) != 0 || - dev_class < 1 || dev_class > 2) - return -EINVAL; - - mutex_lock(&optoe->lock); - optoe->dev_class = dev_class; - mutex_unlock(&optoe->lock); - - return count; -} - -/* - * if using the EEPROM CLASS driver, we don't report a port_name, - * the EEPROM CLASS drive handles that. Hence all this code is - * only compiled if we are NOT using the EEPROM CLASS driver. - */ -#ifndef EEPROM_CLASS - -static ssize_t show_port_name(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%s\n", optoe->port_name); - mutex_unlock(&optoe->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 optoe_data *optoe = 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(&optoe->lock); - strcpy(optoe->port_name, port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); -#endif /* if NOT defined EEPROM_CLASS, the common case */ - -static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); - -static struct attribute *optoe_attrs[] = { -#ifndef EEPROM_CLASS - &dev_attr_port_name.attr, -#endif - &dev_attr_dev_class.attr, - NULL, -}; - -static struct attribute_group optoe_attr_group = { - .attrs = optoe_attrs, -}; - -static int optoe_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - int use_smbus = 0; - struct optoe_platform_data chip; - struct optoe_data *optoe; - int num_addresses = 0; - char port_name[MAX_PORT_NAME_LEN]; - - if (client->addr != 0x50) { - dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", - client->addr); - err = -EINVAL; - goto exit; - } - - if (client->dev.platform_data) { - chip = *(struct optoe_platform_data *)client->dev.platform_data; - /* take the port name from the supplied platform data */ -#ifdef EEPROM_CLASS - strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN); -#else - memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN); -#endif - dev_dbg(&client->dev, - "probe, chip provided, flags:0x%x; name: %s\n", - chip.flags, client->name); - } else { - if (!id->driver_data) { - err = -ENODEV; - goto exit; - } - dev_dbg(&client->dev, "probe, building chip\n"); - strcpy(port_name, "unitialized"); - chip.flags = 0; -#ifdef EEPROM_CLASS - chip.eeprom_data = NULL; -#endif - } - - /* 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 { - err = -EPFNOSUPPORT; - goto exit; - } - } - - - /* - * Make room for two i2c clients - */ - num_addresses = 2; - - optoe = kzalloc(sizeof(struct optoe_data) + - num_addresses * sizeof(struct i2c_client *), - GFP_KERNEL); - if (!optoe) { - err = -ENOMEM; - goto exit; - } - - mutex_init(&optoe->lock); - - /* determine whether this is a one-address or two-address module */ - if ((strcmp(client->name, "optoe1") == 0) || - (strcmp(client->name, "sff8436") == 0)) { - /* one-address (eg QSFP) family */ - optoe->dev_class = ONE_ADDR; - chip.byte_len = ONE_ADDR_EEPROM_SIZE; - num_addresses = 1; - } else if ((strcmp(client->name, "optoe2") == 0) || - (strcmp(client->name, "24c04") == 0)) { - /* SFP family */ - optoe->dev_class = TWO_ADDR; - chip.byte_len = TWO_ADDR_EEPROM_SIZE; - } else { /* those were the only two choices */ - err = -EINVAL; - goto exit; - } - - dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); - optoe->use_smbus = use_smbus; - optoe->chip = chip; - optoe->num_addresses = num_addresses; - memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); - - /* - * 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(&optoe->bin); - optoe->bin.attr.name = "eeprom"; - optoe->bin.attr.mode = 0444; - optoe->bin.read = optoe_bin_read; - optoe->bin.size = chip.byte_len; - - if (!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 int write_max = 1; - - optoe->bin.write = optoe_bin_write; - optoe->bin.attr.mode |= 0200; - - if (write_max > io_limit) - write_max = io_limit; - if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - optoe->write_max = write_max; - - /* buffer (data + address at the beginning) */ - optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!optoe->writebuf) { - err = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - optoe->client[0] = client; - - /* SFF-8472 spec requires that the second I2C address be 0x51 */ - if (num_addresses == 2) { - optoe->client[1] = i2c_new_dummy(client->adapter, 0x51); - if (!optoe->client[1]) { - dev_err(&client->dev, "address 0x51 unavailable\n"); - err = -EADDRINUSE; - goto err_struct; - } - } - - /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); - if (err) - goto err_struct; - - optoe->attr_group = optoe_attr_group; - - err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); - if (err) { - dev_err(&client->dev, "failed to create sysfs attribute group.\n"); - goto err_struct; - } - -#ifdef EEPROM_CLASS - optoe->eeprom_dev = eeprom_device_register(&client->dev, - chip.eeprom_data); - if (IS_ERR(optoe->eeprom_dev)) { - dev_err(&client->dev, "error registering eeprom device.\n"); - err = PTR_ERR(optoe->eeprom_dev); - goto err_sysfs_cleanup; - } -#endif - - i2c_set_clientdata(client, optoe); - - dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", - optoe->bin.size, client->name, - optoe->bin.write ? "read/write" : "read-only"); - - if (use_smbus == I2C_SMBUS_WORD_DATA || - use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, - "Falling back to %s reads, performance will suffer\n", - use_smbus == I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } - - return 0; - -#ifdef EEPROM_CLASS -err_sysfs_cleanup: - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); -#endif - -err_struct: - if (num_addresses == 2) { - if (optoe->client[1]) - i2c_unregister_device(optoe->client[1]); - } - - kfree(optoe->writebuf); -exit_kfree: - kfree(optoe); -exit: - dev_dbg(&client->dev, "probe error %d\n", err); - - return err; -} - -/*-------------------------------------------------------------------------*/ - -static struct i2c_driver optoe_driver = { - .driver = { - .name = "optoe", - .owner = THIS_MODULE, - }, - .probe = optoe_probe, - .remove = optoe_remove, - .id_table = optoe_ids, -}; - -static int __init optoe_init(void) -{ - - if (!io_limit) { - pr_err("optoe: io_limit must not be 0!\n"); - return -EINVAL; - } - - io_limit = rounddown_pow_of_two(io_limit); - return i2c_add_driver(&optoe_driver); -} -module_init(optoe_init); - -static void __exit optoe_exit(void) -{ - i2c_del_driver(&optoe_driver); -} -module_exit(optoe_exit); - -MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); -MODULE_AUTHOR("DON BOLLINGER "); -MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c new file mode 100644 index 00000000..ba36420c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c @@ -0,0 +1,1117 @@ +/* + * 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 as5512_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 { + as5512_54x_cpld1, + as5512_54x_cpld2, + as5512_54x_cpld3 +}; + +struct as5512_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5512_54x_cpld_id[] = { + { "as5512_54x_cpld1", as5512_54x_cpld1 }, + { "as5512_54x_cpld2", as5512_54x_cpld2 }, + { "as5512_54x_cpld3", as5512_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5512_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 + +enum as5512_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 as5512_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5512_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 *as5512_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5512_54x_cpld1_group = { + .attrs = as5512_54x_cpld1_attributes, +}; + +static struct attribute *as5512_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 as5512_54x_cpld2_group = { + .attrs = as5512_54x_cpld2_attributes, +}; + +static struct attribute *as5512_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 as5512_54x_cpld3_group = { + .attrs = as5512_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 as5512_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5512_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5512_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 == as5512_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5512_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 as5512_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5512_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 as5512_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 = 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 ... MODULE_PRESENT_54: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + 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 = as5512_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 as5512_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 = 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 = as5512_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5512_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 as5512_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 = as5512_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 as5512_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 as5512_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 as5512_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5512_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 as5512_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 as5512_54x_cpld1: + group = &as5512_54x_cpld1_group; + break; + case as5512_54x_cpld2: + group = &as5512_54x_cpld2_group; + break; + case as5512_54x_cpld3: + group = &as5512_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5512_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5512_54x_cpld_remove(struct i2c_client *client) +{ + struct as5512_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5512_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5512_54x_cpld1: + group = &as5512_54x_cpld1_group; + break; + case as5512_54x_cpld2: + group = &as5512_54x_cpld2_group; + break; + case as5512_54x_cpld3: + group = &as5512_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5512_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 as5512_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 as5512_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 = as5512_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5512_54x_cpld_read); + +int as5512_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 = as5512_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5512_54x_cpld_write); + +static struct i2c_driver as5512_54x_cpld_driver = { + .driver = { + .name = "as5512_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5512_54x_cpld_probe, + .remove = as5512_54x_cpld_remove, + .id_table = as5512_54x_cpld_id, +}; + +static int __init as5512_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5512_54x_cpld_driver); +} + +static void __exit as5512_54x_cpld_exit(void) +{ + i2c_del_driver(&as5512_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5512_54x_cpld_init); +module_exit(as5512_54x_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c index 67e3dd66..9f2bbf59 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c @@ -131,8 +131,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev, 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); +extern int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5512_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); /*******************/ @@ -269,12 +269,12 @@ static const struct attribute_group accton_as5512_54x_fan_group = { static int accton_as5512_54x_fan_read_value(u8 reg) { - return accton_i2c_cpld_read(0x60, reg); + return as5512_54x_cpld_read(0x60, reg); } static int accton_as5512_54x_fan_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(0x60, reg, value); + return as5512_54x_cpld_write(0x60, reg, value); } static void accton_as5512_54x_fan_update_device(struct device *dev) @@ -405,11 +405,6 @@ static int __init accton_as5512_54x_fan_init(void) { int ret; - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - ret = platform_driver_register(&accton_as5512_54x_fan_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c index 43160557..02eb3d7e 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c @@ -29,8 +29,8 @@ #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 int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5512_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); #define DRVNAME "as5512_54x_led" @@ -168,12 +168,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type, static int accton_as5512_54x_led_read_value(u8 reg) { - return accton_i2c_cpld_read(0x60, reg); + return as5512_54x_cpld_read(0x60, reg); } static int accton_as5512_54x_led_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(0x60, reg, value); + return as5512_54x_cpld_write(0x60, reg, value); } static void accton_as5512_54x_led_update(void) @@ -411,11 +411,6 @@ static int __init accton_as5512_54x_led_init(void) { int ret; - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - ret = platform_driver_register(&accton_as5512_54x_led_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c index 66d61f3c..fb5e02ca 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c @@ -36,7 +36,7 @@ static ssize_t show_index(struct device *dev, struct device_attribute *da, char 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 as5512_54x_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); +extern int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ @@ -253,7 +253,7 @@ static struct as5512_54x_psu_data *as5512_54x_psu_update_device(struct device *d } /* Read psu status */ - status = accton_i2c_cpld_read(0x60, 0x2); + status = as5512_54x_cpld_read(0x60, 0x2); if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); @@ -271,25 +271,9 @@ static struct as5512_54x_psu_data *as5512_54x_psu_update_device(struct device *d return data; } -static int __init as5512_54x_psu_init(void) -{ - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - - return i2c_add_driver(&as5512_54x_psu_driver); -} - -static void __exit as5512_54x_psu_exit(void) -{ - i2c_del_driver(&as5512_54x_psu_driver); -} +module_i2c_driver(as5512_54x_psu_driver); MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("accton as5512_54x_psu driver"); MODULE_LICENSE("GPL"); -module_init(as5512_54x_psu_init); -module_exit(as5512_54x_psu_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c deleted file mode 100644 index d89e71d0..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * SFP driver for accton as5512_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 "as5512_54x_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 54 -#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, -sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, -sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, -sfp49, sfp50, sfp51, sfp52, sfp53, sfp54 -}; - -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 }, -{ "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 }, -{ "sfp49", sfp49 }, { "sfp50", sfp50 }, { "sfp51", sfp51 }, { "sfp52", sfp52 }, -{ "sfp53", sfp53 }, { "sfp54", 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; -}; - -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 -}; - -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) -{ - 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 = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - data = ERR_PTR(status); - 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 = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - data = ERR_PTR(status); - 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 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 as5512_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 = accton_i2c_cpld_read(cpld_addr, reg); - if (unlikely(status < 0)) { - data = ERR_PTR(status); - 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 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; - - 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 = 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; -} - -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); - } -} - -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) { - 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}; - - 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)) { - data = ERR_PTR(status); - 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)) { - data = ERR_PTR(status); - 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 data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int status; - 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); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - 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 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 status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct sfp_port_data *data = NULL; - - 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 (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; - } - - 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) ? 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 = 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)) ? 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_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); - -/* 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_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_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, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -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_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 -}; - -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) -{ - 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)); - 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, result); - 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) -{ - 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 */ - accton_i2c_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; -} - -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 >= sfp1 && dev_id->driver_data <= 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 { /* sfp49 ~ 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; -} - -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) -{ - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_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 as5512_54x_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c index 141b8645..f4c59343 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c @@ -24,58 +24,53 @@ * ***********************************************************/ #include - -#include /* For O_RDWR && open */ -#include -#include -#include -#include - -#include "platform_lib.h" - -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; +#include +#include +#include "x86_64_accton_as5512_54x_int.h" +#include "x86_64_accton_as5512_54x_log.h" #define MUX_START_INDEX 2 -#define NUM_OF_SFP_PORT 54 -static const int sfp_mux_index[NUM_OF_SFP_PORT] = { - 0, 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, -52, 50, 48, 53, 51, 49 -}; -#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]+MUX_START_INDEX) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_present_all" +#define MODULE_PRESENT_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all" -static int -sfp_node_read_int(char *node_path, int *value, int data_len) +static int front_port_bus_index(int port) { - int ret = 0; - char buf[8] = {0}; - *value = 0; + int rport = 0; - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); + switch (port) + { + case 48: + rport = 52; + break; + case 49: + rport = 50; + break; + case 50: + rport = 48; + break; + case 51: + rport = 53; + break; + case 52: + rport = 51; + break; + case 53: + rport = 49; + break; + default: + rport = port; + break; } - return ret; -} - -static char* -sfp_get_port_path_addr(int port, int addr, char *node_name) -{ - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - FRONT_PORT_TO_MUX_INDEX(port), addr, - node_name); - return sfp_node_path; -} - -static char* -sfp_get_port_path(int port, char *node_name) -{ - return sfp_get_port_path_addr(port, 50, node_name); + return (rport + MUX_START_INDEX); } /************************************************************ @@ -114,10 +109,10 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - - if (sfp_node_read_int(path, &present, 0) != 0) { - AIM_LOG_INFO("Unable to read present status from port(%d)\r\n", port); + int addr = (port < 24) ? 61 : 62; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -128,29 +123,35 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[7]; - char* path; FILE* fp; - path = sfp_get_port_path(0, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of port 0~23 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD2, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD2."); return ONLP_STATUS_E_INTERNAL; } - int count = fscanf(fp, "%x %x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5, - bytes+6 - ); + + int count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { + if(count != 3) { /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD2."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Read present status of port 24~53 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD3, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD3."); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x", bytes+3, bytes+4, bytes+5, bytes+6); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD3."); return ONLP_STATUS_E_INTERNAL; } @@ -177,33 +178,39 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7]; - char* path; + uint32_t bytes[6]; + uint32_t *ptr = bytes; FILE* fp; - path = sfp_get_port_path(0, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of port 0~23 */ + int addr, i = 0; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5 - ); - fclose(fp); - if(count != 6) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 61; addr <= 62; addr++) { + if (addr == 61) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; } /* Convert to 64 bit integer in port order */ - int i = 0; + i = 0; uint64_t rx_los_all = 0 ; for(i = 5; i >= 0; i--) { rx_los_all <<= 8; @@ -222,18 +229,22 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - /* * Read the SFP eeprom into data[] * * Return MISSING if SFP is missing. * Return OK if eeprom is read */ + int size = 0; memset(data, 0, 256); - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -243,17 +254,60 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); - memset(data, 0, 256); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); return ONLP_STATUS_E_INTERNAL; } return ONLP_STATUS_OK; } +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { @@ -263,13 +317,13 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - char* path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -291,19 +345,18 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; if (port < 0 || port >= 48) { return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = sfp_get_port_path(port, "sfp_rx_los"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -315,9 +368,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = sfp_get_port_path(port, "sfp_tx_fault"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -329,9 +380,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py index 5f00ee18..3e920af3 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py @@ -8,10 +8,10 @@ class OnlPlatform_x86_64_accton_as5512_54x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".5512.54.1" def baseconfig(self): - + self.insmod('optoe') self.insmod('cpr_4011_4mxx') - self.insmod('accton_i2c_cpld') - self.insmod_platform() + for m in [ 'cpld', 'fan', 'psu', 'leds' ]: + self.insmod("x86-64-accton-as5512-54x-%s.ko" % m) ########### initialize I2C bus 0 ########### @@ -30,23 +30,29 @@ class OnlPlatform_x86_64_accton_as5512_54x_r0(OnlPlatformAccton, # initialize CPLDs self.new_i2c_devices( [ - ('accton_i2c_cpld', 0x60, 0), - ('accton_i2c_cpld', 0x61, 0), - ('accton_i2c_cpld', 0x62, 0), + ('as5512_54x_cpld1', 0x60, 0), + ('as5512_54x_cpld2', 0x61, 0), + ('as5512_54x_cpld3', 0x62, 0), ] ) # initialize SFP devices for port in range(1, 49): - self.new_i2c_device('sfp%d' % port, 0x50, port+1) - self.new_i2c_device('sfp%d' % port, 0x51, port+1) + self.new_i2c_device('optoe2', 0x50, port+1) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+1), shell=True) # Initialize QSFP devices - self.new_i2c_device('sfp51', 0x50, 50) - self.new_i2c_device('sfp54', 0x50, 51) - self.new_i2c_device('sfp50', 0x50, 52) - self.new_i2c_device('sfp53', 0x50, 53) - self.new_i2c_device('sfp49', 0x50, 54) - self.new_i2c_device('sfp52', 0x50, 55) + self.new_i2c_device('optoe1', 0x50, 50) + self.new_i2c_device('optoe1', 0x50, 51) + self.new_i2c_device('optoe1', 0x50, 52) + self.new_i2c_device('optoe1', 0x50, 53) + self.new_i2c_device('optoe1', 0x50, 54) + self.new_i2c_device('optoe1', 0x50, 55) + subprocess.call('echo port51 > /sys/bus/i2c/devices/50-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/51-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/52-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/53-0050/port_name', shell=True) + subprocess.call('echo port49 > /sys/bus/i2c/devices/54-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/55-0050/port_name', shell=True) ########### initialize I2C bus 1 ########### self.new_i2c_devices( diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/fani.c index 2715c75b..a33c626a 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/fani.c @@ -43,7 +43,7 @@ #define FAN_1_ON_PSU1 6 #define FAN_1_ON_PSU2 7 -#define PROJECT_NAME +#define PROJECT_NAME #define LEN_FILE_NAME 50 @@ -52,7 +52,7 @@ typedef struct last_path_S char status[LEN_FILE_NAME]; char speed[LEN_FILE_NAME]; char direction[LEN_FILE_NAME]; - char ctrl_speed[LEN_FILE_NAME]; + char ctrl_speed[LEN_FILE_NAME]; char r_status[LEN_FILE_NAME]; char r_speed[LEN_FILE_NAME]; }last_path_T; @@ -75,10 +75,10 @@ static last_path_T last_path[] = /* must map with onlp_fan_id */ MAKE_FAN_LAST_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_2_ON_MAIN_BOARD), MAKE_FAN_LAST_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_3_ON_MAIN_BOARD), MAKE_FAN_LAST_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_4_ON_MAIN_BOARD), - MAKE_FAN_LAST_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_5_ON_MAIN_BOARD), + MAKE_FAN_LAST_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_5_ON_MAIN_BOARD), - MAKE_FAN_LAST_PATH_ON_PSU(57-003c), - MAKE_FAN_LAST_PATH_ON_PSU(58-003f), + MAKE_FAN_LAST_PATH_ON_PSU(57-003c), + MAKE_FAN_LAST_PATH_ON_PSU(58-003f), }; #define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ @@ -133,7 +133,7 @@ onlp_fan_info_t linfo[] = { printf("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, r_data); \ if (close(fd) == -1) \ return ONLP_STATUS_E_INTERNAL - + /* PSU relative marco */ #define SET_PSU_TYPE_AC_F2B_FAN(info) \ @@ -143,7 +143,7 @@ onlp_fan_info_t linfo[] = { #define SET_PSU_TYPE_AC_B2F_FAN(info) \ info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F); \ info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE - + #define SET_PSU_TYPE_UM400D_F2B_FAN(info) \ info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B) @@ -156,46 +156,46 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info) { int fd, len, nbytes = 10; char r_data[10] = {0}; - char fullpath[65] = {0}; - + char fullpath[100] = {0}; + /* get fan/fanr fault status (turn on when any one fails) */ - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].status); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].status); OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); if (atoi(r_data) > 0) info->status |= ONLP_FAN_STATUS_FAILED; - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].r_status); - OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].r_status); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); if (atoi(r_data) > 0) info->status |= ONLP_FAN_STATUS_FAILED; - /* get fan/fanr direction (both : the same) + /* get fan/fanr direction (both : the same) */ - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].direction); - OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); - + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].direction); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + if (atoi(r_data) == 0) /*F2B*/ info->status |= ONLP_FAN_STATUS_F2B; - else + else info->status |= ONLP_FAN_STATUS_B2F; /* get fan/fanr speed (take the average of two speeds) */ - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].speed); - OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); info->rpm = atoi(r_data); - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].r_speed); - OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].r_speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); info->rpm = (info->rpm + atoi(r_data))/2; /* get speed percentage from rpm */ - info->percentage = (info->rpm * 100)/16800; + info->percentage = (info->rpm * 100)/16800; - /* check present */ + /* check present */ if (info->rpm > 0) - info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_PRESENT; return ONLP_STATUS_OK; } @@ -210,7 +210,7 @@ _onlp_fani_info_get_fan_on_psu_ym2401(int pid, onlp_fan_info_t* info) if (psu_ym2401_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { info->status |= (val > 0) ? 0 : ONLP_FAN_STATUS_FAILED; info->rpm = val; - info->percentage = (info->rpm * 100) / 21600; + info->percentage = (info->rpm * 100) / 21600; } return ONLP_STATUS_OK; @@ -222,16 +222,16 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) int psu_id; int fd, len, nbytes = 10; char r_data[10] = {0}; - char fullpath[50] = {0}; + char fullpath[100] = {0}; psu_type_t psu_type; - - /* get fan other cap status according to psu type + + /* get fan other cap status according to psu type */ psu_id = (local_id-FAN_1_ON_PSU1) + 1; - DEBUG_PRINT("[psu_id: %d]", psu_id); - + DEBUG_PRINT("[psu_id: %d]", psu_id); + psu_type = get_psu_type(psu_id, NULL, 0); /* psu_id = 1 , present PSU1. pus_id =2 , present PSU2 */ - DEBUG_PRINT("[psu_type: %d]", psu_type); + DEBUG_PRINT("[psu_type: %d]", psu_type); switch (psu_type) { case PSU_TYPE_AC_COMPUWARE_F2B: @@ -250,26 +250,26 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) break; default: if (LOCAL_DEBUG) - printf("[Debug][%s][%d][psu_type=%d]\n", __FUNCTION__, __LINE__, psu_type); + printf("[Debug][%s][%d][psu_type=%d]\n", __FUNCTION__, __LINE__, psu_type); break; } - + if (psu_type == PSU_TYPE_AC_COMPUWARE_F2B || psu_type == PSU_TYPE_AC_COMPUWARE_B2F ) { - /* get fan fault status + /* get fan fault status */ - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].status); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].status); OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); if (atoi(r_data) > 0) info->status |= ONLP_FAN_STATUS_FAILED; - + /* get fan speed */ - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].speed); - OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); - info->rpm = atoi(r_data); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + info->rpm = atoi(r_data); /* get speed percentage from rpm */ info->percentage = (info->rpm * 100)/19328; @@ -279,7 +279,7 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) { return _onlp_fani_info_get_fan_on_psu_ym2401(psu_id, info); } - + return ONLP_STATUS_OK; } @@ -301,26 +301,26 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) int local_id; VALIDATE(id); - + local_id = ONLP_OID_ID_GET(id); - + *info = linfo[local_id]; - + if (LOCAL_DEBUG) printf("\n[Debug][%s][%d][local_id: %d]", __FUNCTION__, __LINE__, local_id); - + switch (local_id) { case FAN_1_ON_PSU1: case FAN_1_ON_PSU2: - rc = _onlp_fani_info_get_fan_on_psu(local_id, info); + rc = _onlp_fani_info_get_fan_on_psu(local_id, info); break; default: - rc =_onlp_fani_info_get_fan(local_id, info); + rc =_onlp_fani_info_get_fan(local_id, info); break; - } - + } + return rc; } @@ -349,20 +349,20 @@ onlp_fani_rpm_set(onlp_oid_t id, int rpm) */ int onlp_fani_percentage_set(onlp_oid_t id, int p) -{ +{ int fd, len, nbytes=10, local_id; - char data[10] = {0}; - char fullpath[70] = {0}; + char data[10] = {0}; + char fullpath[100] = {0}; VALIDATE(id); - + local_id = ONLP_OID_ID_GET(id); /* reject p=0 (p=0, stop fan) */ if (p == 0){ return ONLP_STATUS_E_INVALID; } - + /* get fullpath */ switch (local_id) { @@ -380,7 +380,7 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) return psu_ym2401_pmbus_info_set(psu_id, "psu_fan1_duty_cycle_percentage", p); } - sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].ctrl_speed); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, last_path[local_id].ctrl_speed); break; } @@ -388,23 +388,23 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, last_path[local_id].ctrl_speed); break; } - + sprintf(data, "%d", p); if (LOCAL_DEBUG) printf("[Debug][%s][%d][openfile: %s][data=%s]\n", __FUNCTION__, __LINE__, fullpath, data); - + /* Create output file descriptor */ fd = open(fullpath, O_WRONLY, 0644); if(fd == -1){ - return ONLP_STATUS_E_INTERNAL; + return ONLP_STATUS_E_INTERNAL; } - + len = write (fd, data, (ssize_t) nbytes); if(len != nbytes){ - close(fd); - return ONLP_STATUS_E_INTERNAL; - } + close(fd); + return ONLP_STATUS_E_INTERNAL; + } close(fd); return ONLP_STATUS_OK; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/ledi.c index 8298d4b1..96b21d69 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/ledi.c @@ -50,20 +50,20 @@ enum led_light_mode { /*must be the same with the definition @ kernel driver */ LED_MODE_GREEN_BLINK, LED_MODE_AMBER_BLINK, LED_MODE_RED_BLINK, - LED_MODE_AUTO, + LED_MODE_AUTO, }; int led_light_map_mode[][2] = { - {LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_MODE_OFF, ONLP_LED_MODE_OFF}, {LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, {LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, - {LED_MODE_RED, ONLP_LED_MODE_RED}, + {LED_MODE_RED, ONLP_LED_MODE_RED}, {LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, {LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, {LED_MODE_RED_BLINK, ONLP_LED_MODE_RED_BLINKING}, - {LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, -}; + {LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +}; #define prefix_path "/sys/class/leds/accton_as5712_54x_led::" @@ -81,7 +81,7 @@ enum onlp_led_id LED_FAN2, LED_FAN3, LED_FAN4, - LED_FAN5, + LED_FAN5, }; static char last_path[][10] = /* must map with onlp_led_id */ @@ -96,7 +96,7 @@ static char last_path[][10] = /* must map with onlp_led_id */ "fan2", "fan3", "fan4", - "fan5", + "fan5", }; /* @@ -160,7 +160,7 @@ static int conver_led_light_mode_to_onl(int led_ligth_mode) { if (led_ligth_mode == led_light_map_mode[i][0]) { - return led_light_map_mode[i][1]; + return led_light_map_mode[i][1]; } } return 0; @@ -174,7 +174,7 @@ static int conver_led_light_mode_to_driver(int led_ligth_mode) { if (led_ligth_mode == led_light_map_mode[i][1]) { - return led_light_map_mode[i][0]; + return led_light_map_mode[i][0]; } } return 0; @@ -200,40 +200,40 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) int fd, len, nbytes=1, local_id; char data[2] = {0}; - char fullpath[50] = {0}; - + char fullpath[100] = {0}; + VALIDATE(id); - + local_id = ONLP_OID_ID_GET(id); - + /* get fullpath */ if (strchr(last_path[local_id], '/') != NULL) { - sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); + sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); } else { - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); } - - /* Set the onlp_oid_hdr_t and capabilities */ + + /* Set the onlp_oid_hdr_t and capabilities */ *info = linfo[ONLP_OID_ID_GET(id)]; /* Set current mode */ if ((fd = open(fullpath, O_RDONLY)) == -1) - { + { return ONLP_STATUS_E_INTERNAL; } - + if ((len = read(fd, data, nbytes)) <= 0) { - close(fd); + close(fd); return ONLP_STATUS_E_INTERNAL; } - + /* If the read byte count is less, the format is different and calc will be wrong*/ if (close(fd) == -1) - { + { return ONLP_STATUS_E_INTERNAL; } @@ -278,37 +278,37 @@ int onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) { int fd, len, driver_mode, nbytes=1, local_id; - char data[2] = {0}; - char fullpath[50] = {0}; + char data[2] = {0}; + char fullpath[100] = {0}; VALIDATE(id); - + local_id = ONLP_OID_ID_GET(id); - + /* get fullpath */ if (strchr(last_path[local_id], '/') != NULL) { - sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); + sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); } else { - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); } - + driver_mode = conver_led_light_mode_to_driver(mode); sprintf(data, "%d", driver_mode); - + /* Create output file descriptor */ fd = open(fullpath, O_WRONLY, 0644); if(fd == -1){ - return ONLP_STATUS_E_INTERNAL; + return ONLP_STATUS_E_INTERNAL; } - + len = write (fd, data, (ssize_t) nbytes); if(len != nbytes){ - close(fd); - return ONLP_STATUS_E_INTERNAL; - } + close(fd); + return ONLP_STATUS_E_INTERNAL; + } close(fd); return ONLP_STATUS_OK; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c index c44d8a38..b235e099 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c @@ -41,6 +41,32 @@ #define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all" #define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all" +static int front_port_to_driver_port(int port) +{ + int rport = 0; + + switch (port) + { + case 49: + rport = 51; + break; + case 50: + rport = 53; + break; + case 51: + rport = 50; + break; + case 52: + rport = 52; + break; + default: + rport = (port + 1); + break; + } + + return rport; +} + static int front_port_bus_index(int port) { int rport = 0; @@ -48,23 +74,23 @@ static int front_port_bus_index(int port) switch (port) { case 49: - rport = 50; + rport = 54; break; case 50: - rport = 52; + rport = 53; break; case 51: - rport = 49; + rport = 52; break; case 52: rport = 51; break; default: - rport = port; + rport = port + 2; break; } - - return (rport + CPLD_MUX_BUS_START_INDEX); + + return rport; } /************************************************************ @@ -177,7 +203,7 @@ onlp_sfpi_is_present(int port) int present; int addr = (port < 24) ? 61 : 62; - if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, front_port_to_driver_port(port)) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.c index 2a62f3fe..aa49b53d 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.c @@ -253,22 +253,38 @@ int psu_ym2401_pmbus_info_set(int id, char *node, int value) #define PSU_SERIAL_NUMBER_LEN 18 -int psu_serial_number_get(int id, int is_ac, char *serial, int serial_len) +int psu_serial_number_get(int id, psu_type_t psu_type, char *serial, int serial_len) { int size = 0; int ret = ONLP_STATUS_OK; char *prefix = NULL; + char *filename = NULL; if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_PARAM; } memset((void *)serial, 0x0, serial_len); - if(is_ac) - prefix = (id == PSU1_ID) ? PSU1_AC_EEPROM_PREFIX : PSU2_AC_EEPROM_PREFIX; - else - prefix = (id == PSU1_ID) ? PSU1_DC_EEPROM_PREFIX : PSU2_DC_EEPROM_PREFIX; - ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_serial"); + switch (psu_type) { + case PSU_TYPE_AC_COMPUWARE_F2B: + case PSU_TYPE_AC_COMPUWARE_B2F: + filename = "psu_serial"; + prefix = (id == PSU1_ID) ? PSU1_AC_EEPROM_PREFIX : PSU2_AC_EEPROM_PREFIX; + break; + case PSU_TYPE_AC_3YPOWER_F2B: + case PSU_TYPE_AC_3YPOWER_B2F: + filename = "psu_mfr_serial"; + prefix = (id == PSU1_ID) ? PSU1_AC_3YPOWER_PMBUS_PREFIX : PSU2_AC_3YPOWER_PMBUS_PREFIX; + break; + case PSU_TYPE_DC_48V_F2B: + case PSU_TYPE_DC_48V_B2F: + /* fall through */ + default: + serial[0] = '\0'; + return ONLP_STATUS_E_UNSUPPORTED; + } + + ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, filename); if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_INTERNAL; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.h index 61be2f90..ea7c3f0e 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/platform_lib.h @@ -71,7 +71,7 @@ typedef enum psu_type { } psu_type_t; psu_type_t get_psu_type(int id, char* modelname, int modelname_len); -int psu_serial_number_get(int id, int is_ac, char *serial, int serial_len); +int psu_serial_number_get(int id, psu_type_t psu_type, char *serial, int serial_len); int psu_ym2401_pmbus_info_get(int id, char *node, int *value); int psu_ym2401_pmbus_info_set(int id, char *node, int value); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/psui.c index bc753041..4548fc70 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/psui.c @@ -225,7 +225,6 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) int val = 0; int ret = ONLP_STATUS_OK; int index = ONLP_OID_ID_GET(id); - int is_ac=1; psu_type_t psu_type; VALIDATE(id); @@ -271,14 +270,13 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) break; case PSU_TYPE_DC_48V_F2B: case PSU_TYPE_DC_48V_B2F: - is_ac=0; ret = psu_um400d_info_get(info); break; default: ret = ONLP_STATUS_E_UNSUPPORTED; break; } - psu_serial_number_get(index, is_ac, info->serial, sizeof(info->serial)); + psu_serial_number_get(index, psu_type, info->serial, sizeof(info->serial)); return ret; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/sfpi.c index f731e0d3..0f06f522 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/onlp/builds/src/module/src/sfpi.c @@ -41,6 +41,32 @@ #define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all" #define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all" +static int front_port_to_driver_port(int port) +{ + int rport = 0; + + switch (port) + { + case 49: + rport = 51; + break; + case 50: + rport = 53; + break; + case 51: + rport = 50; + break; + case 52: + rport = 52; + break; + default: + rport = (port + 1); + break; + } + + return rport; +} + static int front_port_bus_index(int port) { int rport = 0; @@ -48,23 +74,23 @@ static int front_port_bus_index(int port) switch (port) { case 49: - rport = 50; + rport = 54; break; case 50: - rport = 52; + rport = 53; break; case 51: - rport = 49; + rport = 52; break; case 52: rport = 51; break; default: - rport = port; + rport = port + 2; break; } - - return (rport + CPLD_MUX_BUS_START_INDEX); + + return rport; } /************************************************************ @@ -177,7 +203,7 @@ onlp_sfpi_is_present(int port) int present; int addr = (port < 24) ? 61 : 62; - if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, front_port_to_driver_port(port)) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5912-54x/modules/builds/x86-64-accton-as5912-54x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5912-54x/modules/builds/x86-64-accton-as5912-54x-fan.c old mode 100644 new mode 100755 index 117152e8..3ab8ac48 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5912-54x/modules/builds/x86-64-accton-as5912-54x-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5912-54x/modules/builds/x86-64-accton-as5912-54x-fan.c @@ -115,10 +115,11 @@ enum sysfs_fan_attributes { /* Define attributes */ -#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ - static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) -#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr - +#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 @@ -127,40 +128,47 @@ enum sysfs_fan_attributes { 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_PRESENT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index, index2) &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_present.dev_attr.attr -#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ +#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) -#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 + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) + +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM); #define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr /* 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); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6); +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); -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); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6); +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_PRESENT_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5, 15); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6, 16); /* 6 fan direction attribute in this platform */ DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); @@ -173,24 +181,24 @@ DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); static struct attribute *as5912_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_FAULT_ATTR(6), - 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_SPEED_RPM_ATTR(6), - 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_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, 11), + DECLARE_FAN_PRESENT_ATTR(2, 12), + DECLARE_FAN_PRESENT_ATTR(3, 13), + DECLARE_FAN_PRESENT_ATTR(4, 14), + DECLARE_FAN_PRESENT_ATTR(5, 15), + DECLARE_FAN_PRESENT_ATTR(6, 16), DECLARE_FAN_DIRECTION_ATTR(1), DECLARE_FAN_DIRECTION_ATTR(2), DECLARE_FAN_DIRECTION_ATTR(3), diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/modules/builds/x86-64-accton-as5916-26xb-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/modules/builds/x86-64-accton-as5916-26xb-psu.c old mode 100644 new mode 100755 index ba71289b..1a8d4d0a --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/modules/builds/x86-64-accton-as5916-26xb-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/modules/builds/x86-64-accton-as5916-26xb-psu.c @@ -425,8 +425,8 @@ static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *b case PSU1_FAN_INPUT: case PSU2_FAN_INPUT: VALIDATE_PRESENT_RETURN(pid); - value = ((int)data->ipmi_resp[pid].status[PSU_FAN0] | - (int)data->ipmi_resp[pid].status[PSU_FAN1] << 8); + value = (((unsigned char)data->ipmi_resp[pid].status[PSU_FAN0]) | + ((unsigned char)data->ipmi_resp[pid].status[PSU_FAN1]) << 8); break; default: return -EINVAL; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/onlp/builds/src/module/src/psui.c old mode 100644 new mode 100755 index 156f9bdb..15c2c7f6 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-26xb/onlp/builds/src/module/src/psui.c @@ -57,6 +57,22 @@ static onlp_psu_info_t pinfo[] = } }; +static int +get_DCorAC_cap(char *model) +{ + const char *dc_models[] = {"YM-2401U", "um400d", NULL }; + int i; + + i = 0; + while(dc_models[i]) { + if (!strncasecmp(model, dc_models[i], strlen(dc_models[i]))){ + return ONLP_PSU_CAPS_DC12; + } + i++; + } + return ONLP_PSU_CAPS_AC; +} + int onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) { @@ -140,6 +156,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) if (string && len) { strncpy(info->model, string, len); aim_free(string); + info->caps |= get_DCorAC_cap (info->model); } /* Read serial */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c old mode 100755 new mode 100644 similarity index 89% rename from packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-cpld.c rename to packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c index fd0c548e..0ec59ad4 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-cpld.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c @@ -4,7 +4,7 @@ * This module supports the accton cpld that hold the channel select * mechanism for other i2c slave devices, such as SFP. * This includes the: - * Accton as5916_54xks CPLD1/CPLD2 + * Accton as5916_54xk CPLD1/CPLD2 * * Based on: * pca954x.c from Kumar Gala @@ -46,29 +46,29 @@ struct cpld_client_node { }; enum cpld_type { - as5916_54xks_cpld1, - as5916_54xks_cpld2 + as5916_54xk_cpld1, + as5916_54xk_cpld2 }; -struct as5916_54xks_cpld_data { +struct as5916_54xk_cpld_data { enum cpld_type type; struct device *hwmon_dev; struct mutex update_lock; }; -static const struct i2c_device_id as5916_54xks_cpld_id[] = { - { "as5916_54xks_cpld1", as5916_54xks_cpld1 }, - { "as5916_54xks_cpld2", as5916_54xks_cpld2 }, +static const struct i2c_device_id as5916_54xk_cpld_id[] = { + { "as5916_54xk_cpld1", as5916_54xk_cpld1 }, + { "as5916_54xk_cpld2", as5916_54xk_cpld2 }, { } }; -MODULE_DEVICE_TABLE(i2c, as5916_54xks_cpld_id); +MODULE_DEVICE_TABLE(i2c, as5916_54xk_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 -enum as5916_54xks_cpld1_sysfs_attributes { +enum as5916_54xk_cpld1_sysfs_attributes { CPLD_VERSION, ACCESS, MODULE_PRESENT_ALL, @@ -288,8 +288,8 @@ 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 as5916_54xks_cpld_read_internal(struct i2c_client *client, u8 reg); -static int as5916_54xks_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); +static int as5916_54xk_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5916_54xk_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); /* transceiver attributes */ #define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ @@ -414,7 +414,7 @@ DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); -static struct attribute *as5916_54xks_cpld1_attributes[] = { +static struct attribute *as5916_54xk_cpld1_attributes[] = { &sensor_dev_attr_version.dev_attr.attr, &sensor_dev_attr_access.dev_attr.attr, /* transceiver attributes */ @@ -471,11 +471,11 @@ static struct attribute *as5916_54xks_cpld1_attributes[] = { NULL }; -static const struct attribute_group as5916_54xks_cpld1_group = { - .attrs = as5916_54xks_cpld1_attributes, +static const struct attribute_group as5916_54xk_cpld1_group = { + .attrs = as5916_54xk_cpld1_attributes, }; -static struct attribute *as5916_54xks_cpld2_attributes[] = { +static struct attribute *as5916_54xk_cpld2_attributes[] = { &sensor_dev_attr_version.dev_attr.attr, &sensor_dev_attr_access.dev_attr.attr, /* transceiver attributes */ @@ -538,8 +538,8 @@ static struct attribute *as5916_54xks_cpld2_attributes[] = { NULL }; -static const struct attribute_group as5916_54xks_cpld2_group = { - .attrs = as5916_54xks_cpld2_attributes, +static const struct attribute_group as5916_54xk_cpld2_group = { + .attrs = as5916_54xk_cpld2_attributes, }; static ssize_t show_present_all(struct device *dev, struct device_attribute *da, @@ -549,14 +549,14 @@ static ssize_t show_present_all(struct device *dev, struct device_attribute *da, u8 values[4] = {0}; u8 regs[] = {0x10, 0x11, 0x12, 0x52}; struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); mutex_lock(&data->update_lock); - num_regs = (data->type == as5916_54xks_cpld1) ? 3 : 4; + num_regs = (data->type == as5916_54xk_cpld1) ? 3 : 4; for (i = 0; i < num_regs; i++) { - status = as5916_54xks_cpld_read_internal(client, regs[i]); + status = as5916_54xk_cpld_read_internal(client, regs[i]); if (status < 0) { goto exit; @@ -567,11 +567,11 @@ static ssize_t show_present_all(struct device *dev, struct device_attribute *da, mutex_unlock(&data->update_lock); - if (data->type == as5916_54xks_cpld1) { + if (data->type == as5916_54xk_cpld1) { status = sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); } - else { /* as5916_54xks_cpld2 */ + else { /* as5916_54xk_cpld2 */ values[3] &= 0x3F; status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", values[0], values[1], values[2], values[3]); @@ -591,12 +591,12 @@ static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, u8 values[3] = {0}; u8 regs[] = {0x30, 0x32, 0x34}; struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); mutex_lock(&data->update_lock); for (i = 0; i < ARRAY_SIZE(regs); i++) { - status = as5916_54xks_cpld_read_internal(client, regs[i]); + status = as5916_54xk_cpld_read_internal(client, regs[i]); if (status < 0) { goto exit; @@ -620,7 +620,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); int status = 0; u8 reg = 0, mask = 0, revert = 0; @@ -734,7 +734,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, } mutex_lock(&data->update_lock); - status = as5916_54xks_cpld_read_internal(client, reg); + status = as5916_54xk_cpld_read_internal(client, reg); if (unlikely(status < 0)) { goto exit; } @@ -752,7 +752,7 @@ static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); long disable; int status; u8 reg = 0, mask = 0; @@ -793,7 +793,7 @@ static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, /* Read current status */ mutex_lock(&data->update_lock); - status = as5916_54xks_cpld_read_internal(client, reg); + status = as5916_54xk_cpld_read_internal(client, reg); if (unlikely(status < 0)) { goto exit; } @@ -806,7 +806,7 @@ static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, status &= ~mask; } - status = as5916_54xks_cpld_write_internal(client, reg, status); + status = as5916_54xk_cpld_write_internal(client, reg, status); if (unlikely(status < 0)) { goto exit; } @@ -825,7 +825,7 @@ static ssize_t access(struct device *dev, struct device_attribute *da, int status; u32 addr, val; struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { return -EINVAL; @@ -836,7 +836,7 @@ static ssize_t access(struct device *dev, struct device_attribute *da, } mutex_lock(&data->update_lock); - status = as5916_54xks_cpld_write_internal(client, addr, val); + status = as5916_54xk_cpld_write_internal(client, addr, val); if (unlikely(status < 0)) { goto exit; } @@ -848,7 +848,7 @@ exit: return status; } -static void as5916_54xks_cpld_add_client(struct i2c_client *client) +static void as5916_54xk_cpld_add_client(struct i2c_client *client) { struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); @@ -864,7 +864,7 @@ static void as5916_54xks_cpld_add_client(struct i2c_client *client) mutex_unlock(&list_lock); } -static void as5916_54xks_cpld_remove_client(struct i2c_client *client) +static void as5916_54xk_cpld_remove_client(struct i2c_client *client) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -907,18 +907,18 @@ static ssize_t show_version(struct device *dev, struct device_attribute *attr, c /* * I2C init/probing/exit functions */ -static int as5916_54xks_cpld_probe(struct i2c_client *client, +static int as5916_54xk_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); - struct as5916_54xks_cpld_data *data; + struct as5916_54xk_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 as5916_54xks_cpld_data), GFP_KERNEL); + data = kzalloc(sizeof(struct as5916_54xk_cpld_data), GFP_KERNEL); if (!data) { ret = -ENOMEM; goto exit; @@ -930,11 +930,11 @@ static int as5916_54xks_cpld_probe(struct i2c_client *client, /* Register sysfs hooks */ switch (data->type) { - case as5916_54xks_cpld1: - group = &as5916_54xks_cpld1_group; + case as5916_54xk_cpld1: + group = &as5916_54xk_cpld1_group; break; - case as5916_54xks_cpld2: - group = &as5916_54xks_cpld2_group; + case as5916_54xk_cpld2: + group = &as5916_54xk_cpld2_group; break; default: break; @@ -947,7 +947,7 @@ static int as5916_54xks_cpld_probe(struct i2c_client *client, } } - as5916_54xks_cpld_add_client(client); + as5916_54xk_cpld_add_client(client); return 0; exit_free: @@ -956,20 +956,20 @@ exit: return ret; } -static int as5916_54xks_cpld_remove(struct i2c_client *client) +static int as5916_54xk_cpld_remove(struct i2c_client *client) { - struct as5916_54xks_cpld_data *data = i2c_get_clientdata(client); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); const struct attribute_group *group = NULL; - as5916_54xks_cpld_remove_client(client); + as5916_54xk_cpld_remove_client(client); /* Remove sysfs hooks */ switch (data->type) { - case as5916_54xks_cpld1: - group = &as5916_54xks_cpld1_group; + case as5916_54xk_cpld1: + group = &as5916_54xk_cpld1_group; break; - case as5916_54xks_cpld2: - group = &as5916_54xks_cpld2_group; + case as5916_54xk_cpld2: + group = &as5916_54xk_cpld2_group; break; default: break; @@ -984,7 +984,7 @@ static int as5916_54xks_cpld_remove(struct i2c_client *client) return 0; } -static int as5916_54xks_cpld_read_internal(struct i2c_client *client, u8 reg) +static int as5916_54xk_cpld_read_internal(struct i2c_client *client, u8 reg) { int status = 0, retry = I2C_RW_RETRY_COUNT; @@ -1002,7 +1002,7 @@ static int as5916_54xks_cpld_read_internal(struct i2c_client *client, u8 reg) return status; } -static int as5916_54xks_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +static int as5916_54xk_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) { int status = 0, retry = I2C_RW_RETRY_COUNT; @@ -1020,7 +1020,7 @@ static int as5916_54xks_cpld_write_internal(struct i2c_client *client, u8 reg, u return status; } -int as5916_54xks_cpld_read(unsigned short cpld_addr, u8 reg) +int as5916_54xk_cpld_read(unsigned short cpld_addr, u8 reg) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -1033,7 +1033,7 @@ int as5916_54xks_cpld_read(unsigned short cpld_addr, u8 reg) cpld_node = list_entry(list_node, struct cpld_client_node, list); if (cpld_node->client->addr == cpld_addr) { - ret = as5916_54xks_cpld_read_internal(cpld_node->client, reg); + ret = as5916_54xk_cpld_read_internal(cpld_node->client, reg); break; } } @@ -1042,9 +1042,9 @@ int as5916_54xks_cpld_read(unsigned short cpld_addr, u8 reg) return ret; } -EXPORT_SYMBOL(as5916_54xks_cpld_read); +EXPORT_SYMBOL(as5916_54xk_cpld_read); -int as5916_54xks_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +int as5916_54xk_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -1057,7 +1057,7 @@ int as5916_54xks_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) cpld_node = list_entry(list_node, struct cpld_client_node, list); if (cpld_node->client->addr == cpld_addr) { - ret = as5916_54xks_cpld_write_internal(cpld_node->client, reg, value); + ret = as5916_54xk_cpld_write_internal(cpld_node->client, reg, value); break; } } @@ -1066,33 +1066,33 @@ int as5916_54xks_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) return ret; } -EXPORT_SYMBOL(as5916_54xks_cpld_write); +EXPORT_SYMBOL(as5916_54xk_cpld_write); -static struct i2c_driver as5916_54xks_cpld_driver = { +static struct i2c_driver as5916_54xk_cpld_driver = { .driver = { - .name = "as5916_54xks_cpld", + .name = "as5916_54xk_cpld", .owner = THIS_MODULE, }, - .probe = as5916_54xks_cpld_probe, - .remove = as5916_54xks_cpld_remove, - .id_table = as5916_54xks_cpld_id, + .probe = as5916_54xk_cpld_probe, + .remove = as5916_54xk_cpld_remove, + .id_table = as5916_54xk_cpld_id, }; -static int __init as5916_54xks_cpld_init(void) +static int __init as5916_54xk_cpld_init(void) { mutex_init(&list_lock); - return i2c_add_driver(&as5916_54xks_cpld_driver); + return i2c_add_driver(&as5916_54xk_cpld_driver); } -static void __exit as5916_54xks_cpld_exit(void) +static void __exit as5916_54xk_cpld_exit(void) { - i2c_del_driver(&as5916_54xks_cpld_driver); + i2c_del_driver(&as5916_54xk_cpld_driver); } MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("Accton I2C CPLD driver"); MODULE_LICENSE("GPL"); -module_init(as5916_54xks_cpld_init); -module_exit(as5916_54xks_cpld_exit); +module_init(as5916_54xk_cpld_init); +module_exit(as5916_54xk_cpld_exit); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c index f155e970..078e005a 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c @@ -38,8 +38,8 @@ #define DEBUG_PRINT(fmt, args...) #endif -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 int as5916_54xk_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5916_54xk_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); struct accton_as5916_54xk_led_data { struct platform_device *pdev; @@ -157,12 +157,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type, static int accton_as5916_54xk_led_read_value(u8 reg) { - return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); + return as5916_54xk_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); } static int accton_as5916_54xk_led_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); + return as5916_54xk_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); } static void accton_as5916_54xk_led_update(void) diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c index a2737499..f89fc298 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c @@ -37,7 +37,7 @@ 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 as5916_54xk_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); +extern int as5916_54xk_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ @@ -234,7 +234,7 @@ static struct as5916_54xk_psu_data *as5916_54xk_psu_update_device(struct device dev_dbg(&client->dev, "Starting as5916_54xk update\n"); /* Read psu status */ - status = accton_i2c_cpld_read(0x60, 0x2); + status = as5916_54xk_cpld_read(0x60, 0x2); if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c deleted file mode 100644 index c606e5c2..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c +++ /dev/null @@ -1,1315 +0,0 @@ -/* - * SFP driver for accton as5916_54xk 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 "as5916_54xk_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 54 -#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 - -/* Platform dependent +++ */ -#define I2C_ADDR_CPLD1 0x60 -#define I2C_ADDR_CPLD2 0x62 -/* Platform dependent --- */ - -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 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/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 { -as5916_54xk_sfp1, as5916_54xk_sfp2, as5916_54xk_sfp3, as5916_54xk_sfp4, as5916_54xk_sfp5, as5916_54xk_sfp6, as5916_54xk_sfp7, as5916_54xk_sfp8, -as5916_54xk_sfp9, as5916_54xk_sfp10, as5916_54xk_sfp11, as5916_54xk_sfp12, as5916_54xk_sfp13, as5916_54xk_sfp14, as5916_54xk_sfp15, as5916_54xk_sfp16, -as5916_54xk_sfp17, as5916_54xk_sfp18, as5916_54xk_sfp19, as5916_54xk_sfp20, as5916_54xk_sfp21, as5916_54xk_sfp22, as5916_54xk_sfp23, as5916_54xk_sfp24, -as5916_54xk_sfp25, as5916_54xk_sfp26, as5916_54xk_sfp27, as5916_54xk_sfp28, as5916_54xk_sfp29, as5916_54xk_sfp30, as5916_54xk_sfp31, as5916_54xk_sfp32, -as5916_54xk_sfp33, as5916_54xk_sfp34, as5916_54xk_sfp35, as5916_54xk_sfp36, as5916_54xk_sfp37, as5916_54xk_sfp38, as5916_54xk_sfp39, as5916_54xk_sfp40, -as5916_54xk_sfp41, as5916_54xk_sfp42, as5916_54xk_sfp43, as5916_54xk_sfp44, as5916_54xk_sfp45, as5916_54xk_sfp46, as5916_54xk_sfp47, as5916_54xk_sfp48, -as5916_54xk_sfp49, as5916_54xk_sfp50, as5916_54xk_sfp51, as5916_54xk_sfp52, as5916_54xk_sfp53, as5916_54xk_sfp54 -}; - -static const struct i2c_device_id sfp_device_id[] = { -{ "as5916_54xk_sfp1", as5916_54xk_sfp1 }, { "as5916_54xk_sfp2", as5916_54xk_sfp2 }, { "as5916_54xk_sfp3", as5916_54xk_sfp3 }, { "as5916_54xk_sfp4", as5916_54xk_sfp4 }, -{ "as5916_54xk_sfp5", as5916_54xk_sfp5 }, { "as5916_54xk_sfp6", as5916_54xk_sfp6 }, { "as5916_54xk_sfp7", as5916_54xk_sfp7 }, { "as5916_54xk_sfp8", as5916_54xk_sfp8 }, -{ "as5916_54xk_sfp9", as5916_54xk_sfp9 }, { "as5916_54xk_sfp10", as5916_54xk_sfp10 }, { "as5916_54xk_sfp11", as5916_54xk_sfp11 }, { "as5916_54xk_sfp12", as5916_54xk_sfp12 }, -{ "as5916_54xk_sfp13", as5916_54xk_sfp13 }, { "as5916_54xk_sfp14", as5916_54xk_sfp14 }, { "as5916_54xk_sfp15", as5916_54xk_sfp15 }, { "as5916_54xk_sfp16", as5916_54xk_sfp16 }, -{ "as5916_54xk_sfp17", as5916_54xk_sfp17 }, { "as5916_54xk_sfp18", as5916_54xk_sfp18 }, { "as5916_54xk_sfp19", as5916_54xk_sfp19 }, { "as5916_54xk_sfp20", as5916_54xk_sfp20 }, -{ "as5916_54xk_sfp21", as5916_54xk_sfp21 }, { "as5916_54xk_sfp22", as5916_54xk_sfp22 }, { "as5916_54xk_sfp23", as5916_54xk_sfp23 }, { "as5916_54xk_sfp24", as5916_54xk_sfp24 }, -{ "as5916_54xk_sfp25", as5916_54xk_sfp25 }, { "as5916_54xk_sfp26", as5916_54xk_sfp26 }, { "as5916_54xk_sfp27", as5916_54xk_sfp27 }, { "as5916_54xk_sfp28", as5916_54xk_sfp28 }, -{ "as5916_54xk_sfp29", as5916_54xk_sfp29 }, { "as5916_54xk_sfp30", as5916_54xk_sfp30 }, { "as5916_54xk_sfp31", as5916_54xk_sfp31 }, { "as5916_54xk_sfp32", as5916_54xk_sfp32 }, -{ "as5916_54xk_sfp33", as5916_54xk_sfp33 }, { "as5916_54xk_sfp34", as5916_54xk_sfp34 }, { "as5916_54xk_sfp35", as5916_54xk_sfp35 }, { "as5916_54xk_sfp36", as5916_54xk_sfp36 }, -{ "as5916_54xk_sfp37", as5916_54xk_sfp37 }, { "as5916_54xk_sfp38", as5916_54xk_sfp38 }, { "as5916_54xk_sfp39", as5916_54xk_sfp39 }, { "as5916_54xk_sfp40", as5916_54xk_sfp40 }, -{ "as5916_54xk_sfp41", as5916_54xk_sfp41 }, { "as5916_54xk_sfp42", as5916_54xk_sfp42 }, { "as5916_54xk_sfp43", as5916_54xk_sfp43 }, { "as5916_54xk_sfp44", as5916_54xk_sfp44 }, -{ "as5916_54xk_sfp45", as5916_54xk_sfp45 }, { "as5916_54xk_sfp46", as5916_54xk_sfp46 }, { "as5916_54xk_sfp47", as5916_54xk_sfp47 }, { "as5916_54xk_sfp48", as5916_54xk_sfp48 }, -{ "as5916_54xk_sfp49", as5916_54xk_sfp49 }, { "as5916_54xk_sfp50", as5916_54xk_sfp50 }, { "as5916_54xk_sfp51", as5916_54xk_sfp51 }, { "as5916_54xk_sfp52", as5916_54xk_sfp52 }, -{ "as5916_54xk_sfp53", as5916_54xk_sfp53 }, { "as5916_54xk_sfp54", as5916_54xk_sfp54 }, -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -/* - * 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 = I2C_ADDR_CPLD1 + i*2; - reg = 0x10+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 = 0x52; - 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 & 0x3F) << 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; - u8 tx_rx_regs[] = {0x14, 0x16, 0x18, 0x20, 0x22, 0x24, 0x30, 0x32, 0x34}; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as5916_54xk 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 < ARRAY_SIZE(tx_rx_regs); j++) { - unsigned short cpld_addr = I2C_ADDR_CPLD1 + i*2; - - status = accton_i2c_cpld_read(cpld_addr, tx_rx_regs[j]); - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, tx_rx_regs[i], 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; - u8 tx_disable_regs[] = {0x20, 0x22, 0x24}; - - 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_CPLD1; - cpld_reg = tx_disable_regs[data->port / 8]; - cpld_bit = 1 << (data->port % 8); - } - else { /* port 24 ~ 48 */ - cpld_addr = I2C_ADDR_CPLD2; - cpld_reg = tx_disable_regs[(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)); /* 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) { - 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}; - - 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) { - 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 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 (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)); - 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; - } - - *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 >= as5916_54xk_sfp1 && dev_id->driver_data <= as5916_54xk_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 { /* as5916_54xk_sfp49 ~ as5916_54xk_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) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5916_54xk_sfp driver"); -MODULE_LICENSE("GPL"); - -late_initcall(sfp_init); -module_exit(sfp_exit); - - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c index f4d29904..4f7abdd1 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c @@ -24,17 +24,21 @@ * ***********************************************************/ #include +#include #include -#include "platform_lib.h" - +#include "x86_64_accton_as5916_54xk_int.h" #include "x86_64_accton_as5916_54xk_log.h" -#define NUM_OF_SFP_PORT 54 -#define MAX_PORT_PATH 64 +#define PORT_BUS_INDEX(port) (port+33) -#define SFP_PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s" -#define SFP_PORT_DOM_FORMAT "/sys/bus/i2c/devices/%d-0051/%s" -#define SFP_BUS_INDEX(port) (port+33) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/11-0060/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/12-0062/module_rx_los_all" /************************************************************ * @@ -56,7 +60,7 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) */ int p; - for(p = 0; p < NUM_OF_SFP_PORT; p++) { + for(p = 0; p < 54; p++) { AIM_BITMAP_SET(bmap, p); } @@ -72,7 +76,12 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - if (onlp_file_read_int(&present, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_is_present") < 0) { + int bus, addr; + + addr = (port < 24) ? 60 : 62; + bus = (addr == 60) ? 11 : 12; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -83,31 +92,45 @@ onlp_sfpi_is_present(int port) int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7]; - char path[MAX_PORT_PATH] = {0}; + uint32_t bytes[7], *ptr = NULL; FILE* fp; + int addr; - sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_is_present_all"); - fp = fopen(path, "r"); + ptr = bytes; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5, - bytes+6 - ); - fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 60; addr <= 62; addr+=2) { + /* Read present status of port 0~53 */ + int count = 0; + char file[64] = {0}; + int bus = (addr == 60) ? 11 : 12; + + sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + + if (addr == 60) { /* CPLD1 */ + count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + } + else { /* CPLD2 */ + count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + } + + ptr += count; } /* Mask out non-existant QSFP ports */ @@ -130,64 +153,44 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } -int -onlp_sfpi_eeprom_read(int port, uint8_t data[256]) -{ - int size = 0; - if(onlp_file_read(data, 256, &size, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) { - if(size == 256) { - return ONLP_STATUS_OK; - } - } - - return ONLP_STATUS_E_INTERNAL; -} - -int -onlp_sfpi_dom_read(int port, uint8_t data[256]) -{ - int size = 0; - if(onlp_file_read(data, 256, &size, SFP_PORT_DOM_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) { - if(size == 256) { - return ONLP_STATUS_OK; - } - } - - return ONLP_STATUS_E_INTERNAL; -} - int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[6]; - char path[MAX_PORT_PATH] = {0}; + uint32_t *ptr = bytes; FILE* fp; - sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of port 0~23 */ + int addr, i = 0; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5 - ); - fclose(fp); - if(count != 6) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 60; addr <= 62; addr+=2) { + if (addr == 60) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; } /* Convert to 64 bit integer in port order */ - int i = 0; + i = 0; uint64_t rx_los_all = 0 ; - for(i = 5; i >= 0; i--) { + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { rx_los_all <<= 8; rx_los_all |= bytes[i]; } @@ -201,16 +204,77 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int rv; + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 60 : 62; + int bus = (addr == 60) ? 11 : 12; + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_write_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") != 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -233,12 +297,19 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 60 : 62; + int bus = (addr == 60) ? 11 : 12; + switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_rx_los") < 0) { - AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -249,7 +320,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_fault") < 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -261,7 +332,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") < 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -278,7 +349,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) return rv; } - int onlp_sfpi_denit(void) { diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py index da17b4ea..dc4b3fe0 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py @@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, SYS_OBJECT_ID=".5916.54" def baseconfig(self): - self.insmod("accton_i2c_cpld") + self.insmod('optoe') self.insmod("ym2651y") - for m in [ "sfp", "psu", "fan", "leds" ]: + for m in [ "cpld", "psu", "fan", "leds" ]: self.insmod("x86-64-accton-as5916-54xk-%s" % m) ########### initialize I2C bus 0 ########### @@ -30,8 +30,8 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, ('lm75', 0x4b, 10), # initialize CPLDs - ('accton_i2c_cpld', 0x60, 11), - ('accton_i2c_cpld', 0x62, 12), + ('as5916_54xk_cpld1', 0x60, 11), + ('as5916_54xk_cpld2', 0x62, 12), # initialize multiplexer (PCA9548) ('pca9548', 0x74, 2), @@ -61,12 +61,14 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, # initialize SFP devices for port in range(1, 49): - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32) - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x51, port+32) + self.new_i2c_device('optoe2', 0x50, port+32) # initialize QSFP devices for port in range(49, 55): - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32) + self.new_i2c_device('optoe1', 0x50, port+32) + + for port in range(1, 55): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+32), shell=True) return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-fan.c index 145062db..084290af 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-fan.c @@ -1,485 +1,472 @@ /* - * A hwmon driver for the Accton as5916 54x fan + * Copyright (C) Brandon Chuang * - * Copyright (C) 2016 Accton Technology Corporation. - * Brandon Chuang * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) * - * 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. + * 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 -#include +#include +#include +#include +#include +#include +#include +#include +#include #define DRVNAME "as5916_54xks_fan" -#define MAX_FAN_SPEED_RPM 25500 +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_FAN_READ_CMD 0x14 +#define IPMI_FAN_WRITE_CMD 0x15 +#define IPMI_TIMEOUT (20 * HZ) -static struct as5916_54xks_fan_data *as5916_54xks_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 void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xks_fan_probe(struct platform_device *pdev); +static int as5916_54xks_fan_remove(struct platform_device *pdev); -/* 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) */ +enum fan_id { + FAN_1, + FAN_2, + FAN_3, + FAN_4, + FAN_5, + FAN_6, + NUM_OF_FAN +}; + +enum fan_data_index { + FAN_PRESENT, + FAN_PWM, + FAN_SPEED0, + FAN_SPEED1, + FAN_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; }; -/* Each client has this additional data */ struct as5916_54xks_fan_data { - struct device *hwmon_dev; + struct platform_device *pdev; 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 */ + unsigned char ipmi_resp[24]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[3]; /* 0: FAN id, 1: 0x02, 2: PWM */ }; -enum fan_id { - FAN1_ID, - FAN2_ID, - FAN3_ID, - FAN4_ID, - FAN5_ID, - FAN6_ID +struct as5916_54xks_fan_data *data = NULL; + +static struct platform_driver as5916_54xks_fan_driver = { + .probe = as5916_54xks_fan_probe, + .remove = as5916_54xks_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, }; -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, - FAN_MAX_RPM +#define FAN_PRESENT_ATTR_ID(index) FAN##index##_PRESENT +#define FAN_PWM_ATTR_ID(index) FAN##index##_PWM +#define FAN_RPM_ATTR_ID(index) FAN##index##_INPUT + +#define FAN_ATTR(fan_id) \ + FAN_PRESENT_ATTR_ID(fan_id), \ + FAN_PWM_ATTR_ID(fan_id), \ + FAN_RPM_ATTR_ID(fan_id) + +enum as5916_54x_fan_sysfs_attrs { + FAN_ATTR(1), + FAN_ATTR(2), + FAN_ATTR(3), + FAN_ATTR(4), + FAN_ATTR(5), + FAN_ATTR(6), + NUM_OF_FAN_ATTR, + NUM_OF_PER_FAN_ATTR = (NUM_OF_FAN_ATTR/NUM_OF_FAN) }; -/* Define attributes - */ -#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ - static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) -#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr +/* fan attributes */ +#define DECLARE_FAN_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, show_fan, NULL, FAN##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, show_fan, set_fan, FAN##index##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, show_fan, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.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 - -static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM); -#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr - -/* 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); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6); -/* 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); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6); -/* 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(); +DECLARE_FAN_SENSOR_DEVICE_ATTR(1); +DECLARE_FAN_SENSOR_DEVICE_ATTR(2); +DECLARE_FAN_SENSOR_DEVICE_ATTR(3); +DECLARE_FAN_SENSOR_DEVICE_ATTR(4); +DECLARE_FAN_SENSOR_DEVICE_ATTR(5); +DECLARE_FAN_SENSOR_DEVICE_ATTR(6); static struct attribute *as5916_54xks_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_FAULT_ATTR(6), - 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_SPEED_RPM_ATTR(6), - 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_MAX_RPM_ATTR(), + /* fan attributes */ + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_ATTR(4), + DECLARE_FAN_ATTR(5), + DECLARE_FAN_ATTR(6), 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 as5916_54xks_fan_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int as5916_54xks_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) -{ - return !!(reg_val & BIT(id)); -} - -static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) -{ - return !(reg_val & BIT(id)); -} - -static u8 is_fan_fault(struct as5916_54xks_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; - - as5916_54xks_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ - as5916_54xks_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 as5916_54xks_fan_data *data = as5916_54xks_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; - case FAN_MAX_RPM: - ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM); - default: - break; - } - } - - return ret; -} - static const struct attribute_group as5916_54xks_fan_group = { .attrs = as5916_54xks_fan_attributes, }; -static struct as5916_54xks_fan_data *as5916_54xks_fan_update_device(struct device *dev) +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_fan_data *data = i2c_get_clientdata(client); + int err; - mutex_lock(&data->update_lock); + init_completion(&ipmi->read_complete); - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || - !data->valid) { - int i; + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; - dev_dbg(&client->dev, "Starting as5916_54xks_fan update\n"); - data->valid = 0; - - /* Update fan data - */ - for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { - int status = as5916_54xks_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); + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; - return data; + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; } -static int as5916_54xks_fan_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) { - struct as5916_54xks_fan_data *data; - int status; + int err; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xks_fan_data *as5916_54xks_fan_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { status = -EIO; goto exit; } - data = kzalloc(sizeof(struct as5916_54xks_fan_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + int value = 0; + int index = 0; + int present = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as5916_54xks_fan_update_device(); + if (!data->valid) { + error = -EIO; goto exit; } - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); + index = fid * FAN_DATA_COUNT; /* base index */ + present = !data->ipmi_resp[index + FAN_PRESENT]; - dev_info(&client->dev, "chip found\n"); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &as5916_54xks_fan_group); - if (status) { - goto exit_free; + switch (attr->index) { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + value = !data->ipmi_resp[index + FAN_PRESENT]; + break; + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + value = (data->ipmi_resp[index + FAN_PWM] + 1) * 625 / 100; + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + break; + default: + error = -EINVAL; + goto exit; } - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", present ? value : 0); - 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, &as5916_54xks_fan_group); -exit_free: - kfree(data); exit: - + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long pwm; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + + status = kstrtol(buf, 10, &pwm); + if (status) { + return status; + } + + pwm = (pwm * 100) / 625 - 1; /* Convert pwm to register value */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = 1; /* All FANs share the same PWM register, ALWAYS set 1 for each fan */ + data->ipmi_tx_data[1] = 0x02; + data->ipmi_tx_data[2] = pwm; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm; + status = count; + +exit: + mutex_unlock(&data->update_lock); return status; } -static int as5916_54xks_fan_remove(struct i2c_client *client) +static int as5916_54xks_fan_probe(struct platform_device *pdev) { - struct as5916_54xks_fan_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &as5916_54xks_fan_group); + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_fan_group); + if (status) { + goto exit; + } + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xks_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_fan_group); + return 0; } -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; - -static const struct i2c_device_id as5916_54xks_fan_id[] = { - { "as5916_54xks_fan", 0 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, as5916_54xks_fan_id); - -static struct i2c_driver as5916_54xks_fan_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = DRVNAME, - }, - .probe = as5916_54xks_fan_probe, - .remove = as5916_54xks_fan_remove, - .id_table = as5916_54xks_fan_id, - .address_list = normal_i2c, -}; - static int __init as5916_54xks_fan_init(void) { - return i2c_add_driver(&as5916_54xks_fan_driver); + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xks_fan_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; } static void __exit as5916_54xks_fan_exit(void) { - i2c_del_driver(&as5916_54xks_fan_driver); + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_fan_driver); + kfree(data); } +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5916_54xks fan driver"); +MODULE_LICENSE("GPL"); + module_init(as5916_54xks_fan_init); module_exit(as5916_54xks_fan_exit); -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("as5916_54xks_fan driver"); -MODULE_LICENSE("GPL"); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-leds.c index db530e85..9ed8b252 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-leds.c @@ -1,84 +1,92 @@ /* - * A LED driver for the accton_as5916_54xks_led + * Copyright (C) Brandon Chuang * - * Copyright (C) 2016 Accton Technology Corporation. - * Brandon Chuang + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 * - * This program is free software; you can 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. + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . * - * 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. + * 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 +#include +#include +#include +#include +#include -#define DRVNAME "accton_as5916_54xks_led" +#define DRVNAME "as5916_54xks_led" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_LED_READ_CMD 0x1A +#define IPMI_LED_WRITE_CMD 0x1B +#define IPMI_TIMEOUT (20 * HZ) -#define DEBUG_MODE 1 +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_led(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xks_led_probe(struct platform_device *pdev); +static int as5916_54xks_led_remove(struct platform_device *pdev); -#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 as5916_54xks_cpld_read(unsigned short cpld_addr, u8 reg); -extern int as5916_54xks_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -struct accton_as5916_54xks_led_data { - struct platform_device *pdev; - struct mutex update_lock; - char valid; /* != 0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED, - 1 = FAN/PSU LED, - 2 ~ 4 = SYSTEM LED */ +enum led_data_index { + LOC_INDEX, + DIAG_RED_INDEX, + DIAG_GREEN_INDEX }; -static struct accton_as5916_54xks_led_data *ledctl = NULL; +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; -#define LED_CNTRLER_I2C_ADDRESS (0x60) + struct kernel_ipmi_msg tx_message; + long tx_msgid; -#define LED_TYPE_DIAG_REG_MASK (0x0C) -#define LED_MODE_DIAG_GREEN_VALUE (0x04) -#define LED_MODE_DIAG_ORANGE_VALUE (0x08) -#define LED_MODE_DIAG_OFF_VALUE (0x0C) + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; - -#define LED_TYPE_LOC_REG_MASK (0x10) -#define LED_MODE_LOC_ORANGE_VALUE (0x00) -#define LED_MODE_LOC_OFF_VALUE (0x10) - -static const u8 led_reg[] = { - 0x65, /* LOC/DIAG/FAN LED */ - 0x66, /* PSU LED */ -}; - -enum led_type { - LED_TYPE_DIAG, - LED_TYPE_LOC, - LED_TYPE_FAN, - LED_TYPE_PSU1, - LED_TYPE_PSU2 + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xks_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[3]; /* 0: LOC LED, 1: DIAG Red LED, 2: DIAG Green LED */ + struct ipmi_data ipmi; +}; + +struct as5916_54xks_led_data *data = NULL; + +static struct platform_driver as5916_54xks_led_driver = { + .probe = as5916_54xks_led_probe, + .remove = as5916_54xks_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, }; -/* FAN/PSU/DIAG/RELEASE led mode */ enum led_light_mode { LED_MODE_OFF, LED_MODE_RED = 10, @@ -102,285 +110,360 @@ enum led_light_mode { LED_MODE_UNKNOWN = 99 }; -struct led_type_mode { - enum led_type type; - enum led_light_mode mode; - int type_mask; - int mode_value; +enum as5916_54x_led_sysfs_attrs { + LED_LOC, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN }; -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_ORANGE, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_ORANGE_VALUE}, +static SENSOR_DEVICE_ATTR(led_loc, S_IWUSR | S_IRUGO, show_led, set_led, LED_LOC); +static SENSOR_DEVICE_ATTR(led_diag, S_IWUSR | S_IRUGO, show_led, set_led, LED_DIAG); +static SENSOR_DEVICE_ATTR(led_psu1, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU2); +static SENSOR_DEVICE_ATTR(led_fan, S_IWUSR | S_IRUGO, show_led, set_led, LED_FAN); + +static struct attribute *as5916_54xks_led_attributes[] = { + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_diag.dev_attr.attr, + &sensor_dev_attr_led_psu1.dev_attr.attr, + &sensor_dev_attr_led_psu2.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + NULL }; -static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { - int i; - - for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { - if (type != led_type_mode_data[i].type) { - continue; - } - - if ((led_type_mode_data[i].type_mask & reg_val) == - led_type_mode_data[i].mode_value) { - return led_type_mode_data[i].mode; - } - } - - return LED_MODE_UNKNOWN; -} - -static u8 led_light_mode_to_reg_val(enum led_type type, - enum led_light_mode mode, u8 reg_val) { - int i; - - for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { - int type_mask, mode_value; - - if (type != led_type_mode_data[i].type) - continue; - - if (mode != led_type_mode_data[i].mode) - continue; - - type_mask = led_type_mode_data[i].type_mask; - mode_value = led_type_mode_data[i].mode_value; - reg_val = (reg_val & ~type_mask) | mode_value; - } - - return reg_val; -} - -static int accton_as5916_54xks_led_read_value(u8 reg) -{ - return as5916_54xks_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); -} - -static int accton_as5916_54xks_led_write_value(u8 reg, u8 value) -{ - return as5916_54xks_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); -} - -static void accton_as5916_54xks_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_as5916_54xks_led update\n"); - ledctl->valid = 0; - - /* Update LED data - */ - for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { - int status = accton_as5916_54xks_led_read_value(led_reg[i]); - - if (status < 0) { - dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); - goto exit; - } - else - ledctl->reg_val[i] = status; - } - - ledctl->last_updated = jiffies; - ledctl->valid = 1; - } - -exit: - mutex_unlock(&ledctl->update_lock); -} - -static void accton_as5916_54xks_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_as5916_54xks_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_as5916_54xks_led_write_value(reg, reg_val); - ledctl->valid = 0; - -exit: - mutex_unlock(&ledctl->update_lock); -} - -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 void accton_as5916_54xks_led_diag_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as5916_54xks_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); -} - -static enum led_brightness accton_as5916_54xks_led_diag_get(struct led_classdev *cdev) -{ - accton_as5916_54xks_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); -} - -static enum led_brightness accton_as5916_54xks_led_loc_get(struct led_classdev *cdev) -{ - accton_as5916_54xks_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); -} - -static void accton_as5916_54xks_led_loc_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as5916_54xks_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); -} - -static struct led_classdev accton_as5916_54xks_leds[] = { - [LED_TYPE_LOC] = { - .name = "accton_as5916_54xks_led::loc", - .default_trigger = "unused", - .brightness_set = accton_as5916_54xks_led_loc_set, - .brightness_get = accton_as5916_54xks_led_loc_get, - .max_brightness = LED_MODE_ORANGE, - }, - [LED_TYPE_DIAG] = { - .name = "accton_as5916_54xks_led::diag", - .default_trigger = "unused", - .brightness_set = accton_as5916_54xks_led_diag_set, - .brightness_get = accton_as5916_54xks_led_diag_get, - .max_brightness = LED_MODE_GREEN, - }, - [LED_TYPE_PSU1] = { - .name = "accton_as5916_54xks_led::psu1", - .default_trigger = "unused", - .brightness_set = accton_as7312_54x_led_auto_set, - .brightness_get = accton_as7312_54x_led_auto_get, - .max_brightness = LED_MODE_AUTO, - }, - [LED_TYPE_PSU2] = { - .name = "accton_as5916_54xks_led::psu2", - .default_trigger = "unused", - .brightness_set = accton_as7312_54x_led_auto_set, - .brightness_get = accton_as7312_54x_led_auto_get, - .max_brightness = LED_MODE_AUTO, - }, - [LED_TYPE_FAN] = { - .name = "accton_as5916_54xks_led::fan", - .default_trigger = "unused", - .brightness_set = accton_as7312_54x_led_auto_set, - .brightness_get = accton_as7312_54x_led_auto_get, - .max_brightness = LED_MODE_AUTO, - }, +static const struct attribute_group as5916_54xks_led_group = { + .attrs = as5916_54xks_led_attributes, }; -static int accton_as5916_54xks_led_probe(struct platform_device *pdev) -{ - int ret, i; - - for (i = 0; i < ARRAY_SIZE(accton_as5916_54xks_leds); i++) { - ret = led_classdev_register(&pdev->dev, &accton_as5916_54xks_leds[i]); - - if (ret < 0) { - break; - } - } - - /* Check if all LEDs were successfully registered */ - if (i != ARRAY_SIZE(accton_as5916_54xks_leds)){ - int j; - - /* only unregister the LEDs that were successfully registered */ - for (j = 0; j < i; j++) { - led_classdev_unregister(&accton_as5916_54xks_leds[i]); - } - } +/* Functions to talk to the IPMI layer */ - return ret; -} - -static int accton_as5916_54xks_led_remove(struct platform_device *pdev) +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) { - int i; - - for (i = 0; i < ARRAY_SIZE(accton_as5916_54xks_leds); i++) { - led_classdev_unregister(&accton_as5916_54xks_leds[i]); + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; } return 0; } -static struct platform_driver accton_as5916_54xks_led_driver = { - .probe = accton_as5916_54xks_led_probe, - .remove = accton_as5916_54xks_led_remove, - .driver = { - .name = DRVNAME, - .owner = THIS_MODULE, - }, -}; - -static int __init accton_as5916_54xks_led_init(void) +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) { - int ret; + int err; - ret = platform_driver_register(&accton_as5916_54xks_led_driver); - if (ret < 0) { - goto exit; - } + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; - ledctl = kzalloc(sizeof(struct accton_as5916_54xks_led_data), GFP_KERNEL); - if (!ledctl) { - ret = -ENOMEM; - goto exit_driver; - } + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; - mutex_init(&ledctl->update_lock); + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; - ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); - if (IS_ERR(ledctl->pdev)) { - ret = PTR_ERR(ledctl->pdev); - goto exit_free; - } + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; return 0; -exit_free: - kfree(ledctl); -exit_driver: - platform_driver_unregister(&accton_as5916_54xks_led_driver); -exit: - return ret; +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; } -static void __exit accton_as5916_54xks_led_exit(void) +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) { - platform_device_unregister(ledctl->pdev); - platform_driver_unregister(&accton_as5916_54xks_led_driver); - kfree(ledctl); + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); } -late_initcall(accton_as5916_54xks_led_init); -module_exit(accton_as5916_54xks_led_exit); +static struct as5916_54xks_led_data *as5916_54xks_led_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_LED_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_led(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as5916_54xks_led_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case LED_LOC: + value = data->ipmi_resp[LOC_INDEX] ? LED_MODE_ORANGE_BLINKING : LED_MODE_OFF; + break; + case LED_DIAG: + { + if (!data->ipmi_resp[DIAG_GREEN_INDEX] && !data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (data->ipmi_resp[DIAG_GREEN_INDEX] && data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_ORANGE; + else if (data->ipmi_resp[DIAG_GREEN_INDEX]) + value = LED_MODE_GREEN; + break; + } + case LED_PSU1: + case LED_PSU2: + case LED_FAN: + value = LED_MODE_AUTO; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = kstrtol(buf, 10, &mode); + if (status) { + return status; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_led_update_device(); + if (!data->valid) { + status = -EIO; + goto exit; + } + + switch (attr->index) { + case LED_LOC: + data->ipmi_resp[LOC_INDEX] = !!mode; + break; + case LED_DIAG: + { + if (mode == LED_MODE_GREEN) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 1; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + else if (mode == LED_MODE_ORANGE) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 1; + } + else { /* OFF */ + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + + break; + } + default: + status = -EINVAL; + goto exit; + } + + /* Send IPMI write command */ + status = ipmi_send_message(&data->ipmi, IPMI_LED_WRITE_CMD, + data->ipmi_resp, sizeof(data->ipmi_resp), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as5916_54xks_led_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_led_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xks_led_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_led_group); + + return 0; +} + +static int __init as5916_54xks_led_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_led_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xks_led_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_led_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xks_led_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_led_driver); + kfree(data); +} MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton_as5916_54xks_led driver"); +MODULE_DESCRIPTION("AS5916 54XKS led driver"); MODULE_LICENSE("GPL"); +module_init(as5916_54xks_led_init); +module_exit(as5916_54xks_led_exit); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-psu.c index fa5f7bd0..3249a98f 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-psu.c @@ -1,288 +1,592 @@ /* - * An hwmon driver for accton as5916_54xks Power Module + * Copyright (C) Brandon Chuang + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 * - * Copyright (C) 2014 Accton Technology Corporation. - * Brandon Chuang + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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 -#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 as5916_54xks_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int as5916_54xks_cpld_read(unsigned short cpld_addr, u8 reg); +#define DRVNAME "as5916_54xks_psu" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_PSU_READ_CMD 0x16 +#define IPMI_PSU_MODEL_NAME_CMD 0x10 +#define IPMI_PSU_SERIAL_NUM_CMD 0x11 +#define IPMI_TIMEOUT (20 * HZ) -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_linear(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_psu(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xks_psu_probe(struct platform_device *pdev); +static int as5916_54xks_psu_remove(struct platform_device *pdev); + +enum psu_id { + PSU_1, + PSU_2, + NUM_OF_PSU +}; + +enum psu_data_index { + PSU_PRESENT = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD_CPLD, + PSU_POWER_GOOD_PMBUS, + PSU_OVER_VOLTAGE, + PSU_OVER_CURRENT, + PSU_POWER_ON, + PSU_VIN0, + PSU_VIN1, + PSU_VOUT0, + PSU_VOUT1, + PSU_IOUT0, + PSU_IOUT1, + PSU_TEMP0, + PSU_TEMP1, + PSU_FAN0, + PSU_FAN1, + PSU_POUT0, + PSU_POUT1, + PSU_STATUS_COUNT, + PSU_MODEL = 0, + PSU_SERIAL = 0 +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct ipmi_psu_resp_data { + unsigned char status[19]; + char serial[19]; + char model[9]; +}; -/* Each client has this additional data - */ struct as5916_54xks_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 */ + struct platform_device *pdev; + struct mutex update_lock; + char valid[2]; /* != 0 if registers are valid, 0: PSU1, 1: PSU2 */ + unsigned long last_updated[2]; /* In jiffies, 0: PSU1, 1: PSU2 */ + struct ipmi_data ipmi; + struct ipmi_psu_resp_data ipmi_resp[2]; /* 0: PSU1, 1: PSU2 */ + unsigned char ipmi_tx_data[2]; }; -static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct device *dev); +struct as5916_54xks_psu_data *data = NULL; -enum as5916_54xks_psu_sysfs_attributes { - PSU_PRESENT, - PSU_MODEL_NAME, - PSU_POWER_GOOD +static struct platform_driver as5916_54xks_psu_driver = { + .probe = as5916_54xks_psu_probe, + .remove = as5916_54xks_psu_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, }; -/* 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); +#define PSU_PRESENT_ATTR_ID(index) PSU##index##_PRESENT +#define PSU_POWERGOOD_ATTR_ID(index) PSU##index##_POWER_GOOD +#define PSU_VOUT_ATTR_ID(index) PSU##index##_VOUT +#define PSU_IOUT_ATTR_ID(index) PSU##index##_IOUT +#define PSU_POUT_ATTR_ID(index) PSU##index##_POUT +#define PSU_MODEL_ATTR_ID(index) PSU##index##_MODEL +#define PSU_SERIAL_ATTR_ID(index) PSU##index##_SERIAL +#define PSU_TEMP_INPUT_ATTR_ID(index) PSU##index##_TEMP_INPUT +#define PSU_FAN_INPUT_ATTR_ID(index) PSU##index##_FAN_INPUT + +#define PSU_ATTR(psu_id) \ + PSU_PRESENT_ATTR_ID(psu_id), \ + PSU_POWERGOOD_ATTR_ID(psu_id), \ + PSU_VOUT_ATTR_ID(psu_id), \ + PSU_IOUT_ATTR_ID(psu_id), \ + PSU_POUT_ATTR_ID(psu_id), \ + PSU_MODEL_ATTR_ID(psu_id), \ + PSU_SERIAL_ATTR_ID(psu_id), \ + PSU_TEMP_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_INPUT_ATTR_ID(psu_id) + +enum as5916_54x_psu_sysfs_attrs { + /* psu attributes */ + PSU_ATTR(1), + PSU_ATTR(2), + NUM_OF_PSU_ATTR, + NUM_OF_PER_PSU_ATTR = (NUM_OF_PSU_ATTR/NUM_OF_PSU) +}; + +/* psu attributes */ +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, PSU##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL, PSU##index##_POWER_GOOD); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_linear, NULL, PSU##index##_VOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_linear, NULL, PSU##index##_IOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_linear, NULL, PSU##index##_POUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, PSU##index##_MODEL); \ + static SENSOR_DEVICE_ATTR(psu##index##_serial, S_IRUGO, show_string, NULL, PSU##index##_SERIAL);\ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input, S_IRUGO, show_psu, NULL, PSU##index##_TEMP_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan1_input, S_IRUGO, show_psu, NULL, PSU##index##_FAN_INPUT) +#define DECLARE_PSU_ATTR(index) \ + &sensor_dev_attr_psu##index##_present.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_power_good.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_model.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_serial.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_temp1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan1_input.dev_attr.attr + +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); static struct attribute *as5916_54xks_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, + /* psu attributes */ + DECLARE_PSU_ATTR(1), + DECLARE_PSU_ATTR(2), 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 as5916_54xks_psu_data *data = as5916_54xks_psu_update_device(dev); - u8 status = 0; - - if (attr->index == PSU_PRESENT) { - status = !(data->status & BIT(1 - data->index));; - } - else { /* PSU_POWER_GOOD */ - status = !!(data->status & BIT(3 - data->index)); - } - - return sprintf(buf, "%d\n", status); -} - -static ssize_t show_model_name(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct as5916_54xks_psu_data *data = as5916_54xks_psu_update_device(dev); - - return sprintf(buf, "%s\n", data->model_name); -} - static const struct attribute_group as5916_54xks_psu_group = { .attrs = as5916_54xks_psu_attributes, }; -static int as5916_54xks_psu_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct as5916_54xks_psu_data *data; - int status; +/* Functions to talk to the IPMI layer */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int status = 0; + + if (time_before(jiffies, data->last_updated[pid] + HZ * 5) && data->valid[pid]) { + return data; + } + + data->valid[pid] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */ + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 1, + data->ipmi_resp[pid].status, sizeof(data->ipmi_resp[pid].status)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { status = -EIO; goto exit; } - data = kzalloc(sizeof(struct as5916_54xks_psu_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; + /* Get model name from ipmi */ + data->ipmi_tx_data[1] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].model, sizeof(data->ipmi_resp[pid].model) - 1); + if (unlikely(status != 0)) { 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, &as5916_54xks_psu_group); - if (status) { - goto exit_free; + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; } - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; + /* Get serial number from ipmi */ + data->ipmi_tx_data[1] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].serial, sizeof(data->ipmi_resp[pid].serial) - 1); + if (unlikely(status != 0)) { + goto exit; } - dev_info(&client->dev, "%s: psu '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated[pid] = jiffies; + data->valid[pid] = 1; -exit_remove: - sysfs_remove_group(&client->dev.kobj, &as5916_54xks_psu_group); -exit_free: - kfree(data); exit: - - return status; + return data; } -static int as5916_54xks_psu_remove(struct i2c_client *client) -{ - struct as5916_54xks_psu_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &as5916_54xks_psu_group); - kfree(data); - - return 0; +#define VALIDATE_PRESENT_RETURN(id) \ +{ \ + if (data->ipmi_resp[id].status[PSU_PRESENT] != 0) { \ + mutex_unlock(&data->update_lock); \ + return -ENXIO; \ + } \ } -enum psu_index -{ - as5916_54xks_psu1, - as5916_54xks_psu2 -}; - -static const struct i2c_device_id as5916_54xks_psu_id[] = { - { "as5916_54xks_psu1", as5916_54xks_psu1 }, - { "as5916_54xks_psu2", as5916_54xks_psu2 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, as5916_54xks_psu_id); - -static struct i2c_driver as5916_54xks_psu_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "as5916_54xks_psu", - }, - .probe = as5916_54xks_psu_probe, - .remove = as5916_54xks_psu_remove, - .id_table = as5916_54xks_psu_id, - .address_list = normal_i2c, -}; - -static int as5916_54xks_psu_read_block(struct i2c_client *client, u8 command, u8 *data, - int data_len) +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) { - 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; + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; } -static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct device *dev) +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct as5916_54xks_psu_data *data = i2c_get_clientdata(client); - + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + u16 value = 0; + int error = 0; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + 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 as5916_54xks update\n"); - - /* Read psu status */ - status = as5916_54xks_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 & BIT(3 - data->index); - - if (power_good) { - status = as5916_54xks_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; + data = as5916_54xks_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; } + switch (attr->index) { + case PSU1_VOUT: + case PSU2_VOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_VOUT0] | + (u16)data->ipmi_resp[pid].status[PSU_VOUT1] << 8); + break; + case PSU1_IOUT: + case PSU2_IOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_IOUT0] | + (u16)data->ipmi_resp[pid].status[PSU_IOUT1] << 8); + break; + case PSU1_POUT: + case PSU2_POUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_POUT0] | + (u16)data->ipmi_resp[pid].status[PSU_POUT1] << 8); + break; + default: + error = -EINVAL; + goto exit; + } + mutex_unlock(&data->update_lock); - return data; + 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)); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as5916_54xks_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + value = !(data->ipmi_resp[pid].status[PSU_PRESENT]); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + VALIDATE_PRESENT_RETURN(pid); + value = data->ipmi_resp[pid].status[PSU_POWER_GOOD_CPLD]; + break; + case PSU1_TEMP_INPUT: + case PSU2_TEMP_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_TEMP0] | + (u32)data->ipmi_resp[pid].status[PSU_TEMP1] << 8) * 1000; + break; + case PSU1_FAN_INPUT: + case PSU2_FAN_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_FAN0] | + (u32)data->ipmi_resp[pid].status[PSU_FAN1] << 8); + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + char *str = NULL; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as5916_54xks_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_MODEL: + case PSU2_MODEL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].model; + break; + case PSU1_SERIAL: + case PSU2_SERIAL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].serial; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", str); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static int as5916_54xks_psu_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_psu_group); + if (status) { + goto exit; + } + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xks_psu_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_psu_group); + return 0; } static int __init as5916_54xks_psu_init(void) { - return i2c_add_driver(&as5916_54xks_psu_driver); + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_psu_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xks_psu_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_psu_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; } static void __exit as5916_54xks_psu_exit(void) { - i2c_del_driver(&as5916_54xks_psu_driver); + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_psu_driver); + kfree(data); } +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XKS PSU driver"); +MODULE_LICENSE("GPL"); + module_init(as5916_54xks_psu_init); module_exit(as5916_54xks_psu_exit); -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("as5916_54xks_psu driver"); -MODULE_LICENSE("GPL"); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sfp.c new file mode 100644 index 00000000..9e843094 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sfp.c @@ -0,0 +1,1675 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xks_sfp" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_QSFP_READ_CMD 0x10 +#define IPMI_QSFP_WRITE_CMD 0x11 +#define IPMI_SFP_READ_CMD 0x1C +#define IPMI_SFP_WRITE_CMD 0x1D +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_DATA_MAX_LEN 128 + +#define SFP_EEPROM_SIZE 768 +#define QSFP_EEPROM_SIZE 640 + +#define NUM_OF_SFP 48 +#define NUM_OF_QSFP 6 +#define NUM_OF_PORT (NUM_OF_SFP + NUM_OF_QSFP) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_sfp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf); +static int as5916_54xks_sfp_probe(struct platform_device *pdev); +static int as5916_54xks_sfp_remove(struct platform_device *pdev); +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf); +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_present(void); +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txdisable(void); +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txfault(void); +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_rxlos(void); +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_present(void); +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_txdisable(void); +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_reset(void); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +enum module_status { + SFP_PRESENT = 0, + SFP_TXDISABLE, + SFP_TXFAULT, + SFP_RXLOS, + NUM_OF_SFP_STATUS, + + QSFP_PRESENT = 0, + QSFP_TXDISABLE, + QSFP_RESET, + QSFP_LPMODE, + NUM_OF_QSFP_STATUS, + + PRESENT_ALL = 0, + RXLOS_ALL +}; + +struct ipmi_sfp_resp_data { + unsigned char eeprom[IPMI_DATA_MAX_LEN]; + char eeprom_valid; + + char sfp_valid[NUM_OF_SFP_STATUS]; /* != 0 if registers are valid */ + unsigned long sfp_last_updated[NUM_OF_SFP_STATUS]; /* In jiffies */ + unsigned char sfp_resp[NUM_OF_SFP_STATUS][NUM_OF_SFP]; /* 0: present, 1: tx-disable + 2: tx-fault, 3: rx-los */ + char qsfp_valid[NUM_OF_QSFP_STATUS]; /* != 0 if registers are valid */ + unsigned long qsfp_last_updated[NUM_OF_QSFP_STATUS]; /* In jiffies */ + unsigned char qsfp_resp[NUM_OF_QSFP_STATUS][NUM_OF_QSFP]; /* 0: present, 1: tx-disable, + 2: reset , 3: low power mode */ +}; + +struct as5916_54xks_sfp_data { + struct platform_device *pdev; + struct mutex update_lock; + struct ipmi_data ipmi; + struct ipmi_sfp_resp_data ipmi_resp; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom[NUM_OF_PORT]; /* eeprom data */ +}; + +struct sfp_eeprom_write_data { + unsigned char ipmi_tx_data[4]; /* 0:port index 1:page number 2:offset 3:Data len */ + unsigned char write_buf[IPMI_DATA_MAX_LEN]; +}; + +struct as5916_54xks_sfp_data *data = NULL; + +static struct platform_driver as5916_54xks_sfp_driver = { + .probe = as5916_54xks_sfp_probe, + .remove = as5916_54xks_sfp_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define SFP_PRESENT_ATTR_ID(port) SFP##port##_PRESENT +#define SFP_TXDISABLE_ATTR_ID(port) SFP##port##_TXDISABLE +#define SFP_TXFAULT_ATTR_ID(port) SFP##port##_TXFAULT +#define SFP_RXLOS_ATTR_ID(port) SFP##port##_RXLOS + +#define SFP_ATTR(port) \ + SFP_PRESENT_ATTR_ID(port), \ + SFP_TXDISABLE_ATTR_ID(port), \ + SFP_TXFAULT_ATTR_ID(port), \ + SFP_RXLOS_ATTR_ID(port) + +#define QSFP_PRESENT_ATTR_ID(port) QSFP##port##_PRESENT +#define QSFP_TXDISABLE_ATTR_ID(port) QSFP##port##_TXDISABLE +#define QSFP_RESET_ATTR_ID(port) QSFP##port##_RESET +#define QSFP_LPMODE_ATTR_ID(port) QSFP##port##_LPMODE + +#define QSFP_ATTR(port) \ + QSFP_PRESENT_ATTR_ID(port), \ + QSFP_TXDISABLE_ATTR_ID(port), \ + QSFP_RESET_ATTR_ID(port), \ + QSFP_LPMODE_ATTR_ID(port) + +enum as5916_54x_sfp_sysfs_attrs { + SFP_ATTR(1), + SFP_ATTR(2), + SFP_ATTR(3), + SFP_ATTR(4), + SFP_ATTR(5), + SFP_ATTR(6), + SFP_ATTR(7), + SFP_ATTR(8), + SFP_ATTR(9), + SFP_ATTR(10), + SFP_ATTR(11), + SFP_ATTR(12), + SFP_ATTR(13), + SFP_ATTR(14), + SFP_ATTR(15), + SFP_ATTR(16), + SFP_ATTR(17), + SFP_ATTR(18), + SFP_ATTR(19), + SFP_ATTR(20), + SFP_ATTR(21), + SFP_ATTR(22), + SFP_ATTR(23), + SFP_ATTR(24), + SFP_ATTR(25), + SFP_ATTR(26), + SFP_ATTR(27), + SFP_ATTR(28), + SFP_ATTR(29), + SFP_ATTR(30), + SFP_ATTR(31), + SFP_ATTR(32), + SFP_ATTR(33), + SFP_ATTR(34), + SFP_ATTR(35), + SFP_ATTR(36), + SFP_ATTR(37), + SFP_ATTR(38), + SFP_ATTR(39), + SFP_ATTR(40), + SFP_ATTR(41), + SFP_ATTR(42), + SFP_ATTR(43), + SFP_ATTR(44), + SFP_ATTR(45), + SFP_ATTR(46), + SFP_ATTR(47), + SFP_ATTR(48), + NUM_OF_SFP_ATTR, + NUM_OF_PER_SFP_ATTR = (NUM_OF_SFP_ATTR/NUM_OF_SFP), +}; + +enum as5916_54xks_qsfp_sysfs_attrs { + QSFP_ATTR(49), + QSFP_ATTR(50), + QSFP_ATTR(51), + QSFP_ATTR(52), + QSFP_ATTR(53), + QSFP_ATTR(54), + NUM_OF_QSFP_ATTR, + NUM_OF_PER_QSFP_ATTR = (NUM_OF_QSFP_ATTR/NUM_OF_QSFP), +}; + +/* sfp attributes */ +#define DECLARE_SFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_sfp, NULL, SFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_sfp, set_sfp, SFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##port, S_IRUGO, show_sfp, NULL, SFP##port##_TXFAULT); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##port, S_IRUGO, show_sfp, NULL, SFP##port##_RXLOS) +#define DECLARE_SFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##port.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##port.dev_attr.attr + +/* qsfp attributes */ +#define DECLARE_QSFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_qsfp, NULL, QSFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_txdisable, QSFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_reset_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_reset, QSFP##port##_RESET); \ + static SENSOR_DEVICE_ATTR(module_lpmode_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_lpmode, QSFP##port##_LPMODE) +#define DECLARE_QSFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##port.dev_attr.attr, \ + &sensor_dev_attr_module_lpmode_##port.dev_attr.attr + +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_all, NULL, PRESENT_ALL); \ +static SENSOR_DEVICE_ATTR(module_rxlos_all, S_IRUGO, show_all, NULL, RXLOS_ALL); \ + +DECLARE_SFP_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_SENSOR_DEVICE_ATTR(48); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5916_54xks_sfp_attributes[] = { + /* sfp attributes */ + DECLARE_SFP_ATTR(1), + DECLARE_SFP_ATTR(2), + DECLARE_SFP_ATTR(3), + DECLARE_SFP_ATTR(4), + DECLARE_SFP_ATTR(5), + DECLARE_SFP_ATTR(6), + DECLARE_SFP_ATTR(7), + DECLARE_SFP_ATTR(8), + DECLARE_SFP_ATTR(9), + DECLARE_SFP_ATTR(10), + DECLARE_SFP_ATTR(11), + DECLARE_SFP_ATTR(12), + DECLARE_SFP_ATTR(13), + DECLARE_SFP_ATTR(14), + DECLARE_SFP_ATTR(15), + DECLARE_SFP_ATTR(16), + DECLARE_SFP_ATTR(17), + DECLARE_SFP_ATTR(18), + DECLARE_SFP_ATTR(19), + DECLARE_SFP_ATTR(20), + DECLARE_SFP_ATTR(21), + DECLARE_SFP_ATTR(22), + DECLARE_SFP_ATTR(23), + DECLARE_SFP_ATTR(24), + DECLARE_SFP_ATTR(25), + DECLARE_SFP_ATTR(26), + DECLARE_SFP_ATTR(27), + DECLARE_SFP_ATTR(28), + DECLARE_SFP_ATTR(29), + DECLARE_SFP_ATTR(30), + DECLARE_SFP_ATTR(31), + DECLARE_SFP_ATTR(32), + DECLARE_SFP_ATTR(33), + DECLARE_SFP_ATTR(34), + DECLARE_SFP_ATTR(35), + DECLARE_SFP_ATTR(36), + DECLARE_SFP_ATTR(37), + DECLARE_SFP_ATTR(38), + DECLARE_SFP_ATTR(39), + DECLARE_SFP_ATTR(40), + DECLARE_SFP_ATTR(41), + DECLARE_SFP_ATTR(42), + DECLARE_SFP_ATTR(43), + DECLARE_SFP_ATTR(44), + DECLARE_SFP_ATTR(45), + DECLARE_SFP_ATTR(46), + DECLARE_SFP_ATTR(47), + DECLARE_SFP_ATTR(48), + DECLARE_QSFP_ATTR(49), + DECLARE_QSFP_ATTR(50), + DECLARE_QSFP_ATTR(51), + DECLARE_QSFP_ATTR(52), + DECLARE_QSFP_ATTR(53), + DECLARE_QSFP_ATTR(54), + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rxlos_all.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5916_54xks_sfp_group = { + .attrs = as5916_54xks_sfp_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_PRESENT] + HZ) && + data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_PRESENT], + sizeof(data->ipmi_resp.sfp_resp[SFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_PRESENT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXDISABLE], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txfault(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXFAULT], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXFAULT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_rxlos(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_RXLOS] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x13; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_RXLOS], + sizeof(data->ipmi_resp.sfp_resp[SFP_RXLOS])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_RXLOS] = jiffies; + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] + HZ) && + data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_PRESENT], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_reset(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_RESET] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_RESET], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_RESET])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_RESET] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 1; + +exit: + return data; +} + +static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_lpmode(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_LPMODE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_LPMODE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 1; + +exit: + return data; +} + +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u64 values = 0; + int i; + + switch (attr->index) { + case PRESENT_ALL: + { + mutex_lock(&data->update_lock); + + data = as5916_54xks_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + data = as5916_54xks_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + /* Update qsfp present status */ + for (i = (NUM_OF_QSFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.qsfp_resp[QSFP_PRESENT][i] & 0x1); + } + + /* Update sfp present status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.sfp_resp[SFP_PRESENT][i] & 0x1); + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40)), + (unsigned int)(0x3F & (values >> 48))); + } + case RXLOS_ALL: + { + mutex_lock(&data->update_lock); + + data = as5916_54xks_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + /* Update sfp rxlos status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= !(data->ipmi_resp.sfp_resp[SFP_RXLOS][i] & 0x1); + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40))); + } + default: + break; + } + + return 0; +} + +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + switch (attr->index) { + case SFP1_PRESENT: + case SFP2_PRESENT: + case SFP3_PRESENT: + case SFP4_PRESENT: + case SFP5_PRESENT: + case SFP6_PRESENT: + case SFP7_PRESENT: + case SFP8_PRESENT: + case SFP9_PRESENT: + case SFP10_PRESENT: + case SFP11_PRESENT: + case SFP12_PRESENT: + case SFP13_PRESENT: + case SFP14_PRESENT: + case SFP15_PRESENT: + case SFP16_PRESENT: + case SFP17_PRESENT: + case SFP18_PRESENT: + case SFP19_PRESENT: + case SFP20_PRESENT: + case SFP21_PRESENT: + case SFP22_PRESENT: + case SFP23_PRESENT: + case SFP24_PRESENT: + case SFP25_PRESENT: + case SFP26_PRESENT: + case SFP27_PRESENT: + case SFP28_PRESENT: + case SFP29_PRESENT: + case SFP30_PRESENT: + case SFP31_PRESENT: + case SFP32_PRESENT: + case SFP33_PRESENT: + case SFP34_PRESENT: + case SFP35_PRESENT: + case SFP36_PRESENT: + case SFP37_PRESENT: + case SFP38_PRESENT: + case SFP39_PRESENT: + case SFP40_PRESENT: + case SFP41_PRESENT: + case SFP42_PRESENT: + case SFP43_PRESENT: + case SFP44_PRESENT: + case SFP45_PRESENT: + case SFP46_PRESENT: + case SFP47_PRESENT: + case SFP48_PRESENT: + { + data = as5916_54xks_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.sfp_resp[SFP_PRESENT][pid]; + break; + } + case SFP1_TXDISABLE: + case SFP2_TXDISABLE: + case SFP3_TXDISABLE: + case SFP4_TXDISABLE: + case SFP5_TXDISABLE: + case SFP6_TXDISABLE: + case SFP7_TXDISABLE: + case SFP8_TXDISABLE: + case SFP9_TXDISABLE: + case SFP10_TXDISABLE: + case SFP11_TXDISABLE: + case SFP12_TXDISABLE: + case SFP13_TXDISABLE: + case SFP14_TXDISABLE: + case SFP15_TXDISABLE: + case SFP16_TXDISABLE: + case SFP17_TXDISABLE: + case SFP18_TXDISABLE: + case SFP19_TXDISABLE: + case SFP20_TXDISABLE: + case SFP21_TXDISABLE: + case SFP22_TXDISABLE: + case SFP23_TXDISABLE: + case SFP24_TXDISABLE: + case SFP25_TXDISABLE: + case SFP26_TXDISABLE: + case SFP27_TXDISABLE: + case SFP28_TXDISABLE: + case SFP29_TXDISABLE: + case SFP30_TXDISABLE: + case SFP31_TXDISABLE: + case SFP32_TXDISABLE: + case SFP33_TXDISABLE: + case SFP34_TXDISABLE: + case SFP35_TXDISABLE: + case SFP36_TXDISABLE: + case SFP37_TXDISABLE: + case SFP38_TXDISABLE: + case SFP39_TXDISABLE: + case SFP40_TXDISABLE: + case SFP41_TXDISABLE: + case SFP42_TXDISABLE: + case SFP43_TXDISABLE: + case SFP44_TXDISABLE: + case SFP45_TXDISABLE: + case SFP46_TXDISABLE: + case SFP47_TXDISABLE: + case SFP48_TXDISABLE: + { + data = as5916_54xks_sfp_update_txdisable(); + if (!data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid]; + break; + } + case SFP1_TXFAULT: + case SFP2_TXFAULT: + case SFP3_TXFAULT: + case SFP4_TXFAULT: + case SFP5_TXFAULT: + case SFP6_TXFAULT: + case SFP7_TXFAULT: + case SFP8_TXFAULT: + case SFP9_TXFAULT: + case SFP10_TXFAULT: + case SFP11_TXFAULT: + case SFP12_TXFAULT: + case SFP13_TXFAULT: + case SFP14_TXFAULT: + case SFP15_TXFAULT: + case SFP16_TXFAULT: + case SFP17_TXFAULT: + case SFP18_TXFAULT: + case SFP19_TXFAULT: + case SFP20_TXFAULT: + case SFP21_TXFAULT: + case SFP22_TXFAULT: + case SFP23_TXFAULT: + case SFP24_TXFAULT: + case SFP25_TXFAULT: + case SFP26_TXFAULT: + case SFP27_TXFAULT: + case SFP28_TXFAULT: + case SFP29_TXFAULT: + case SFP30_TXFAULT: + case SFP31_TXFAULT: + case SFP32_TXFAULT: + case SFP33_TXFAULT: + case SFP34_TXFAULT: + case SFP35_TXFAULT: + case SFP36_TXFAULT: + case SFP37_TXFAULT: + case SFP38_TXFAULT: + case SFP39_TXFAULT: + case SFP40_TXFAULT: + case SFP41_TXFAULT: + case SFP42_TXFAULT: + case SFP43_TXFAULT: + case SFP44_TXFAULT: + case SFP45_TXFAULT: + case SFP46_TXFAULT: + case SFP47_TXFAULT: + case SFP48_TXFAULT: + { + data = as5916_54xks_sfp_update_txfault(); + if (!data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.sfp_resp[SFP_TXFAULT][pid]; + break; + } + case SFP1_RXLOS: + case SFP2_RXLOS: + case SFP3_RXLOS: + case SFP4_RXLOS: + case SFP5_RXLOS: + case SFP6_RXLOS: + case SFP7_RXLOS: + case SFP8_RXLOS: + case SFP9_RXLOS: + case SFP10_RXLOS: + case SFP11_RXLOS: + case SFP12_RXLOS: + case SFP13_RXLOS: + case SFP14_RXLOS: + case SFP15_RXLOS: + case SFP16_RXLOS: + case SFP17_RXLOS: + case SFP18_RXLOS: + case SFP19_RXLOS: + case SFP20_RXLOS: + case SFP21_RXLOS: + case SFP22_RXLOS: + case SFP23_RXLOS: + case SFP24_RXLOS: + case SFP25_RXLOS: + case SFP26_RXLOS: + case SFP27_RXLOS: + case SFP28_RXLOS: + case SFP29_RXLOS: + case SFP30_RXLOS: + case SFP31_RXLOS: + case SFP32_RXLOS: + case SFP33_RXLOS: + case SFP34_RXLOS: + case SFP35_RXLOS: + case SFP36_RXLOS: + case SFP37_RXLOS: + case SFP38_RXLOS: + case SFP39_RXLOS: + case SFP40_RXLOS: + case SFP41_RXLOS: + case SFP42_RXLOS: + case SFP43_RXLOS: + case SFP44_RXLOS: + case SFP45_RXLOS: + case SFP46_RXLOS: + case SFP47_RXLOS: + case SFP48_RXLOS: + { + data = as5916_54xks_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.sfp_resp[SFP_RXLOS][pid]; + break; + } + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_sfp(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); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + disable = !disable; /* the IPMI cmd is 0 for tx-disable and 1 for tx-enable */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid] = disable; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + switch (attr->index) { + case QSFP49_PRESENT: + case QSFP50_PRESENT: + case QSFP51_PRESENT: + case QSFP52_PRESENT: + case QSFP53_PRESENT: + case QSFP54_PRESENT: + { + data = as5916_54xks_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]; + break; + } + case QSFP49_TXDISABLE: + case QSFP50_TXDISABLE: + case QSFP51_TXDISABLE: + case QSFP52_TXDISABLE: + case QSFP53_TXDISABLE: + case QSFP54_TXDISABLE: + { + data = as5916_54xks_qsfp_update_txdisable(); + if (!data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + error = -EIO; + goto exit; + } + + value = !!data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid]; + break; + } + case QSFP49_RESET: + case QSFP50_RESET: + case QSFP51_RESET: + case QSFP52_RESET: + case QSFP53_RESET: + case QSFP54_RESET: + { + data = as5916_54xks_qsfp_update_reset(); + if (!data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.qsfp_resp[QSFP_RESET][pid]; + break; + } + case QSFP49_LPMODE: + case QSFP50_LPMODE: + case QSFP51_LPMODE: + case QSFP52_LPMODE: + case QSFP53_LPMODE: + case QSFP54_LPMODE: + { + data = as5916_54xks_qsfp_update_lpmode(); + if (!data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid]; + break; + } + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_qsfp_txdisable(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); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + mutex_lock(&data->update_lock); + + data = as5916_54xks_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + status = -EIO; + goto exit; + } + + if (!data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]) { + status = -ENXIO; + goto exit; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + goto exit; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable ? 0xf : 0; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid] = disable; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + reset = !reset; /* the IPMI cmd is 0 for reset and 1 for out of reset */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x11; + data->ipmi_tx_data[2] = reset; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_RESET][pid] = reset; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long lpmode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &lpmode); + if (status) { + return status; + } + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x12; + data->ipmi_tx_data[2] = lpmode; /* 0: High Power Mode, 1: Low Power Mode */ + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid] = lpmode; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~48 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1C 1" +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 2" +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1C 3" +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1C 4" +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1C 5" + +QSFP: PS: index of QSFP is 1~6" +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x10 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x10 1" +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x10 2" +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x10 3" +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x10 4" +**************************************************************************************/ +static ssize_t sfp_eeprom_read(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_READ_CMD : IPMI_QSFP_READ_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + + data->ipmi_resp.eeprom_valid = 0; + data->ipmi_tx_data[0] = ipmi_port_id; + data->ipmi_tx_data[1] = ipmi_page; + status = ipmi_send_message(&data->ipmi, cmd, data->ipmi_tx_data, 2, + data->ipmi_resp.eeprom, IPMI_DATA_MAX_LEN); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Calculate return length */ + if (count < length) { + length = count; + } + + memcpy(buf, data->ipmi_resp.eeprom + (off % IPMI_DATA_MAX_LEN), length); + data->ipmi_resp.eeprom_valid = 1; + return length; + +exit: + return status; +} + + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~48 +ipmitool raw 0x34 0x1d +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1d 1 offset " +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 2 offset " +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1d 3 offset " +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1d 4 offset " +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1d 5 offset " + +QSFP: PS: index of QSFP is 1~6" +ipmitool raw 0x34 0x11 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x11 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x11 1 offset " +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x11 2 offset " +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x11 3 offset " +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x11 4 offset " +**************************************************************************************/ +static ssize_t sfp_eeprom_write(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_WRITE_CMD : IPMI_QSFP_WRITE_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + struct sfp_eeprom_write_data wdata; + + /* Calculate write length */ + if (count < length) { + length = count; + } + + wdata.ipmi_tx_data[0] = ipmi_port_id; + wdata.ipmi_tx_data[1] = ipmi_page; + wdata.ipmi_tx_data[2] = (off % IPMI_DATA_MAX_LEN); + wdata.ipmi_tx_data[3] = length; + memcpy(&wdata.write_buf, buf, length); + status = ipmi_send_message(&data->ipmi, cmd, &wdata.ipmi_tx_data[0], + length + sizeof(wdata.ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + return length; + +exit: + return status; +} + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * 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(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + +#define EEPROM_FORMAT "module_eeprom_%d" + +static int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, u64 port) +{ + int ret = 0; + char *eeprom_name = NULL; + + eeprom_name = kzalloc(32, GFP_KERNEL); + if (!eeprom_name) { + ret = -ENOMEM; + goto alloc_err; + } + + sprintf(eeprom_name, EEPROM_FORMAT, (int)port); + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = eeprom_name; + eeprom->attr.mode = S_IRUGO | S_IWUSR; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = (port <= NUM_OF_SFP) ? SFP_EEPROM_SIZE : QSFP_EEPROM_SIZE; + eeprom->private = (void*)port; + + /* Create eeprom file */ + ret = sysfs_create_bin_file(kobj, eeprom); + if (unlikely(ret != 0)) { + goto bin_err; + } + + return ret; + +bin_err: + kfree(eeprom_name); +alloc_err: + return ret; +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static int as5916_54xks_sfp_probe(struct platform_device *pdev) +{ + int status = -1; + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom[i], + i+1/* port name start from 1*/); + if (status) { + goto exit; + } + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_sfp_group); + if (status) { + goto exit; + } + + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + /* Remove the eeprom attributes which were created successfully */ + for (--i; i >= 0; i--) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + return status; +} + +static int as5916_54xks_sfp_remove(struct platform_device *pdev) +{ + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_sfp_group); + return 0; +} + +static int __init as5916_54xks_sfp_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_sfp_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xks_sfp_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_sfp_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xks_sfp_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_sfp_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XKS sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xks_sfp_init); +module_exit(as5916_54xks_sfp_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sys.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sys.c new file mode 100644 index 00000000..d4021701 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-sys.c @@ -0,0 +1,888 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xks_sys" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_TCAM_READ_CMD 0x1E +#define IPMI_TCAM_WRITE_CMD 0x1F +#define IPMI_TCAM_RESET_SUBCMD 1 +#define IPMI_TCAM_INT_SUMCMD 2 +#define IPMI_TCAM_INT_MASK_SUBCMD 3 + +#define IPMI_SYSEEPROM_READ_CMD 0x18 +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_NAME "eeprom" +#define EEPROM_SIZE 512 /* 512 byte eeprom */ + +#define IPMI_GET_CPLD_VER_CMD 0x20 +#define MAINBOARD_CPLD1_ADDR 0x60 +#define MAINBOARD_CPLD2_ADDR 0x62 +#define CPU_CPLD_ADDR 0x65 +#define FAN_CPLD_ADDR 0x66 + +#define IPMI_CPLD_READ_CMD 0x22 +#define IPMI_CPLD_WRITE_CMD 0x23 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static int as5916_54xks_sys_probe(struct platform_device *pdev); +static int as5916_54xks_sys_remove(struct platform_device *pdev); +static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_watchdog(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_watchdog(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xks_sys_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct ipmi_data ipmi; + unsigned char ipmi_resp_eeprom[EEPROM_SIZE]; + unsigned char ipmi_resp_tcam; /* tcam reset: (CPLD register 0x51) + Bit0/1: Reserved + Bit 2 : CPU_JTAG_RST + Bit 3 : RESET_SYS_CPLD + Bit 4 : RESET_MAC + Bit 5 : CPLD1_TCAM_SRST_L + Bit 6 : CPLD1_TCAM_PERST_L + Bit 7 : CPLD1_TCAM_CRST_L + tcam interrupt (CPLD register 0x62) + tcam interrupt mask (CPLD register 0x63) + Bit 0 : TCAM_CPLD1_GIO_L_1 + Bit 1 : TCAM_CPLD1_GIO_L_0 */ + unsigned char ipmi_resp_cpld; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom; /* eeprom data */ +}; + +struct as5916_54xks_sys_data *data = NULL; + +static struct platform_driver as5916_54xks_sys_driver = { + .probe = as5916_54xks_sys_probe, + .remove = as5916_54xks_sys_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as5916_54xks_sys_sysfs_attrs { + SYS_RESET_6_BIT0, /* Not Used */ + SYS_RESET_6_BIT1, /* Not Used */ + CPU_JTAG_RST, + RESET_SYS_CPLD, + RESET_MAC, + TCAM_SRST_L, + TCAM_PERST_L, + TCAM_CRST_L, + TCAM_RST_ALL, + SYS_RESET_6_ALL, + TCAM_CPLD1_GIO_L, + TCAM_CPLD1_GIO_L_MASK, + MB_CPLD1_VER, /* mainboard cpld1 version */ + MB_CPLD2_VER, /* mainboard cpld2 version */ + CPU_CPLD_VER, /* CPU board CPLD version */ + FAN_CPLD_VER, /* FAN CPLD version */ + CPU_CPLD_WDS1,/* CPU board CPLD Offset 0x02 Watch Dog Status_1 */ + CPU_CPLD_WDS2,/* CPU board CPLD Offset 0x03 Watch Dog Status_2 */ + CPU_CPLD_SR, /* CPU board CPLD Offset 0x04 System Reset */ + CPU_CPLD_LRS, /* CPU board CPLD Offset 0x24 Last Reset Reason Register */ + MB_CPLD_SR1, /* main board CPLD Offset 0x08 System Reset-1 */ +}; + +static SENSOR_DEVICE_ATTR(tcam_rst_c, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_CRST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_pe, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_PERST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_s, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_SRST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_all, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_RST_ALL); +static SENSOR_DEVICE_ATTR(sys_rst_6, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, SYS_RESET_6_ALL); +static SENSOR_DEVICE_ATTR(tcam_int, S_IRUGO, show_interrupt_status_6, NULL, TCAM_CPLD1_GIO_L); +static SENSOR_DEVICE_ATTR(tcam_int_msk, S_IWUSR | S_IRUGO, show_interrupt_status_6, set_interrupt_status_6_mask, TCAM_CPLD1_GIO_L_MASK); +static SENSOR_DEVICE_ATTR(mb_cpld1_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD1_VER); +static SENSOR_DEVICE_ATTR(mb_cpld2_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD2_VER); +static SENSOR_DEVICE_ATTR(cpu_cpld_ver, S_IRUGO, show_cpld_version, NULL, CPU_CPLD_VER); +static SENSOR_DEVICE_ATTR(fan_cpld_ver, S_IRUGO, show_cpld_version, NULL, FAN_CPLD_VER); +static SENSOR_DEVICE_ATTR(cpu_cpld_wds1, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_WDS1); +static SENSOR_DEVICE_ATTR(cpu_cpld_wds2, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_WDS2); +static SENSOR_DEVICE_ATTR(cpu_cpld_system_reset, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_SR); +static SENSOR_DEVICE_ATTR(cpu_cpld_last_reset_reson, S_IRUGO, show_watchdog, NULL, CPU_CPLD_LRS); +static SENSOR_DEVICE_ATTR(mb_cpld1_system_reset1, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, MB_CPLD_SR1); + + +static struct attribute *as5916_54xks_sys_attributes[] = { + &sensor_dev_attr_tcam_rst_c.dev_attr.attr, + &sensor_dev_attr_tcam_rst_pe.dev_attr.attr, + &sensor_dev_attr_tcam_rst_s.dev_attr.attr, + &sensor_dev_attr_tcam_rst_all.dev_attr.attr, + &sensor_dev_attr_sys_rst_6.dev_attr.attr, + &sensor_dev_attr_tcam_int.dev_attr.attr, + &sensor_dev_attr_tcam_int_msk.dev_attr.attr, + &sensor_dev_attr_mb_cpld1_ver.dev_attr.attr, + &sensor_dev_attr_mb_cpld2_ver.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_ver.dev_attr.attr, + &sensor_dev_attr_fan_cpld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_wds1.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_wds2.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_system_reset.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_last_reset_reson.dev_attr.attr, + &sensor_dev_attr_mb_cpld1_system_reset1.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5916_54xks_sys_group = { + .attrs = as5916_54xks_sys_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) +{ + int status = 0; + unsigned char length = 0; + + if ((off + count) > EEPROM_SIZE) { + return -EINVAL; + } + + length = (count >= IPMI_READ_MAX_LEN) ? IPMI_READ_MAX_LEN : count; + data->ipmi_tx_data[0] = (off >> 8) & 0xff; + data->ipmi_tx_data[1] = (off & 0xff); + data->ipmi_tx_data[2] = length; + status = ipmi_send_message(&data->ipmi, IPMI_SYSEEPROM_READ_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), + data->ipmi_resp_eeprom + off, length); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = length; /* Read length */ + memcpy(buf, data->ipmi_resp_eeprom + off, length); + +exit: + return status; +} + +static ssize_t sysfs_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + 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 + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sys_eeprom_read(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 int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IRUGO; + eeprom->read = sysfs_bin_read; + eeprom->write = NULL; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + return sysfs_create_bin_file(kobj, eeprom); +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static struct as5916_54xks_sys_data *as5916_54xks_sys_update_tcam(unsigned char subcmd) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = subcmd; + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_READ_CMD, data->ipmi_tx_data, 1, + &data->ipmi_resp_tcam, sizeof(data->ipmi_resp_tcam)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; /* reset value to be set */ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD); + if (!data->valid) { + status = -EIO; + goto exit; + } + + switch (attr->index) { + case SYS_RESET_6_BIT0: + case SYS_RESET_6_BIT1: + case CPU_JTAG_RST: + case RESET_SYS_CPLD: + case RESET_MAC: + case TCAM_SRST_L: + case TCAM_PERST_L: + case TCAM_CRST_L: + data->ipmi_tx_data[1] = reset ? (data->ipmi_resp_tcam | (1 << attr->index)): + (data->ipmi_resp_tcam & ~(1 << attr->index)); + break; + case TCAM_RST_ALL: + data->ipmi_tx_data[1] = (data->ipmi_resp_tcam & 0x1f) | (reset << TCAM_SRST_L); + break; + case SYS_RESET_6_ALL: + data->ipmi_tx_data[1] = reset; + break; + default: + status = -EINVAL; + goto exit; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = IPMI_TCAM_RESET_SUBCMD; + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD, + data->ipmi_tx_data, 2, NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD); + if (!data->valid) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case SYS_RESET_6_BIT0: + case SYS_RESET_6_BIT1: + case CPU_JTAG_RST: + case RESET_SYS_CPLD: + case RESET_MAC: + case TCAM_SRST_L: + case TCAM_PERST_L: + case TCAM_CRST_L: + value = !!(data->ipmi_resp_tcam & (1 << attr->index)); + break; + case TCAM_RST_ALL: + value = (data->ipmi_resp_tcam >> 5) & 0x7; + break; + case SYS_RESET_6_ALL: + value = data->ipmi_resp_tcam & 0xff; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char subcmd = 0; + int value = 0; + int error = 0; + + switch (attr->index) { + case TCAM_CPLD1_GIO_L: + subcmd = IPMI_TCAM_INT_SUMCMD; + break; + case TCAM_CPLD1_GIO_L_MASK: + subcmd = IPMI_TCAM_INT_MASK_SUBCMD; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_tcam(subcmd); + if (!data->valid) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp_tcam & 0x3; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mask = 0; /* mask value to be set */ + int status; + + status = kstrtol(buf, 10, &mask); + if (status) { + return status; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_tcam(IPMI_TCAM_INT_MASK_SUBCMD); + if (!data->valid) { + status = -EIO; + goto exit; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = IPMI_TCAM_INT_MASK_SUBCMD; + data->ipmi_tx_data[1] = (data->ipmi_resp_tcam & 0xfc) | (mask & 0x3); + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD, + data->ipmi_tx_data, 2, NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static struct as5916_54xks_sys_data *as5916_54xks_sys_update_cpld_ver(unsigned char cpld_addr) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = cpld_addr; + status = ipmi_send_message(&data->ipmi, IPMI_GET_CPLD_VER_CMD, data->ipmi_tx_data, 1, + &data->ipmi_resp_cpld, sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char cpld_addr = 0, value = 0; + int error = 0; + + switch (attr->index) { + case MB_CPLD1_VER: + cpld_addr = MAINBOARD_CPLD1_ADDR; + break; + case MB_CPLD2_VER: + cpld_addr = MAINBOARD_CPLD2_ADDR; + break; + case CPU_CPLD_VER: + cpld_addr = CPU_CPLD_ADDR; + break; + case FAN_CPLD_VER: + cpld_addr = FAN_CPLD_ADDR; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_cpld_ver(cpld_addr); + if (!data->valid) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp_cpld; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static struct as5916_54xks_sys_data *as5916_54xks_sys_update_watchdog(unsigned char cpld_addr, + unsigned char reg) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = cpld_addr; + data->ipmi_tx_data[1] = reg; + status = ipmi_send_message(&data->ipmi, IPMI_CPLD_READ_CMD, data->ipmi_tx_data, 2, + &data->ipmi_resp_cpld, sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +/* Get CPLD¡¦s Offset Value + * ipmitool raw 0x34 0x22 + * # ipmitool raw 0x34 0x22 0x65 0x02 + * # ipmitool raw 0x34 0x22 0x65 0x03 + * # ipmitool raw 0x34 0x22 0x65 0x04 + * # ipmitool raw 0x34 0x22 0x65 0x24 + * # ipmitool raw 0x34 0x22 0x60 0x08 + */ +static ssize_t show_watchdog(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char cpld_addr = 0, reg = 0, value = 0; + int error = 0; + + switch (attr->index) { + case CPU_CPLD_WDS1: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x2; + break; + case CPU_CPLD_WDS2: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x3; + break; + case CPU_CPLD_SR: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x4; + break; + case CPU_CPLD_LRS: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x24; + break; + case MB_CPLD_SR1: + cpld_addr = MAINBOARD_CPLD1_ADDR; + reg = 0x8; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + data = as5916_54xks_sys_update_watchdog(cpld_addr, reg); + if (!data->valid) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp_cpld; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +/* Set CPLDValue + * # ipmitool raw 0x34 0x23 + * # ipmitool raw 0x34 0x23 0x65 0x03 0x08 + */ +static ssize_t set_watchdog(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long value = 0; /* cpld value to be set */ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char cpld_addr = 0, reg = 0; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + switch (attr->index) { + case CPU_CPLD_WDS1: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x2; + break; + case CPU_CPLD_WDS2: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x3; + break; + case CPU_CPLD_SR: + cpld_addr = CPU_CPLD_ADDR; + reg = 0x4; + break; + case MB_CPLD_SR1: + cpld_addr = MAINBOARD_CPLD1_ADDR; + reg = 0x8; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = cpld_addr; + data->ipmi_tx_data[1] = reg; + data->ipmi_tx_data[2] = value; + status = ipmi_send_message(&data->ipmi, IPMI_CPLD_WRITE_CMD, + data->ipmi_tx_data, 3, NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as5916_54xks_sys_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom); + if (status) { + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_sys_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xks_sys_remove(struct platform_device *pdev) +{ + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom); + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_sys_group); + + return 0; +} + +static int __init as5916_54xks_sys_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_sys_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xks_sys_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_sys_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xks_sys_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_sys_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916-54XKS System driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xks_sys_init); +module_exit(as5916_54xks_sys_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-thermal.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-thermal.c new file mode 100644 index 00000000..3ba28742 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/modules/builds/x86-64-accton-as5916-54xks-thermal.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xks_thermal" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_THERMAL_READ_CMD 0x12 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xks_thermal_probe(struct platform_device *pdev); +static int as5916_54xks_thermal_remove(struct platform_device *pdev); + +enum temp_data_index { + TEMP_ADDR, + TEMP_FAULT, + TEMP_INPUT, + TEMP_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xks_thermal_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + char ipmi_resp[12]; /* 3 bytes for each thermal */ + struct ipmi_data ipmi; +}; + +struct as5916_54xks_thermal_data *data = NULL; + +static struct platform_driver as5916_54xks_thermal_driver = { + .probe = as5916_54xks_thermal_probe, + .remove = as5916_54xks_thermal_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as5916_54x_thermal_sysfs_attrs { + TEMP1_INPUT, + TEMP2_INPUT, + TEMP3_INPUT, + TEMP4_INPUT, +}; + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, TEMP4_INPUT); + +static struct attribute *as5916_54xks_thermal_attributes[] = { + &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, + NULL +}; + +static const struct attribute_group as5916_54xks_thermal_group = { + .attrs = as5916_54xks_thermal_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = 0; + int index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 5) || !data->valid) { + data->valid = 0; + + status = ipmi_send_message(&data->ipmi, IPMI_THERMAL_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + /* Get temp fault status */ + index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT; + if (unlikely(data->ipmi_resp[index] == 0)) { + status = -EIO; + goto exit; + } + + /* Get temperature in degree celsius */ + index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT; + status = data->ipmi_resp[index] * 1000; + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as5916_54xks_thermal_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xks_thermal_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xks_thermal_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xks_thermal_group); + + return 0; +} + +static int __init as5916_54xks_thermal_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xks_thermal_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xks_thermal_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xks_thermal_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xks_thermal_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xks_thermal_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XKS Thermal driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xks_thermal_init); +module_exit(as5916_54xks_thermal_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/README index 64864843..94773967 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/README +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/README @@ -1,6 +1,6 @@ ############################################################################### # -# x86_64_accton_as5916_54x README +# x86_64_accton_as5916_54xks README # ############################################################################### diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..123580b7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_as5916_54xks Autogeneration +# +############################################################################### +x86_64_accton_as5916_54xks_AUTO_DEFS := module/auto/x86_64_accton_as5916_54xks.yml +x86_64_accton_as5916_54xks_AUTO_DIRS := module/inc/x86_64_accton_as5916_54xks module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/fani.c index 6e990cfd..03c6912a 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/fani.c @@ -100,110 +100,57 @@ _onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) info->status |= ONLP_FAN_STATUS_PRESENT; - /* get fan fault status (turn on when any one fails) + /* get fan direction */ - ret = onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid); - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); - return ONLP_STATUS_E_INTERNAL; - } - - if (value > 0) { - info->status |= ONLP_FAN_STATUS_FAILED; - } + info->status |= ONLP_FAN_STATUS_F2B; - /* get fan direction (both : the same) + /* get fan speed */ - ret = onlp_file_read_int(&value, "%s""fan%d_direction", FAN_BOARD_PATH, fid); - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); - return ONLP_STATUS_E_INTERNAL; - } - - info->status |= value ? ONLP_FAN_STATUS_F2B : ONLP_FAN_STATUS_B2F; - - - /* get front fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid); + ret = onlp_file_read_int(&value, "%s""fan%d_input", FAN_BOARD_PATH, fid); if (ret < 0) { AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); return ONLP_STATUS_E_INTERNAL; } info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; - /* get rear fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid); - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); - return ONLP_STATUS_E_INTERNAL; - } - /* take the min value from front/rear fan speed - */ - if (info->rpm > value) { - info->rpm = value; - } - - /* get speed percentage from rpm - */ - ret = onlp_file_read_int(&value, "%s""fan_max_speed_rpm", FAN_BOARD_PATH); - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); - return ONLP_STATUS_E_INTERNAL; - } - - info->percentage = (info->rpm * 100)/value; - - return ONLP_STATUS_OK; -} - -static uint32_t -_onlp_get_fan_direction_on_psu(void) -{ - /* Try to read direction from PSU1. - * If PSU1 is not valid, read from PSU2 + /* get fan fault status */ - int i = 0; - - for (i = PSU1_ID; i <= PSU2_ID; i++) { - psu_type_t psu_type; - psu_type = get_psu_type(i, NULL, 0); - - if (psu_type == PSU_TYPE_UNKNOWN) { - continue; - } - - if (PSU_TYPE_AC_F2B == psu_type) { - return ONLP_FAN_STATUS_F2B; - } - else { - return ONLP_FAN_STATUS_B2F; - } + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; } - return 0; + return ONLP_STATUS_OK; } static int _onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) { - int val = 0; + int value, ret; info->status |= ONLP_FAN_STATUS_PRESENT; /* get fan direction */ - info->status |= _onlp_get_fan_direction_on_psu(); + info->status |= ONLP_FAN_STATUS_F2B; /* get fan speed */ - if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { - info->rpm = val; - info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; - info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0; + ret = onlp_file_read_int(&value, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", PSU_SYSFS_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED; + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; } return ONLP_STATUS_OK; @@ -264,7 +211,6 @@ int onlp_fani_percentage_set(onlp_oid_t id, int p) { int fid; - char *path = NULL; VALIDATE(id); @@ -275,26 +221,12 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) return ONLP_STATUS_E_INVALID; } - switch (fid) - { - case FAN_1_ON_PSU_1: - return psu_ym2651y_pmbus_info_set(PSU1_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_PSU_2: - return psu_ym2651y_pmbus_info_set(PSU2_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_FAN_BOARD: - case FAN_2_ON_FAN_BOARD: - case FAN_3_ON_FAN_BOARD: - case FAN_4_ON_FAN_BOARD: - case FAN_5_ON_FAN_BOARD: - case FAN_6_ON_FAN_BOARD: - path = FAN_NODE(fan_duty_cycle_percentage); - break; - default: - return ONLP_STATUS_E_INVALID; + if (fid < FAN_1_ON_FAN_BOARD || fid > FAN_6_ON_FAN_BOARD) { + return ONLP_STATUS_E_INVALID; } - if (onlp_file_write_int(p, path) < 0) { - AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + if (onlp_file_write_int(p, "%s""fan%d_pwm", FAN_BOARD_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to write data to file %s""fan%d_pwm", FAN_BOARD_PATH, fid); return ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/ledi.c index ca5c609d..1fbdd731 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/ledi.c @@ -27,7 +27,7 @@ #include #include "platform_lib.h" -#define LED_FORMAT "/sys/class/leds/accton_as5916_54xks_led::%s/brightness" +#define LED_FORMAT "/sys/devices/platform/as5916_54xks_led/%s" #define VALIDATE(_id) \ do { \ @@ -78,8 +78,8 @@ typedef struct led_light_mode_map { } led_light_mode_map_t; led_light_mode_map_t led_map[] = { -{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_LOC, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE}, +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_ORANGE_BLINKING, ONLP_LED_MODE_ORANGE_BLINKING}, {LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, {LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, {LED_DIAG, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE}, @@ -91,11 +91,11 @@ led_light_mode_map_t led_map[] = { static char *leds[] = /* must map with onlp_led_id */ { NULL, - "loc", - "diag", - "psu1", - "psu2", - "fan" + "led_loc", + "led_diag", + "led_psu1", + "led_psu2", + "led_fan" }; /* @@ -107,12 +107,12 @@ static onlp_led_info_t linfo[] = { { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE_BLINKING, }, { { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, }, { { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0 }, @@ -197,7 +197,7 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) info->mode = driver_to_onlp_led_mode(lid, value); /* Set the on/off status */ - if (info->mode != ONLP_LED_MODE_OFF) { + if (info->mode != ONLP_LED_MODE_OFF && info->mode != ONLP_LED_MODE_AUTO) { info->status |= ONLP_LED_STATUS_ON; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.c deleted file mode 100644 index 1837a772..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.c +++ /dev/null @@ -1,124 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2013 Accton Technology Corporation. - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * - ************************************************************ - * - * - * - ***********************************************************/ -#include -#include -#include -#include -#include "platform_lib.h" - -#define PSU_NODE_MAX_PATH_LEN 64 -#define PSU_MODEL_NAME_LEN 9 -#define PSU_FAN_DIR_LEN 3 - -psu_type_t get_psu_type(int id, char* modelname, int modelname_len) -{ - int ret = 0, value = 0; - char model[PSU_MODEL_NAME_LEN + 1] = {0}; - char fan_dir[PSU_FAN_DIR_LEN + 1] = {0}; - char *path = NULL; - - if (modelname && modelname_len < PSU_MODEL_NAME_LEN) { - return PSU_TYPE_UNKNOWN; - } - - /* Check AC model name */ - path = (id == PSU1_ID) ? PSU1_AC_EEPROM_NODE(psu_model_name) : PSU2_AC_EEPROM_NODE(psu_model_name); - ret = onlp_file_read((uint8_t*)model, PSU_MODEL_NAME_LEN, &value, path); - if (ret != ONLP_STATUS_OK || value != PSU_MODEL_NAME_LEN) { - return PSU_TYPE_UNKNOWN; - - } - - if (strncmp(model, "YM-2651Y", strlen("YM-2651Y")) != 0) { - return PSU_TYPE_UNKNOWN; - } - - if (modelname) { - strncpy(modelname, model, modelname_len-1); - } - - path = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); - ret = onlp_file_read((uint8_t*)fan_dir, sizeof(fan_dir), &value, path); - if (ret != ONLP_STATUS_OK) { - return PSU_TYPE_UNKNOWN; - } - - if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { - return PSU_TYPE_AC_F2B; - } - - if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { - return PSU_TYPE_AC_B2F; - } - - return PSU_TYPE_UNKNOWN; -} - -int psu_ym2651y_pmbus_info_get(int id, char *node, int *value) -{ - int ret = 0; - char path[PSU_NODE_MAX_PATH_LEN] = {0}; - - *value = 0; - - if (PSU1_ID == id) { - ret = onlp_file_read_int(value, "%s%s", PSU1_AC_PMBUS_PREFIX, node); - } - else { - ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node); - } - - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); - return ONLP_STATUS_E_INTERNAL; - } - - return ret; -} - -int psu_ym2651y_pmbus_info_set(int id, char *node, int value) -{ - char path[PSU_NODE_MAX_PATH_LEN] = {0}; - - switch (id) { - case PSU1_ID: - sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); - break; - case PSU2_ID: - sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); - break; - default: - return ONLP_STATUS_E_UNSUPPORTED; - }; - - if (onlp_file_write_int(value, path) < 0) { - AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); - return ONLP_STATUS_E_INTERNAL; - } - - return ONLP_STATUS_OK; -} - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.h index ec908afc..ae746c46 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/platform_lib.h @@ -36,22 +36,9 @@ #define PSU1_ID 1 #define PSU2_ID 2 -#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-005b/" -#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/17-0058/" - -#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node -#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node - -#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/18-0053/" -#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/17-0050/" - -#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node -#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node - -#define FAN_BOARD_PATH "/sys/bus/i2c/devices/9-0066/" -#define FAN_NODE(node) FAN_BOARD_PATH#node - -#define IDPROM_PATH "/sys/bus/i2c/devices/0-0056/eeprom" +#define PSU_SYSFS_PATH "/sys/devices/platform/as5916_54xks_psu/" +#define FAN_BOARD_PATH "/sys/devices/platform/as5916_54xks_fan/" +#define IDPROM_PATH "/sys/devices/platform/as5916_54xks_sys/eeprom" enum onlp_thermal_id { @@ -65,16 +52,6 @@ enum onlp_thermal_id THERMAL_1_ON_PSU2, }; -typedef enum psu_type { - PSU_TYPE_UNKNOWN, - PSU_TYPE_AC_F2B, - PSU_TYPE_AC_B2F -} psu_type_t; - -psu_type_t get_psu_type(int id, char* modelname, int modelname_len); -int psu_ym2651y_pmbus_info_get(int id, char *node, int *value); -int psu_ym2651y_pmbus_info_set(int id, char *node, int value); - #define DEBUG_MODE 0 #if (DEBUG_MODE == 1) @@ -86,4 +63,3 @@ int psu_ym2651y_pmbus_info_set(int id, char *node, int value); #endif /* __PLATFORM_LIB_H__ */ - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/psui.c index f7f64f0e..156f9bdb 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/psui.c @@ -29,7 +29,6 @@ #define PSU_STATUS_PRESENT 1 #define PSU_STATUS_POWER_GOOD 1 -#define PSU_NODE_MAX_PATH_LEN 64 #define VALIDATE(_id) \ do { \ @@ -38,65 +37,12 @@ } \ } while(0) -static int -psu_status_info_get(int id, char *node, int *value) -{ - char *prefix = NULL; - - *value = 0; - - prefix = (id == PSU1_ID) ? PSU1_AC_EEPROM_PREFIX : PSU2_AC_EEPROM_PREFIX; - if (onlp_file_read_int(value, "%s%s", prefix, node) < 0) { - AIM_LOG_ERROR("Unable to read status from file(%s%s)\r\n", prefix, node); - return ONLP_STATUS_E_INTERNAL; - } - - return 0; -} - int onlp_psui_init(void) { return ONLP_STATUS_OK; } -static int -psu_ym2651y_info_get(onlp_psu_info_t* info) -{ - int val = 0; - int index = ONLP_OID_ID_GET(info->hdr.id); - - /* Set capability - */ - info->caps = ONLP_PSU_CAPS_AC; - - if (info->status & ONLP_PSU_STATUS_FAILED) { - return ONLP_STATUS_OK; - } - - /* Set the associated oid_table */ - info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); - info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); - - /* Read voltage, current and power */ - if (psu_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) { - info->mvout = val; - info->caps |= ONLP_PSU_CAPS_VOUT; - } - - if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) { - info->miout = val; - info->caps |= ONLP_PSU_CAPS_IOUT; - } - - if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) { - info->mpout = val; - info->caps |= ONLP_PSU_CAPS_POUT; - } - - return ONLP_STATUS_OK; -} - /* * Get all information about the given PSU oid. */ @@ -116,17 +62,18 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) { int val = 0; int ret = ONLP_STATUS_OK; - int index = ONLP_OID_ID_GET(id); - psu_type_t psu_type; + int pid = ONLP_OID_ID_GET(id); VALIDATE(id); memset(info, 0, sizeof(onlp_psu_info_t)); - *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + *info = pinfo[pid]; /* Set the onlp_oid_hdr_t */ /* Get the present state */ - if (psu_status_info_get(index, "psu_present", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + ret = onlp_file_read_int(&val, "%s""psu%d_present", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_present)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; } if (val != PSU_STATUS_PRESENT) { @@ -137,41 +84,71 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) /* Get power good status */ - if (psu_status_info_get(index, "psu_power_good", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + ret = onlp_file_read_int(&val, "%s""psu%d_power_good", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_power_good)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; } if (val != PSU_STATUS_POWER_GOOD) { info->status |= ONLP_PSU_STATUS_FAILED; } + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } - /* Get PSU type - */ - psu_type = get_psu_type(index, info->model, sizeof(info->model)); + /* Read voltage, current and power */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vin", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } - switch (psu_type) { - case PSU_TYPE_AC_F2B: - case PSU_TYPE_AC_B2F: - ret = psu_ym2651y_info_get(info); - break; - case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ - info->status |= ONLP_PSU_STATUS_UNPLUGGED; - info->status &= ~ONLP_PSU_STATUS_FAILED; - ret = ONLP_STATUS_OK; - break; - default: - ret = ONLP_STATUS_E_UNSUPPORTED; - break; + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_iout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_pout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + /* Set the associated oid_table */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(pid + CHASSIS_FAN_COUNT); + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_temp1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(pid + CHASSIS_THERMAL_COUNT); + } + + /* Read model */ + char *string = NULL; + int len = onlp_file_read_str(&string, "%s""psu%d_model", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->model, string, len); + aim_free(string); + } + + /* Read serial */ + len = onlp_file_read_str(&string, "%s""psu%d_serial", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->serial, string, len); + aim_free(string); } return ret; } -int -onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sfpi.c index 86530460..66f63056 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sfpi.c @@ -29,16 +29,13 @@ #include "x86_64_accton_as5916_54xks_int.h" #include "x86_64_accton_as5916_54xks_log.h" -#define PORT_BUS_INDEX(port) (port+33) - -#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" -#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d" -#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" -#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" -#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" -#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all" -#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/11-0060/module_rx_los_all" -#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/12-0062/module_rx_los_all" +#define PORT_EEPROM_FORMAT "/sys/devices/platform/as5916_54xks_sfp/module_eeprom_%d" +#define MODULE_PRESENT_FORMAT "/sys/devices/platform/as5916_54xks_sfp/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/devices/platform/as5916_54xks_sfp/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/devices/platform/as5916_54xks_sfp/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/devices/platform/as5916_54xks_sfp/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/devices/platform/as5916_54xks_sfp/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/devices/platform/as5916_54xks_sfp/module_rxlos_all" /************************************************************ * @@ -76,12 +73,8 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - int bus, addr; - addr = (port < 24) ? 60 : 62; - bus = (addr == 60) ? 11 : 12; - - if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) { + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -92,45 +85,25 @@ onlp_sfpi_is_present(int port) int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7], *ptr = NULL; + uint32_t bytes[7]; FILE* fp; - int addr; - ptr = bytes; + /* Read present status of port 0~54 */ + int count = 0; - for (addr = 60; addr <= 62; addr+=2) { - /* Read present status of port 0~53 */ - int count = 0; - char file[64] = {0}; - int bus = (addr == 60) ? 11 : 12; - - sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr); - fp = fopen(file, "r"); - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr); - return ONLP_STATUS_E_INTERNAL; - } + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file from (%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } - if (addr == 60) { /* CPLD1 */ - count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); - fclose(fp); - if(count != 3) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); - return ONLP_STATUS_E_INTERNAL; - } - } - else { /* CPLD2 */ - count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3); - fclose(fp); - if(count != 4) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); - return ONLP_STATUS_E_INTERNAL; - } - } - - ptr += count; + count = fscanf(fp, "%x %x %x %x %x %x %x", bytes+0, bytes+1, bytes+2, bytes+3, + bytes+4, bytes+5, bytes+6); + fclose(fp); + if(count != 7) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file from(%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; } /* Mask out non-existant QSFP ports */ @@ -157,38 +130,28 @@ int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[6]; - uint32_t *ptr = bytes; FILE* fp; - /* Read present status of port 0~23 */ - int addr, i = 0; + /* Read present status of port 0~25 */ + int count = 0; - for (addr = 60; addr <= 62; addr+=2) { - if (addr == 60) { - fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r"); - } - else { - fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); - } - - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); - return ONLP_STATUS_E_INTERNAL; - } - - int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); - fclose(fp); - if(count != 3) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); - return ONLP_STATUS_E_INTERNAL; - } - - ptr += count; + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rxlos_all device file from (%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; } + count = fscanf(fp, "%x %x %x %x %x %x", bytes+0, bytes+1, bytes+2, + bytes+3, bytes+4, bytes+5); + fclose(fp); + if(count != 6) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rxlos_all device file from(%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + /* Convert to 64 bit integer in port order */ - i = 0; + int i = 0; uint64_t rx_los_all = 0 ; for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { rx_los_all <<= 8; @@ -216,7 +179,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) int size = 0; memset(data, 0, 256); - if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, (port+1)) != ONLP_STATUS_OK) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -229,52 +192,16 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) return ONLP_STATUS_OK; } -int -onlp_sfpi_dom_read(int port, uint8_t data[256]) -{ - FILE* fp; - char file[64] = {0}; - - sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); - fp = fopen(file, "r"); - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); - return ONLP_STATUS_E_INTERNAL; - } - - if (fseek(fp, 256, SEEK_CUR) != 0) { - fclose(fp); - AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); - return ONLP_STATUS_E_INTERNAL; - } - - int ret = fread(data, 1, 256, fp); - fclose(fp); - if (ret != 256) { - AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); - return ONLP_STATUS_E_INTERNAL; - } - - return ONLP_STATUS_OK; -} - int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int rv; - if (port < 0 || port >= 48) { - return ONLP_STATUS_E_UNSUPPORTED; - } - - int addr = (port < 24) ? 60 : 62; - int bus = (addr == 60) ? 11 : 12; - switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -297,18 +224,19 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - if (port < 0 || port >= 48) { + if (port < 0) { return ONLP_STATUS_E_UNSUPPORTED; } - int addr = (port < 24) ? 60 : 62; - int bus = (addr == 60) ? 11 : 12; - switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + if (port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -320,7 +248,11 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { + if (port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -332,7 +264,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c index 21e6daf1..d0e1440d 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -38,15 +37,6 @@ #include "x86_64_accton_as5916_54xks_int.h" #include "x86_64_accton_as5916_54xks_log.h" -#define CPLD_VERSION_FORMAT "/sys/bus/i2c/devices/%s/version" -#define NUM_OF_CPLD 2 - -static char* cpld_path[NUM_OF_CPLD] = -{ - "11-0060", - "12-0062" -}; - const char* onlp_sysi_platform_get(void) { @@ -56,26 +46,17 @@ onlp_sysi_platform_get(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { - int ret = ONLP_STATUS_OK; - int i = 0; - uint8_t* rdata = aim_zmalloc(256); - - for (i = 0; i < 128; i++) { - ret = onlp_i2c_readw(0, 0x56, i*2, ONLP_I2C_F_FORCE); - if (ret < 0) { - aim_free(rdata); - *size = 0; - return ret; + uint8_t* rdata = aim_zmalloc(512); + if(onlp_file_read(rdata, 512, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 512) { + *data = rdata; + return ONLP_STATUS_OK; } - - rdata[i*2] = ret & 0xff; - rdata[i*2+1] = (ret >> 8) & 0xff; } - *size = 256; - *data = rdata; - - return ONLP_STATUS_OK; + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; } int @@ -108,20 +89,38 @@ onlp_sysi_oids_get(onlp_oid_t* table, int max) return 0; } +#define CPLD_VERSION_FORMAT "/sys/devices/platform/as5916_54xks_sys/%s" + +typedef struct cpld_version { + char *attr_name; + int version; + char *description; +} cpld_version_t; + int onlp_sysi_platform_info_get(onlp_platform_info_t* pi) { - int i, v[NUM_OF_CPLD] = {0}; + int i, ret; + cpld_version_t cplds[] = { { "mb_cpld1_ver", 0, "Mainboard-CPLD#1"}, + { "mb_cpld2_ver", 0, "Mainboard-CPLD#2"}, + { "cpu_cpld_ver", 0, "CPU-CPLD"}, + { "fan_cpld_ver", 0, "FAN-CPLD"} }; + /* Read CPLD version + */ + for (i = 0; i < AIM_ARRAYSIZE(cplds); i++) { + ret = onlp_file_read_int(&cplds[i].version, CPLD_VERSION_FORMAT, cplds[i].attr_name); - for (i = 0; i < AIM_ARRAYSIZE(cpld_path); i++) { - v[i] = 0; - - if(onlp_file_read_int(v+i, CPLD_VERSION_FORMAT , cpld_path[i]) < 0) { + if (ret < 0) { + AIM_LOG_ERROR("Unable to read version from CPLD(%s)\r\n", cplds[i].attr_name); return ONLP_STATUS_E_INTERNAL; } } - pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + pi->cpld_versions = aim_fstrdup("%s:%d, %s:%d, %s:%d, %s:%d", + cplds[0].description, cplds[0].version, + cplds[1].description, cplds[1].version, + cplds[2].description, cplds[2].version, + cplds[3].description, cplds[3].version); return ONLP_STATUS_OK; } @@ -131,219 +130,3 @@ onlp_sysi_platform_info_free(onlp_platform_info_t* pi) aim_free(pi->cpld_versions); } -#define FAN_DUTY_MAX (100) -#define FAN_DUTY_MID (69) -#define FAN_DUTY_MIN (38) - -#define FANCTRL_DIR_FACTOR (ONLP_FAN_STATUS_B2F) -#define FANCTRL_DIR_FACTOR_DUTY_ADDON (6) - -static int -sysi_fanctrl_fan_fault_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted) -{ - int i; - *adjusted = 0; - - /* Bring fan speed to FAN_DUTY_MAX if any fan is not operational */ - for (i = 0; i < CHASSIS_FAN_COUNT; i++) { - if (!(fi[i].status & ONLP_FAN_STATUS_FAILED)) { - continue; - } - - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - - return ONLP_STATUS_OK; -} - -static int -sysi_fanctrl_fan_absent_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted) -{ - int i; - *adjusted = 0; - - /* Bring fan speed to FAN_DUTY_MAX if fan is not present */ - for (i = 0; i < CHASSIS_FAN_COUNT; i++) { - if (fi[i].status & ONLP_FAN_STATUS_PRESENT) { - continue; - } - - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - - return ONLP_STATUS_OK; -} - -static int -sysi_fanctrl_fan_unknown_speed_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted) -{ - int fanduty; - int fanduty_min = FAN_DUTY_MIN; - int fanduty_mid = FAN_DUTY_MID; - - *adjusted = 0; - fanduty_min += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0; - fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0; - - if (onlp_file_read_int(&fanduty, FAN_NODE(fan_duty_cycle_percentage)) < 0) { - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - - /* Bring fan speed to max if current speed is not expected - */ - if (fanduty != fanduty_min && fanduty != fanduty_mid && fanduty != FAN_DUTY_MAX) { - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - - return ONLP_STATUS_OK; -} - -static int -sysi_fanctrl_single_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted) -{ - int i; - *adjusted = 0; - - /* When anyone higher than 50 degrees, all fans run with duty 100%. - */ - for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) { - if (ti[i-1].mcelsius < 50000) { - continue; - } - - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - - /* When anyone higher than 45 degrees, all fans run with duty 62.5%. - */ - for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) { - if (ti[i-1].mcelsius < 45000) { - continue; - } - - int fanduty_mid = FAN_DUTY_MID; - fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0; - - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_mid); - } - - return ONLP_STATUS_OK; -} - -static int -sysi_fanctrl_overall_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted) -{ - int fanduty_min = FAN_DUTY_MIN; - int fanduty_mid = FAN_DUTY_MID; - int i, num_of_sensor = 0, temp_avg = 0; - - *adjusted = 0; - fanduty_min += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0; - fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0; - - for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) { - num_of_sensor++; - temp_avg += ti[i-1].mcelsius; - } - - temp_avg /= num_of_sensor; - - if (temp_avg >= 45000) { - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - } - else if (temp_avg >= 40000) { - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_mid); - } - else if (temp_avg < 35000) { - *adjusted = 1; - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_min); - } - - return ONLP_STATUS_OK; -} - -typedef int (*fan_control_policy)(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], - int *adjusted); - -fan_control_policy fan_control_policies[] = { -sysi_fanctrl_fan_fault_policy, -sysi_fanctrl_fan_absent_policy, -sysi_fanctrl_fan_unknown_speed_policy, -sysi_fanctrl_single_thermal_sensor_policy, -sysi_fanctrl_overall_thermal_sensor_policy, -}; - -int -onlp_sysi_platform_manage_fans(void) -{ - int i, rc; - onlp_fan_info_t fi[CHASSIS_FAN_COUNT]; - onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT]; - - memset(fi, 0, sizeof(fi)); - memset(ti, 0, sizeof(ti)); - - /* Get fan status - */ - for (i = 0; i < CHASSIS_FAN_COUNT; i++) { - rc = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i+1), &fi[i]); - - if (rc != ONLP_STATUS_OK) { - onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - return ONLP_STATUS_E_INTERNAL; - } - } - - /* Get thermal sensor status - */ - for (i = 0; i < CHASSIS_THERMAL_COUNT; i++) { - rc = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+1), &ti[i]); - - if (rc != ONLP_STATUS_OK) { - onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); - return ONLP_STATUS_E_INTERNAL; - } - } - - /* Apply thermal policy according the policy list, - * If fan duty is adjusted by one of the policies, skip the others - */ - for (i = 0; i < AIM_ARRAYSIZE(fan_control_policies); i++) { - int adjusted = 0; - - rc = fan_control_policies[i](fi, ti, &adjusted); - if (!adjusted) { - continue; - } - - return rc; - } - - return ONLP_STATUS_OK; -} - -int -onlp_sysi_platform_manage_leds(void) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/thermali.c index 742a4dd1..6c8e13d3 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/thermali.c @@ -34,16 +34,16 @@ } \ } while(0) -static char* devfiles__[] = /* must map with onlp_thermal_id */ +static char* ipmi_devfiles__[] = /* must map with onlp_thermal_id */ { NULL, NULL, /* CPU_CORE files */ - "/sys/bus/i2c/devices/10-0048*temp1_input", - "/sys/bus/i2c/devices/10-0049*temp1_input", - "/sys/bus/i2c/devices/10-004a*temp1_input", - "/sys/bus/i2c/devices/10-004b*temp1_input", - "/sys/bus/i2c/devices/18-005b*psu_temp1_input", - "/sys/bus/i2c/devices/17-0058*psu_temp1_input", + "/sys/devices/platform/as5916_54xks_thermal/temp1_input", + "/sys/devices/platform/as5916_54xks_thermal/temp2_input", + "/sys/devices/platform/as5916_54xks_thermal/temp3_input", + "/sys/devices/platform/as5916_54xks_thermal/temp4_input", + "/sys/devices/platform/as5916_54xks_psu/psu1_temp1_input", + "/sys/devices/platform/as5916_54xks_psu/psu2_temp1_input", }; static char* cpu_coretemp_files[] = @@ -60,23 +60,23 @@ static onlp_thermal_info_t linfo[] = { { }, /* Not used */ { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, ONLP_THERMAL_STATUS_PRESENT, - ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + ONLP_THERMAL_CAPS_ALL, 0, {82000, 104000, 104000} }, - { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-48", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1 U39", 0}, ONLP_THERMAL_STATUS_PRESENT, - ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + ONLP_THERMAL_CAPS_ALL, 0, {45000, 56000, 69000} }, - { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2-49", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2 U50", 0}, ONLP_THERMAL_STATUS_PRESENT, - ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + ONLP_THERMAL_CAPS_ALL, 0, {45000, 55000, 68000} }, - { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3-4A", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3 U35", 0}, ONLP_THERMAL_STATUS_PRESENT, - ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + ONLP_THERMAL_CAPS_ALL, 0, {45000, 51000, 64000} }, - { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-3-4B", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4 U20", 0}, ONLP_THERMAL_STATUS_PRESENT, - ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + ONLP_THERMAL_CAPS_ALL, 0, {45000, 52000, 65000} }, { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, ONLP_THERMAL_STATUS_PRESENT, @@ -123,6 +123,7 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) return rv; } - return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); + return onlp_file_read_int(&info->mcelsius, ipmi_devfiles__[tid]); + } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py index 5dd206e8..dc62cbb7 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py @@ -2,71 +2,14 @@ from onl.platform.base import * from onl.platform.accton import * class OnlPlatform_x86_64_accton_as5916_54xks_r0(OnlPlatformAccton, - OnlPlatformPortConfig_48x10_6x40): + OnlPlatformPortConfig_48x10_6x100): PLATFORM='x86-64-accton-as5916-54xks-r0' MODEL="AS5916-54XKS" SYS_OBJECT_ID=".5916.54" def baseconfig(self): - self.insmod('optoe') - self.insmod("ym2651y") - for m in [ "cpld", "psu", "fan", "leds" ]: - self.insmod("x86-64-accton-as5916-54xks-%s" % m) - - ########### initialize I2C bus 0 ########### - self.new_i2c_devices( - [ - # initialize multiplexer (PCA9548) - ('pca9548', 0x77, 0), - ('pca9548', 0x76, 1), - - # initiate chassis fan - ('as5916_54xks_fan', 0x66, 9), - - # inititate LM75 - ('lm75', 0x48, 10), - ('lm75', 0x49, 10), - ('lm75', 0x4a, 10), - ('lm75', 0x4b, 10), - - # initialize CPLDs - ('as5916_54xks_cpld1', 0x60, 11), - ('as5916_54xks_cpld2', 0x62, 12), - - # initialize multiplexer (PCA9548) - ('pca9548', 0x74, 2), - - # initiate PSU-1 AC Power - ('as5916_54xks_psu1', 0x53, 18), - ('ym2651', 0x5b, 18), - - # initiate PSU-2 AC Power - ('as5916_54xks_psu2', 0x50, 17), - ('ym2651', 0x58, 17), - - # initialize multiplexer (PCA9548) - ('pca9548', 0x72, 2), - ('pca9548', 0x75, 25), - ('pca9548', 0x75, 26), - ('pca9548', 0x75, 27), - ('pca9548', 0x75, 28), - ('pca9548', 0x75, 29), - ('pca9548', 0x75, 30), - ('pca9548', 0x75, 31), - - ] - ) - - # initialize SFP devices - for port in range(1, 49): - self.new_i2c_device('optoe2', 0x50, port+32) - - # initialize QSFP devices - for port in range(49, 55): - self.new_i2c_device('optoe1', 0x50, port+32) - - for port in range(1, 55): - subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+32), shell=True) + for m in [ 'fan', 'psu', 'leds', 'sfp', 'sys', 'thermal' ]: + self.insmod("x86-64-accton-as5916-54xks-%s.ko" % m) return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/.gitignore new file mode 100755 index 00000000..3b99c8dd --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/.gitignore @@ -0,0 +1,2 @@ +*x86*64*accton*as5916*54xl*.mk +onlpdump.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/PKG.yml new file mode 100755 index 00000000..87cf8642 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as5916-54xl ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/.gitignore new file mode 100755 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/Makefile new file mode 100755 index 00000000..909d8a24 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-as5916-54xl +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-fan.c new file mode 100755 index 00000000..b8051156 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-fan.c @@ -0,0 +1,460 @@ +/* + * Copyright (C) Brandon Chuang + * + * + * 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 +#include + +#define DRVNAME "as5916_54xl_fan" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_FAN_READ_CMD 0x14 +#define IPMI_FAN_WRITE_CMD 0x15 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xl_fan_probe(struct platform_device *pdev); +static int as5916_54xl_fan_remove(struct platform_device *pdev); + +enum fan_id { + FAN_1, + FAN_2, + FAN_3, + FAN_4, + FAN_5, + FAN_6, + NUM_OF_FAN +}; + +enum fan_data_index { + FAN_PRESENT, + FAN_PWM, + FAN_SPEED0, + FAN_SPEED1, + FAN_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xl_fan_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[24]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[3]; /* 0: FAN id, 1: 0x02, 2: PWM */ +}; + +struct as5916_54xl_fan_data *data = NULL; + +static struct platform_driver as5916_54xl_fan_driver = { + .probe = as5916_54xl_fan_probe, + .remove = as5916_54xl_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define FAN_PRESENT_ATTR_ID(index) FAN##index##_PRESENT +#define FAN_PWM_ATTR_ID(index) FAN##index##_PWM +#define FAN_RPM_ATTR_ID(index) FAN##index##_INPUT + +#define FAN_ATTR(fan_id) \ + FAN_PRESENT_ATTR_ID(fan_id), \ + FAN_PWM_ATTR_ID(fan_id), \ + FAN_RPM_ATTR_ID(fan_id) + +enum as5916_54x_fan_sysfs_attrs { + FAN_ATTR(1), + FAN_ATTR(2), + FAN_ATTR(3), + FAN_ATTR(4), + FAN_ATTR(5), + FAN_ATTR(6), + NUM_OF_FAN_ATTR, + NUM_OF_PER_FAN_ATTR = (NUM_OF_FAN_ATTR/NUM_OF_FAN) +}; + +/* fan attributes */ +#define DECLARE_FAN_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, show_fan, NULL, FAN##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, show_fan, set_fan, FAN##index##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, show_fan, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr + +DECLARE_FAN_SENSOR_DEVICE_ATTR(1); +DECLARE_FAN_SENSOR_DEVICE_ATTR(2); +DECLARE_FAN_SENSOR_DEVICE_ATTR(3); +DECLARE_FAN_SENSOR_DEVICE_ATTR(4); +DECLARE_FAN_SENSOR_DEVICE_ATTR(5); +DECLARE_FAN_SENSOR_DEVICE_ATTR(6); + +static struct attribute *as5916_54xl_fan_attributes[] = { + /* fan attributes */ + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_ATTR(4), + DECLARE_FAN_ATTR(5), + DECLARE_FAN_ATTR(6), + NULL +}; + +static const struct attribute_group as5916_54xl_fan_group = { + .attrs = as5916_54xl_fan_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xl_fan_data *as5916_54xl_fan_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + struct as5916_54xl_fan_data *data = NULL; + int value = 0; + int index = 0; + int present = 0; + + data = as5916_54xl_fan_update_device(); + if (!data->valid) { + return -EIO; + } + + index = fid * FAN_DATA_COUNT; /* base index */ + present = !data->ipmi_resp[index + FAN_PRESENT]; + + switch (attr->index) { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + value = !data->ipmi_resp[index + FAN_PRESENT]; + break; + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + value = (data->ipmi_resp[index + FAN_PWM] + 1) * 625 / 100; + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", present ? value : 0); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long pwm; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + + status = kstrtol(buf, 10, &pwm); + if (status) { + return status; + } + + pwm = (pwm * 100) / 625 - 1; /* Convert pwm to register value */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = 1; /* All FANs share the same PWM register, ALWAYS set 1 for each fan */ + data->ipmi_tx_data[1] = 0x02; + data->ipmi_tx_data[2] = pwm; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm; + + return count; +} + +static int as5916_54xl_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_fan_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xl_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_fan_group); + + return 0; +} + +static int __init as5916_54xl_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xl_fan_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_fan_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_fan_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5916_54xl fan driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_fan_init); +module_exit(as5916_54xl_fan_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-leds.c new file mode 100755 index 00000000..a6cd3c20 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-leds.c @@ -0,0 +1,455 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xl_led" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_LED_READ_CMD 0x1A +#define IPMI_LED_WRITE_CMD 0x1B +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_led(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xl_led_probe(struct platform_device *pdev); +static int as5916_54xl_led_remove(struct platform_device *pdev); + +enum led_data_index { + LOC_INDEX, + DIAG_RED_INDEX, + DIAG_GREEN_INDEX +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xl_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[3]; /* 0: LOC LED, 1: DIAG Red LED, 2: DIAG Green LED */ + struct ipmi_data ipmi; +}; + +struct as5916_54xl_led_data *data = NULL; + +static struct platform_driver as5916_54xl_led_driver = { + .probe = as5916_54xl_led_probe, + .remove = as5916_54xl_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +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 +}; + +enum as5916_54x_led_sysfs_attrs { + LED_LOC, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN +}; + +static SENSOR_DEVICE_ATTR(led_loc, S_IWUSR | S_IRUGO, show_led, set_led, LED_LOC); +static SENSOR_DEVICE_ATTR(led_diag, S_IWUSR | S_IRUGO, show_led, set_led, LED_DIAG); +static SENSOR_DEVICE_ATTR(led_psu1, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU2); +static SENSOR_DEVICE_ATTR(led_fan, S_IWUSR | S_IRUGO, show_led, set_led, LED_FAN); + +static struct attribute *as5916_54xl_led_attributes[] = { + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_diag.dev_attr.attr, + &sensor_dev_attr_led_psu1.dev_attr.attr, + &sensor_dev_attr_led_psu2.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5916_54xl_led_group = { + .attrs = as5916_54xl_led_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xl_led_data *as5916_54xl_led_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_LED_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_led(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_led_data *data = NULL; + int value = 0; + + data = as5916_54xl_led_update_device(); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case LED_LOC: + value = data->ipmi_resp[LOC_INDEX] ? LED_MODE_ORANGE_BLINKING : LED_MODE_OFF; + break; + case LED_DIAG: + { + if (!data->ipmi_resp[DIAG_GREEN_INDEX] && !data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (data->ipmi_resp[DIAG_GREEN_INDEX] && data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_ORANGE; + else if (data->ipmi_resp[DIAG_GREEN_INDEX]) + value = LED_MODE_GREEN; + break; + } + case LED_PSU1: + case LED_PSU2: + case LED_FAN: + value = LED_MODE_AUTO; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_led_data *data = NULL; + + status = kstrtol(buf, 10, &mode); + if (status) { + return status; + } + + data = as5916_54xl_led_update_device(); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case LED_LOC: + data->ipmi_resp[LOC_INDEX] = !!mode; + break; + case LED_DIAG: + { + if (mode == LED_MODE_GREEN) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 1; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + else if (mode == LED_MODE_ORANGE) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 1; + } + else { /* OFF */ + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + + break; + } + default: + return -EINVAL; + } + + /* Send IPMI write command */ + status = ipmi_send_message(&data->ipmi, IPMI_LED_WRITE_CMD, + data->ipmi_resp, sizeof(data->ipmi_resp), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + return count; +} + +static int as5916_54xl_led_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_led_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xl_led_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_led_group); + + return 0; +} + +static int __init as5916_54xl_led_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_led_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xl_led_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_led_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_led_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_led_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XL led driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_led_init); +module_exit(as5916_54xl_led_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-psu.c new file mode 100755 index 00000000..2f728e7d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-psu.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) Brandon Chuang + * 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 +#include + +#define DRVNAME "as5916_54xl_psu" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_PSU_READ_CMD 0x16 +#define IPMI_PSU_MODEL_NAME_CMD 0x10 +#define IPMI_PSU_SERIAL_NUM_CMD 0x11 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_psu(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xl_psu_probe(struct platform_device *pdev); +static int as5916_54xl_psu_remove(struct platform_device *pdev); + +enum psu_id { + PSU_1, + PSU_2, + NUM_OF_PSU +}; + +enum psu_data_index { + PSU_PRESENT = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD_CPLD, + PSU_POWER_GOOD_PMBUS, + PSU_OVER_VOLTAGE, + PSU_OVER_CURRENT, + PSU_POWER_ON, + PSU_VIN0, + PSU_VIN1, + PSU_VOUT0, + PSU_VOUT1, + PSU_IOUT0, + PSU_IOUT1, + PSU_TEMP0, + PSU_TEMP1, + PSU_FAN0, + PSU_FAN1, + PSU_POUT0, + PSU_POUT1, + PSU_STATUS_COUNT, + PSU_MODEL = 0, + PSU_SERIAL = 0 +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct ipmi_psu_resp_data { + unsigned char status[19]; + char serial[19]; + char model[9]; +}; + +struct as5916_54xl_psu_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid[2]; /* != 0 if registers are valid, 0: PSU1, 1: PSU2 */ + unsigned long last_updated[2]; /* In jiffies, 0: PSU1, 1: PSU2 */ + struct ipmi_data ipmi; + struct ipmi_psu_resp_data ipmi_resp[2]; /* 0: PSU1, 1: PSU2 */ + unsigned char ipmi_tx_data[2]; +}; + +struct as5916_54xl_psu_data *data = NULL; + +static struct platform_driver as5916_54xl_psu_driver = { + .probe = as5916_54xl_psu_probe, + .remove = as5916_54xl_psu_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define PSU_PRESENT_ATTR_ID(index) PSU##index##_PRESENT +#define PSU_POWERGOOD_ATTR_ID(index) PSU##index##_POWER_GOOD +#define PSU_VOUT_ATTR_ID(index) PSU##index##_VOUT +#define PSU_IOUT_ATTR_ID(index) PSU##index##_IOUT +#define PSU_POUT_ATTR_ID(index) PSU##index##_POUT +#define PSU_MODEL_ATTR_ID(index) PSU##index##_MODEL +#define PSU_SERIAL_ATTR_ID(index) PSU##index##_SERIAL +#define PSU_TEMP_INPUT_ATTR_ID(index) PSU##index##_TEMP_INPUT +#define PSU_FAN_INPUT_ATTR_ID(index) PSU##index##_FAN_INPUT + +#define PSU_ATTR(psu_id) \ + PSU_PRESENT_ATTR_ID(psu_id), \ + PSU_POWERGOOD_ATTR_ID(psu_id), \ + PSU_VOUT_ATTR_ID(psu_id), \ + PSU_IOUT_ATTR_ID(psu_id), \ + PSU_POUT_ATTR_ID(psu_id), \ + PSU_MODEL_ATTR_ID(psu_id), \ + PSU_SERIAL_ATTR_ID(psu_id), \ + PSU_TEMP_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_INPUT_ATTR_ID(psu_id) + +enum as5916_54x_psu_sysfs_attrs { + /* psu attributes */ + PSU_ATTR(1), + PSU_ATTR(2), + NUM_OF_PSU_ATTR, + NUM_OF_PER_PSU_ATTR = (NUM_OF_PSU_ATTR/NUM_OF_PSU) +}; + +/* psu attributes */ +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, PSU##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL, PSU##index##_POWER_GOOD); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_psu, NULL, PSU##index##_VOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_psu, NULL, PSU##index##_IOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_psu, NULL, PSU##index##_POUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, PSU##index##_MODEL); \ + static SENSOR_DEVICE_ATTR(psu##index##_serial, S_IRUGO, show_string, NULL, PSU##index##_SERIAL);\ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input, S_IRUGO, show_psu, NULL, PSU##index##_TEMP_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan1_input, S_IRUGO, show_psu, NULL, PSU##index##_FAN_INPUT) +#define DECLARE_PSU_ATTR(index) \ + &sensor_dev_attr_psu##index##_present.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_power_good.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_model.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_serial.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_temp1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan1_input.dev_attr.attr + +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); + +static struct attribute *as5916_54xl_psu_attributes[] = { + /* psu attributes */ + DECLARE_PSU_ATTR(1), + DECLARE_PSU_ATTR(2), + NULL +}; + +static const struct attribute_group as5916_54xl_psu_group = { + .attrs = as5916_54xl_psu_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xl_psu_data *as5916_54xl_psu_update_device(struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int status = 0; + + if (time_before(jiffies, data->last_updated[pid] + HZ * 5) && data->valid[pid]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid[pid] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */ + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 1, + data->ipmi_resp[pid].status, sizeof(data->ipmi_resp[pid].status)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get model name from ipmi */ + data->ipmi_tx_data[1] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].model, sizeof(data->ipmi_resp[pid].model) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get serial number from ipmi */ + data->ipmi_tx_data[1] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].serial, sizeof(data->ipmi_resp[pid].serial) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated[pid] = jiffies; + data->valid[pid] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +#define VALIDATE_PRESENT_RETURN(id) \ +{ \ + if (data->ipmi_resp[id].status[PSU_PRESENT] != 0) { \ + return -ENXIO; \ + } \ +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + struct as5916_54xl_psu_data *data = NULL; + int value = 0; + + data = as5916_54xl_psu_update_device(da); + if (!data->valid[pid]) { + return -EIO; + } + + switch (attr->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + value = !(data->ipmi_resp[pid].status[PSU_PRESENT]); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + VALIDATE_PRESENT_RETURN(pid); + value = data->ipmi_resp[pid].status[PSU_POWER_GOOD_CPLD]; + break; + case PSU1_VOUT: + case PSU2_VOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_VOUT0] | + (int)data->ipmi_resp[pid].status[PSU_VOUT1] << 8) * 1000; + break; + case PSU1_IOUT: + case PSU2_IOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_IOUT0] | + (int)data->ipmi_resp[pid].status[PSU_IOUT1] << 8) * 1000; + break; + case PSU1_POUT: + case PSU2_POUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_POUT0] | + (int)data->ipmi_resp[pid].status[PSU_POUT1] << 8) * 1000; + break; + case PSU1_TEMP_INPUT: + case PSU2_TEMP_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_TEMP0] | + (int)data->ipmi_resp[pid].status[PSU_TEMP1] << 8) * 1000; + break; + case PSU1_FAN_INPUT: + case PSU2_FAN_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_FAN0] | + (int)data->ipmi_resp[pid].status[PSU_FAN1] << 8); + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + struct as5916_54xl_psu_data *data; + char *str = NULL; + + data = as5916_54xl_psu_update_device(da); + if (!data->valid[pid]) { + return -EIO; + } + + switch (attr->index) { + case PSU1_MODEL: + case PSU2_MODEL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].model; + break; + case PSU1_SERIAL: + case PSU2_SERIAL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].serial; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", str); +} + +static int as5916_54xl_psu_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_psu_group); + if (status) { + goto exit; + } + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xl_psu_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_psu_group); + return 0; +} + +static int __init as5916_54xl_psu_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_psu_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xl_psu_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_psu_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_psu_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_psu_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XL PSU driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_psu_init); +module_exit(as5916_54xl_psu_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sfp.c new file mode 100755 index 00000000..557f162c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sfp.c @@ -0,0 +1,1640 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xl_sfp" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_QSFP_READ_CMD 0x10 +#define IPMI_QSFP_WRITE_CMD 0x11 +#define IPMI_SFP_READ_CMD 0x1C +#define IPMI_SFP_WRITE_CMD 0x1D +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_DATA_MAX_LEN 128 + +#define SFP_EEPROM_SIZE 768 +#define QSFP_EEPROM_SIZE 640 + +#define NUM_OF_SFP 48 +#define NUM_OF_QSFP 6 +#define NUM_OF_PORT (NUM_OF_SFP + NUM_OF_QSFP) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_sfp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf); +static int as5916_54xl_sfp_probe(struct platform_device *pdev); +static int as5916_54xl_sfp_remove(struct platform_device *pdev); +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf); +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_present(void); +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_txdisable(void); +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_txfault(void); +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_rxlos(void); +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_present(void); +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_txdisable(void); +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_reset(void); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +enum module_status { + SFP_PRESENT = 0, + SFP_TXDISABLE, + SFP_TXFAULT, + SFP_RXLOS, + NUM_OF_SFP_STATUS, + + QSFP_PRESENT = 0, + QSFP_TXDISABLE, + QSFP_RESET, + QSFP_LPMODE, + NUM_OF_QSFP_STATUS, + + PRESENT_ALL = 0, + RXLOS_ALL +}; + +struct ipmi_sfp_resp_data { + unsigned char eeprom[IPMI_DATA_MAX_LEN]; + char eeprom_valid; + + char sfp_valid[NUM_OF_SFP_STATUS]; /* != 0 if registers are valid */ + unsigned long sfp_last_updated[NUM_OF_SFP_STATUS]; /* In jiffies */ + unsigned char sfp_resp[NUM_OF_SFP_STATUS][NUM_OF_SFP]; /* 0: present, 1: tx-disable + 2: tx-fault, 3: rx-los */ + char qsfp_valid[NUM_OF_QSFP_STATUS]; /* != 0 if registers are valid */ + unsigned long qsfp_last_updated[NUM_OF_QSFP_STATUS]; /* In jiffies */ + unsigned char qsfp_resp[NUM_OF_QSFP_STATUS][NUM_OF_QSFP]; /* 0: present, 1: tx-disable, + 2: reset , 3: low power mode */ +}; + +struct as5916_54xl_sfp_data { + struct platform_device *pdev; + struct mutex update_lock; + struct ipmi_data ipmi; + struct ipmi_sfp_resp_data ipmi_resp; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom[NUM_OF_PORT]; /* eeprom data */ +}; + +struct sfp_eeprom_write_data { + unsigned char ipmi_tx_data[4]; /* 0:port index 1:page number 2:offset 3:Data len */ + unsigned char write_buf[IPMI_DATA_MAX_LEN]; +}; + +struct as5916_54xl_sfp_data *data = NULL; + +static struct platform_driver as5916_54xl_sfp_driver = { + .probe = as5916_54xl_sfp_probe, + .remove = as5916_54xl_sfp_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define SFP_PRESENT_ATTR_ID(port) SFP##port##_PRESENT +#define SFP_TXDISABLE_ATTR_ID(port) SFP##port##_TXDISABLE +#define SFP_TXFAULT_ATTR_ID(port) SFP##port##_TXFAULT +#define SFP_RXLOS_ATTR_ID(port) SFP##port##_RXLOS + +#define SFP_ATTR(port) \ + SFP_PRESENT_ATTR_ID(port), \ + SFP_TXDISABLE_ATTR_ID(port), \ + SFP_TXFAULT_ATTR_ID(port), \ + SFP_RXLOS_ATTR_ID(port) + +#define QSFP_PRESENT_ATTR_ID(port) QSFP##port##_PRESENT +#define QSFP_TXDISABLE_ATTR_ID(port) QSFP##port##_TXDISABLE +#define QSFP_RESET_ATTR_ID(port) QSFP##port##_RESET +#define QSFP_LPMODE_ATTR_ID(port) QSFP##port##_LPMODE + +#define QSFP_ATTR(port) \ + QSFP_PRESENT_ATTR_ID(port), \ + QSFP_TXDISABLE_ATTR_ID(port), \ + QSFP_RESET_ATTR_ID(port), \ + QSFP_LPMODE_ATTR_ID(port) + +enum as5916_54x_sfp_sysfs_attrs { + SFP_ATTR(1), + SFP_ATTR(2), + SFP_ATTR(3), + SFP_ATTR(4), + SFP_ATTR(5), + SFP_ATTR(6), + SFP_ATTR(7), + SFP_ATTR(8), + SFP_ATTR(9), + SFP_ATTR(10), + SFP_ATTR(11), + SFP_ATTR(12), + SFP_ATTR(13), + SFP_ATTR(14), + SFP_ATTR(15), + SFP_ATTR(16), + SFP_ATTR(17), + SFP_ATTR(18), + SFP_ATTR(19), + SFP_ATTR(20), + SFP_ATTR(21), + SFP_ATTR(22), + SFP_ATTR(23), + SFP_ATTR(24), + SFP_ATTR(25), + SFP_ATTR(26), + SFP_ATTR(27), + SFP_ATTR(28), + SFP_ATTR(29), + SFP_ATTR(30), + SFP_ATTR(31), + SFP_ATTR(32), + SFP_ATTR(33), + SFP_ATTR(34), + SFP_ATTR(35), + SFP_ATTR(36), + SFP_ATTR(37), + SFP_ATTR(38), + SFP_ATTR(39), + SFP_ATTR(40), + SFP_ATTR(41), + SFP_ATTR(42), + SFP_ATTR(43), + SFP_ATTR(44), + SFP_ATTR(45), + SFP_ATTR(46), + SFP_ATTR(47), + SFP_ATTR(48), + NUM_OF_SFP_ATTR, + NUM_OF_PER_SFP_ATTR = (NUM_OF_SFP_ATTR/NUM_OF_SFP), +}; + +enum as5916_54xl_qsfp_sysfs_attrs { + QSFP_ATTR(49), + QSFP_ATTR(50), + QSFP_ATTR(51), + QSFP_ATTR(52), + QSFP_ATTR(53), + QSFP_ATTR(54), + NUM_OF_QSFP_ATTR, + NUM_OF_PER_QSFP_ATTR = (NUM_OF_QSFP_ATTR/NUM_OF_QSFP), +}; + +/* sfp attributes */ +#define DECLARE_SFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_sfp, NULL, SFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_sfp, set_sfp, SFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##port, S_IRUGO, show_sfp, NULL, SFP##port##_TXFAULT); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##port, S_IRUGO, show_sfp, NULL, SFP##port##_RXLOS) +#define DECLARE_SFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##port.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##port.dev_attr.attr + +/* qsfp attributes */ +#define DECLARE_QSFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_qsfp, NULL, QSFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_txdisable, QSFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_reset_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_reset, QSFP##port##_RESET); \ + static SENSOR_DEVICE_ATTR(module_lpmode_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_lpmode, QSFP##port##_LPMODE) +#define DECLARE_QSFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##port.dev_attr.attr, \ + &sensor_dev_attr_module_lpmode_##port.dev_attr.attr + +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_all, NULL, PRESENT_ALL); \ +static SENSOR_DEVICE_ATTR(module_rxlos_all, S_IRUGO, show_all, NULL, RXLOS_ALL); \ + +DECLARE_SFP_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_SENSOR_DEVICE_ATTR(48); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5916_54xl_sfp_attributes[] = { + /* sfp attributes */ + DECLARE_SFP_ATTR(1), + DECLARE_SFP_ATTR(2), + DECLARE_SFP_ATTR(3), + DECLARE_SFP_ATTR(4), + DECLARE_SFP_ATTR(5), + DECLARE_SFP_ATTR(6), + DECLARE_SFP_ATTR(7), + DECLARE_SFP_ATTR(8), + DECLARE_SFP_ATTR(9), + DECLARE_SFP_ATTR(10), + DECLARE_SFP_ATTR(11), + DECLARE_SFP_ATTR(12), + DECLARE_SFP_ATTR(13), + DECLARE_SFP_ATTR(14), + DECLARE_SFP_ATTR(15), + DECLARE_SFP_ATTR(16), + DECLARE_SFP_ATTR(17), + DECLARE_SFP_ATTR(18), + DECLARE_SFP_ATTR(19), + DECLARE_SFP_ATTR(20), + DECLARE_SFP_ATTR(21), + DECLARE_SFP_ATTR(22), + DECLARE_SFP_ATTR(23), + DECLARE_SFP_ATTR(24), + DECLARE_SFP_ATTR(25), + DECLARE_SFP_ATTR(26), + DECLARE_SFP_ATTR(27), + DECLARE_SFP_ATTR(28), + DECLARE_SFP_ATTR(29), + DECLARE_SFP_ATTR(30), + DECLARE_SFP_ATTR(31), + DECLARE_SFP_ATTR(32), + DECLARE_SFP_ATTR(33), + DECLARE_SFP_ATTR(34), + DECLARE_SFP_ATTR(35), + DECLARE_SFP_ATTR(36), + DECLARE_SFP_ATTR(37), + DECLARE_SFP_ATTR(38), + DECLARE_SFP_ATTR(39), + DECLARE_SFP_ATTR(40), + DECLARE_SFP_ATTR(41), + DECLARE_SFP_ATTR(42), + DECLARE_SFP_ATTR(43), + DECLARE_SFP_ATTR(44), + DECLARE_SFP_ATTR(45), + DECLARE_SFP_ATTR(46), + DECLARE_SFP_ATTR(47), + DECLARE_SFP_ATTR(48), + DECLARE_QSFP_ATTR(49), + DECLARE_QSFP_ATTR(50), + DECLARE_QSFP_ATTR(51), + DECLARE_QSFP_ATTR(52), + DECLARE_QSFP_ATTR(53), + DECLARE_QSFP_ATTR(54), + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rxlos_all.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5916_54xl_sfp_group = { + .attrs = as5916_54xl_sfp_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_PRESENT] + HZ) && + data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_PRESENT], + sizeof(data->ipmi_resp.sfp_resp[SFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_PRESENT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXDISABLE], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_txfault(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXFAULT], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXFAULT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_sfp_update_rxlos(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_RXLOS] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x13; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_RXLOS], + sizeof(data->ipmi_resp.sfp_resp[SFP_RXLOS])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_RXLOS] = jiffies; + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] + HZ) && + data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_PRESENT], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_reset(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_RESET] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_RESET], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_RESET])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_RESET] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as5916_54xl_sfp_data *as5916_54xl_qsfp_update_lpmode(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_LPMODE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_LPMODE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_sfp_data *data = NULL; + u64 values = 0; + int i; + + switch (attr->index) { + case PRESENT_ALL: + { + data = as5916_54xl_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return -EIO; + } + + data = as5916_54xl_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + /* Update qsfp present status */ + for (i = (NUM_OF_QSFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.qsfp_resp[QSFP_PRESENT][i] & 0x1); + } + + /* Update sfp present status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.sfp_resp[SFP_PRESENT][i] & 0x1); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40)), + (unsigned int)(0x3F & (values >> 48))); + } + case RXLOS_ALL: + { + data = as5916_54xl_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return -EIO; + } + + /* Update sfp rxlos status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= !(data->ipmi_resp.sfp_resp[SFP_RXLOS][i] & 0x1); + } + + /* Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40))); + } + default: + break; + } + + return 0; +} + +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + struct as5916_54xl_sfp_data *data = NULL; + int value = 0; + + switch (attr->index) { + case SFP1_PRESENT: + case SFP2_PRESENT: + case SFP3_PRESENT: + case SFP4_PRESENT: + case SFP5_PRESENT: + case SFP6_PRESENT: + case SFP7_PRESENT: + case SFP8_PRESENT: + case SFP9_PRESENT: + case SFP10_PRESENT: + case SFP11_PRESENT: + case SFP12_PRESENT: + case SFP13_PRESENT: + case SFP14_PRESENT: + case SFP15_PRESENT: + case SFP16_PRESENT: + case SFP17_PRESENT: + case SFP18_PRESENT: + case SFP19_PRESENT: + case SFP20_PRESENT: + case SFP21_PRESENT: + case SFP22_PRESENT: + case SFP23_PRESENT: + case SFP24_PRESENT: + case SFP25_PRESENT: + case SFP26_PRESENT: + case SFP27_PRESENT: + case SFP28_PRESENT: + case SFP29_PRESENT: + case SFP30_PRESENT: + case SFP31_PRESENT: + case SFP32_PRESENT: + case SFP33_PRESENT: + case SFP34_PRESENT: + case SFP35_PRESENT: + case SFP36_PRESENT: + case SFP37_PRESENT: + case SFP38_PRESENT: + case SFP39_PRESENT: + case SFP40_PRESENT: + case SFP41_PRESENT: + case SFP42_PRESENT: + case SFP43_PRESENT: + case SFP44_PRESENT: + case SFP45_PRESENT: + case SFP46_PRESENT: + case SFP47_PRESENT: + case SFP48_PRESENT: + { + data = as5916_54xl_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return -EIO; + } + + value = data->ipmi_resp.sfp_resp[SFP_PRESENT][pid]; + break; + } + case SFP1_TXDISABLE: + case SFP2_TXDISABLE: + case SFP3_TXDISABLE: + case SFP4_TXDISABLE: + case SFP5_TXDISABLE: + case SFP6_TXDISABLE: + case SFP7_TXDISABLE: + case SFP8_TXDISABLE: + case SFP9_TXDISABLE: + case SFP10_TXDISABLE: + case SFP11_TXDISABLE: + case SFP12_TXDISABLE: + case SFP13_TXDISABLE: + case SFP14_TXDISABLE: + case SFP15_TXDISABLE: + case SFP16_TXDISABLE: + case SFP17_TXDISABLE: + case SFP18_TXDISABLE: + case SFP19_TXDISABLE: + case SFP20_TXDISABLE: + case SFP21_TXDISABLE: + case SFP22_TXDISABLE: + case SFP23_TXDISABLE: + case SFP24_TXDISABLE: + case SFP25_TXDISABLE: + case SFP26_TXDISABLE: + case SFP27_TXDISABLE: + case SFP28_TXDISABLE: + case SFP29_TXDISABLE: + case SFP30_TXDISABLE: + case SFP31_TXDISABLE: + case SFP32_TXDISABLE: + case SFP33_TXDISABLE: + case SFP34_TXDISABLE: + case SFP35_TXDISABLE: + case SFP36_TXDISABLE: + case SFP37_TXDISABLE: + case SFP38_TXDISABLE: + case SFP39_TXDISABLE: + case SFP40_TXDISABLE: + case SFP41_TXDISABLE: + case SFP42_TXDISABLE: + case SFP43_TXDISABLE: + case SFP44_TXDISABLE: + case SFP45_TXDISABLE: + case SFP46_TXDISABLE: + case SFP47_TXDISABLE: + case SFP48_TXDISABLE: + { + data = as5916_54xl_sfp_update_txdisable(); + if (!data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return -EIO; + } + + value = !data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid]; + break; + } + case SFP1_TXFAULT: + case SFP2_TXFAULT: + case SFP3_TXFAULT: + case SFP4_TXFAULT: + case SFP5_TXFAULT: + case SFP6_TXFAULT: + case SFP7_TXFAULT: + case SFP8_TXFAULT: + case SFP9_TXFAULT: + case SFP10_TXFAULT: + case SFP11_TXFAULT: + case SFP12_TXFAULT: + case SFP13_TXFAULT: + case SFP14_TXFAULT: + case SFP15_TXFAULT: + case SFP16_TXFAULT: + case SFP17_TXFAULT: + case SFP18_TXFAULT: + case SFP19_TXFAULT: + case SFP20_TXFAULT: + case SFP21_TXFAULT: + case SFP22_TXFAULT: + case SFP23_TXFAULT: + case SFP24_TXFAULT: + case SFP25_TXFAULT: + case SFP26_TXFAULT: + case SFP27_TXFAULT: + case SFP28_TXFAULT: + case SFP29_TXFAULT: + case SFP30_TXFAULT: + case SFP31_TXFAULT: + case SFP32_TXFAULT: + case SFP33_TXFAULT: + case SFP34_TXFAULT: + case SFP35_TXFAULT: + case SFP36_TXFAULT: + case SFP37_TXFAULT: + case SFP38_TXFAULT: + case SFP39_TXFAULT: + case SFP40_TXFAULT: + case SFP41_TXFAULT: + case SFP42_TXFAULT: + case SFP43_TXFAULT: + case SFP44_TXFAULT: + case SFP45_TXFAULT: + case SFP46_TXFAULT: + case SFP47_TXFAULT: + case SFP48_TXFAULT: + { + data = as5916_54xl_sfp_update_txfault(); + if (!data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return -EIO; + } + + value = data->ipmi_resp.sfp_resp[SFP_TXFAULT][pid]; + break; + } + case SFP1_RXLOS: + case SFP2_RXLOS: + case SFP3_RXLOS: + case SFP4_RXLOS: + case SFP5_RXLOS: + case SFP6_RXLOS: + case SFP7_RXLOS: + case SFP8_RXLOS: + case SFP9_RXLOS: + case SFP10_RXLOS: + case SFP11_RXLOS: + case SFP12_RXLOS: + case SFP13_RXLOS: + case SFP14_RXLOS: + case SFP15_RXLOS: + case SFP16_RXLOS: + case SFP17_RXLOS: + case SFP18_RXLOS: + case SFP19_RXLOS: + case SFP20_RXLOS: + case SFP21_RXLOS: + case SFP22_RXLOS: + case SFP23_RXLOS: + case SFP24_RXLOS: + case SFP25_RXLOS: + case SFP26_RXLOS: + case SFP27_RXLOS: + case SFP28_RXLOS: + case SFP29_RXLOS: + case SFP30_RXLOS: + case SFP31_RXLOS: + case SFP32_RXLOS: + case SFP33_RXLOS: + case SFP34_RXLOS: + case SFP35_RXLOS: + case SFP36_RXLOS: + case SFP37_RXLOS: + case SFP38_RXLOS: + case SFP39_RXLOS: + case SFP40_RXLOS: + case SFP41_RXLOS: + case SFP42_RXLOS: + case SFP43_RXLOS: + case SFP44_RXLOS: + case SFP45_RXLOS: + case SFP46_RXLOS: + case SFP47_RXLOS: + case SFP48_RXLOS: + { + data = as5916_54xl_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return -EIO; + } + + value = !data->ipmi_resp.sfp_resp[SFP_RXLOS][pid]; + break; + } + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_sfp(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); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + disable = !disable; /* the IPMI cmd is 0 for tx-disable and 1 for tx-enable */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid] = disable; + + return count; +} + +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + struct as5916_54xl_sfp_data *data = NULL; + int value = 0; + + switch (attr->index) { + case QSFP49_PRESENT: + case QSFP50_PRESENT: + case QSFP51_PRESENT: + case QSFP52_PRESENT: + case QSFP53_PRESENT: + case QSFP54_PRESENT: + { + data = as5916_54xl_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]; + break; + } + case QSFP49_TXDISABLE: + case QSFP50_TXDISABLE: + case QSFP51_TXDISABLE: + case QSFP52_TXDISABLE: + case QSFP53_TXDISABLE: + case QSFP54_TXDISABLE: + { + data = as5916_54xl_qsfp_update_txdisable(); + if (!data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return -EIO; + } + + value = !!data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid]; + break; + } + case QSFP49_RESET: + case QSFP50_RESET: + case QSFP51_RESET: + case QSFP52_RESET: + case QSFP53_RESET: + case QSFP54_RESET: + { + data = as5916_54xl_qsfp_update_reset(); + if (!data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return -EIO; + } + + value = !data->ipmi_resp.qsfp_resp[QSFP_RESET][pid]; + break; + } + case QSFP49_LPMODE: + case QSFP50_LPMODE: + case QSFP51_LPMODE: + case QSFP52_LPMODE: + case QSFP53_LPMODE: + case QSFP54_LPMODE: + { + data = as5916_54xl_qsfp_update_lpmode(); + if (!data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + return -EIO; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid]; + break; + } + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_qsfp_txdisable(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); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + struct as5916_54xl_sfp_data *data = NULL; + + data = as5916_54xl_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + if (!data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]) { + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable ? 0xf : 0; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid] = disable; + + return count; +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + reset = !reset; /* the IPMI cmd is 0 for reset and 1 for out of reset */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x11; + data->ipmi_tx_data[2] = reset; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_RESET][pid] = reset; + + return count; +} + +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long lpmode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &lpmode); + if (status) { + return status; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x12; + data->ipmi_tx_data[2] = lpmode; /* 0: High Power Mode, 1: Low Power Mode */ + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid] = lpmode; + + return count; +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~48 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1C 1" +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 2" +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1C 3" +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1C 4" +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1C 5" + +QSFP: PS: index of QSFP is 1~6" +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x10 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x10 1" +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x10 2" +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x10 3" +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x10 4" +**************************************************************************************/ +static ssize_t sfp_eeprom_read(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_READ_CMD : IPMI_QSFP_READ_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + + data->ipmi_resp.eeprom_valid = 0; + data->ipmi_tx_data[0] = ipmi_port_id; + data->ipmi_tx_data[1] = ipmi_page; + status = ipmi_send_message(&data->ipmi, cmd, data->ipmi_tx_data, 2, + data->ipmi_resp.eeprom, IPMI_DATA_MAX_LEN); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Calculate return length */ + if (count < length) { + length = count; + } + + memcpy(buf, data->ipmi_resp.eeprom + (off % IPMI_DATA_MAX_LEN), length); + data->ipmi_resp.eeprom_valid = 1; + return length; + +exit: + return status; +} + + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~48 +ipmitool raw 0x34 0x1d +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1d 1 offset " +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 2 offset " +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1d 3 offset " +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1d 4 offset " +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1d 5 offset " + +QSFP: PS: index of QSFP is 1~6" +ipmitool raw 0x34 0x11 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x11 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x11 1 offset " +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x11 2 offset " +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x11 3 offset " +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x11 4 offset " +**************************************************************************************/ +static ssize_t sfp_eeprom_write(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_WRITE_CMD : IPMI_QSFP_WRITE_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + struct sfp_eeprom_write_data wdata; + + /* Calculate write length */ + if (count < length) { + length = count; + } + + wdata.ipmi_tx_data[0] = ipmi_port_id; + wdata.ipmi_tx_data[1] = ipmi_page; + wdata.ipmi_tx_data[2] = (off % IPMI_DATA_MAX_LEN); + wdata.ipmi_tx_data[3] = length; + memcpy(&wdata.write_buf, buf, length); + status = ipmi_send_message(&data->ipmi, cmd, &wdata.ipmi_tx_data[0], + length + sizeof(wdata.ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + return length; + +exit: + return status; +} + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * 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(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + +#define EEPROM_FORMAT "module_eeprom_%d" + +static int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, u64 port) +{ + int ret = 0; + char *eeprom_name = NULL; + + eeprom_name = kzalloc(32, GFP_KERNEL); + if (!eeprom_name) { + ret = -ENOMEM; + goto alloc_err; + } + + sprintf(eeprom_name, EEPROM_FORMAT, (int)port); + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = eeprom_name; + eeprom->attr.mode = S_IRUGO | S_IWUSR; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = (port <= NUM_OF_SFP) ? SFP_EEPROM_SIZE : QSFP_EEPROM_SIZE; + eeprom->private = (void*)port; + + /* Create eeprom file */ + ret = sysfs_create_bin_file(kobj, eeprom); + if (unlikely(ret != 0)) { + goto bin_err; + } + + return ret; + +bin_err: + kfree(eeprom_name); +alloc_err: + return ret; +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static int as5916_54xl_sfp_probe(struct platform_device *pdev) +{ + int status = -1; + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom[i], + i+1/* port name start from 1*/); + if (status) { + goto exit; + } + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_sfp_group); + if (status) { + goto exit; + } + + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + /* Remove the eeprom attributes which were created successfully */ + for (--i; i >= 0; i--) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + return status; +} + +static int as5916_54xl_sfp_remove(struct platform_device *pdev) +{ + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_sfp_group); + return 0; +} + +static int __init as5916_54xl_sfp_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_sfp_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xl_sfp_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_sfp_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_sfp_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_sfp_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XL sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_sfp_init); +module_exit(as5916_54xl_sfp_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sys.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sys.c new file mode 100755 index 00000000..f629cc4c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-sys.c @@ -0,0 +1,686 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xl_sys" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_TCAM_READ_CMD 0x1E +#define IPMI_TCAM_WRITE_CMD 0x1F +#define IPMI_TCAM_RESET_SUBCMD 1 +#define IPMI_TCAM_INT_SUMCMD 2 +#define IPMI_TCAM_INT_MASK_SUBCMD 3 + +#define IPMI_SYSEEPROM_READ_CMD 0x18 +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_NAME "eeprom" +#define EEPROM_SIZE 512 /* 512 byte eeprom */ + +#define IPMI_GET_CPLD_VER_CMD 0x20 +#define MAINBOARD_CPLD1_ADDR 0x60 +#define MAINBOARD_CPLD2_ADDR 0x62 +#define CPU_CPLD_ADDR 0x65 +#define FAN_CPLD_ADDR 0x66 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static int as5916_54xl_sys_probe(struct platform_device *pdev); +static int as5916_54xl_sys_remove(struct platform_device *pdev); +static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xl_sys_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct ipmi_data ipmi; + unsigned char ipmi_resp_eeprom[EEPROM_SIZE]; + unsigned char ipmi_resp_tcam; /* tcam reset: (CPLD register 0x51) + Bit0/1: Reserved + Bit 2 : CPU_JTAG_RST + Bit 3 : RESET_SYS_CPLD + Bit 4 : RESET_MAC + Bit 5 : CPLD1_TCAM_SRST_L + Bit 6 : CPLD1_TCAM_PERST_L + Bit 7 : CPLD1_TCAM_CRST_L + tcam interrupt (CPLD register 0x62) + tcam interrupt mask (CPLD register 0x63) + Bit 0 : TCAM_CPLD1_GIO_L_1 + Bit 1 : TCAM_CPLD1_GIO_L_0 */ + unsigned char ipmi_resp_cpld; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom; /* eeprom data */ +}; + +struct as5916_54xl_sys_data *data = NULL; + +static struct platform_driver as5916_54xl_sys_driver = { + .probe = as5916_54xl_sys_probe, + .remove = as5916_54xl_sys_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as5916_54xl_sys_sysfs_attrs { + SYS_RESET_6_BIT0, /* Not Used */ + SYS_RESET_6_BIT1, /* Not Used */ + CPU_JTAG_RST, + RESET_SYS_CPLD, + RESET_MAC, + TCAM_SRST_L, + TCAM_PERST_L, + TCAM_CRST_L, + TCAM_RST_ALL, + SYS_RESET_6_ALL, + TCAM_CPLD1_GIO_L, + TCAM_CPLD1_GIO_L_MASK, + MB_CPLD1_VER, /* mainboard cpld1 version */ + MB_CPLD2_VER, /* mainboard cpld2 version */ + CPU_CPLD_VER, /* CPU board CPLD version */ + FAN_CPLD_VER, /* FAN CPLD version */ +}; + +static SENSOR_DEVICE_ATTR(tcam_rst_c, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_CRST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_pe, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_PERST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_s, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_SRST_L); +static SENSOR_DEVICE_ATTR(tcam_rst_all, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_RST_ALL); +static SENSOR_DEVICE_ATTR(sys_rst_6, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, SYS_RESET_6_ALL); +static SENSOR_DEVICE_ATTR(tcam_int, S_IRUGO, show_interrupt_status_6, NULL, TCAM_CPLD1_GIO_L); +static SENSOR_DEVICE_ATTR(tcam_int_msk, S_IWUSR | S_IRUGO, show_interrupt_status_6, set_interrupt_status_6_mask, TCAM_CPLD1_GIO_L_MASK); +static SENSOR_DEVICE_ATTR(mb_cpld1_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD1_VER); +static SENSOR_DEVICE_ATTR(mb_cpld2_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD2_VER); +static SENSOR_DEVICE_ATTR(cpu_cpld_ver, S_IRUGO, show_cpld_version, NULL, CPU_CPLD_VER); +static SENSOR_DEVICE_ATTR(fan_cpld_ver, S_IRUGO, show_cpld_version, NULL, FAN_CPLD_VER); + +static struct attribute *as5916_54xl_sys_attributes[] = { + &sensor_dev_attr_tcam_rst_c.dev_attr.attr, + &sensor_dev_attr_tcam_rst_pe.dev_attr.attr, + &sensor_dev_attr_tcam_rst_s.dev_attr.attr, + &sensor_dev_attr_tcam_rst_all.dev_attr.attr, + &sensor_dev_attr_sys_rst_6.dev_attr.attr, + &sensor_dev_attr_tcam_int.dev_attr.attr, + &sensor_dev_attr_tcam_int_msk.dev_attr.attr, + &sensor_dev_attr_mb_cpld1_ver.dev_attr.attr, + &sensor_dev_attr_mb_cpld2_ver.dev_attr.attr, + &sensor_dev_attr_cpu_cpld_ver.dev_attr.attr, + &sensor_dev_attr_fan_cpld_ver.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5916_54xl_sys_group = { + .attrs = as5916_54xl_sys_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) +{ + int status = 0; + unsigned char length = 0; + + if ((off + count) > EEPROM_SIZE) { + return -EINVAL; + } + + length = (count >= IPMI_READ_MAX_LEN) ? IPMI_READ_MAX_LEN : count; + data->ipmi_tx_data[0] = off; + data->ipmi_tx_data[1] = length; + status = ipmi_send_message(&data->ipmi, IPMI_SYSEEPROM_READ_CMD, + data->ipmi_tx_data, 2, + data->ipmi_resp_eeprom + off, length); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = length; /* Read length */ + memcpy(buf, data->ipmi_resp_eeprom + off, length); + +exit: + return status; +} + +static ssize_t sysfs_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + 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 + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sys_eeprom_read(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 int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IRUGO; + eeprom->read = sysfs_bin_read; + eeprom->write = NULL; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + return sysfs_create_bin_file(kobj, eeprom); +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static struct as5916_54xl_sys_data *as5916_54xl_sys_update_tcam(unsigned char subcmd) +{ + int status = 0; + + mutex_lock(&data->update_lock); + + data->valid = 0; + data->ipmi_tx_data[0] = subcmd; + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_READ_CMD, data->ipmi_tx_data, 1, + &data->ipmi_resp_tcam, sizeof(data->ipmi_resp_tcam)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; /* reset value to be set */ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_sys_data *data = NULL; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + data = as5916_54xl_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case SYS_RESET_6_BIT0: + case SYS_RESET_6_BIT1: + case CPU_JTAG_RST: + case RESET_SYS_CPLD: + case RESET_MAC: + case TCAM_SRST_L: + case TCAM_PERST_L: + case TCAM_CRST_L: + data->ipmi_tx_data[1] = reset ? (data->ipmi_resp_tcam | (1 << attr->index)): + (data->ipmi_resp_tcam & ~(1 << attr->index)); + break; + case TCAM_RST_ALL: + data->ipmi_tx_data[1] = (data->ipmi_resp_tcam & 0x1f) | (reset << TCAM_SRST_L); + break; + case SYS_RESET_6_ALL: + data->ipmi_tx_data[1] = reset; + break; + default: + return -EINVAL; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = IPMI_TCAM_RESET_SUBCMD; + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD, + data->ipmi_tx_data, 2, NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + return count; +} + +static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_sys_data *data = NULL; + int value = 0; + + data = as5916_54xl_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case SYS_RESET_6_BIT0: + case SYS_RESET_6_BIT1: + case CPU_JTAG_RST: + case RESET_SYS_CPLD: + case RESET_MAC: + case TCAM_SRST_L: + case TCAM_PERST_L: + case TCAM_CRST_L: + value = !!(data->ipmi_resp_tcam & (1 << attr->index)); + break; + case TCAM_RST_ALL: + value = (data->ipmi_resp_tcam >> 5) & 0x7; + break; + case SYS_RESET_6_ALL: + value = data->ipmi_resp_tcam & 0xff; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_sys_data *data = NULL; + unsigned char subcmd = 0; + int value = 0; + + switch (attr->index) { + case TCAM_CPLD1_GIO_L: + subcmd = IPMI_TCAM_INT_SUMCMD; + break; + case TCAM_CPLD1_GIO_L_MASK: + subcmd = IPMI_TCAM_INT_MASK_SUBCMD; + break; + default: + return -EINVAL; + } + + data = as5916_54xl_sys_update_tcam(subcmd); + if (!data->valid) { + return -EIO; + } + + value = data->ipmi_resp_tcam & 0x3; + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mask = 0; /* mask value to be set */ + int status; + struct as5916_54xl_sys_data *data = NULL; + + status = kstrtol(buf, 10, &mask); + if (status) { + return status; + } + + data = as5916_54xl_sys_update_tcam(IPMI_TCAM_INT_MASK_SUBCMD); + if (!data->valid) { + return -EIO; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = IPMI_TCAM_INT_MASK_SUBCMD; + data->ipmi_tx_data[1] = (data->ipmi_resp_tcam & 0xfc) | (mask & 0x3); + status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD, + data->ipmi_tx_data, 2, NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + return count; +} + +static struct as5916_54xl_sys_data *as5916_54xl_sys_update_cpld_ver(unsigned char cpld_addr) +{ + int status = 0; + + mutex_lock(&data->update_lock); + + data->valid = 0; + data->ipmi_tx_data[0] = cpld_addr; + status = ipmi_send_message(&data->ipmi, IPMI_GET_CPLD_VER_CMD, data->ipmi_tx_data, 1, + &data->ipmi_resp_cpld, sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5916_54xl_sys_data *data = NULL; + unsigned char cpld_addr = 0; + + switch (attr->index) { + case MB_CPLD1_VER: + cpld_addr = MAINBOARD_CPLD1_ADDR; + break; + case MB_CPLD2_VER: + cpld_addr = MAINBOARD_CPLD2_ADDR; + break; + case CPU_CPLD_VER: + cpld_addr = CPU_CPLD_ADDR; + break; + case FAN_CPLD_VER: + cpld_addr = FAN_CPLD_ADDR; + break; + default: + return -EINVAL; + } + + data = as5916_54xl_sys_update_cpld_ver(cpld_addr); + if (!data->valid) { + return -EIO; + } + + return sprintf(buf, "%d\n", data->ipmi_resp_cpld); +} + +static int as5916_54xl_sys_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom); + if (status) { + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_sys_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xl_sys_remove(struct platform_device *pdev) +{ + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom); + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_sys_group); + + return 0; +} + +static int __init as5916_54xl_sys_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_sys_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as5916_54xl_sys_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_sys_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_sys_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_sys_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916-54XL System driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_sys_init); +module_exit(as5916_54xl_sys_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-thermal.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-thermal.c new file mode 100755 index 00000000..6261a5e0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/modules/builds/x86-64-accton-as5916-54xl-thermal.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) Brandon Chuang + * + * 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 +#include + +#define DRVNAME "as5916_54xl_thermal" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_THERMAL_READ_CMD 0x12 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf); +static int as5916_54xl_thermal_probe(struct platform_device *pdev); +static int as5916_54xl_thermal_remove(struct platform_device *pdev); + +enum temp_data_index { + TEMP_ADDR, + TEMP_FAULT, + TEMP_INPUT, + TEMP_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as5916_54xl_thermal_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + char ipmi_resp[12]; /* 3 bytes for each thermal */ + struct ipmi_data ipmi; +}; + +struct as5916_54xl_thermal_data *data = NULL; + +static struct platform_driver as5916_54xl_thermal_driver = { + .probe = as5916_54xl_thermal_probe, + .remove = as5916_54xl_thermal_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as5916_54x_thermal_sysfs_attrs { + TEMP1_INPUT, + TEMP2_INPUT, + TEMP3_INPUT, + TEMP4_INPUT, +}; + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, TEMP4_INPUT); + +static struct attribute *as5916_54xl_thermal_attributes[] = { + &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, + NULL +}; + +static const struct attribute_group as5916_54xl_thermal_group = { + .attrs = as5916_54xl_thermal_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = 0; + int index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 5) || !data->valid) { + data->valid = 0; + + status = ipmi_send_message(&data->ipmi, IPMI_THERMAL_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + /* Get temp fault status */ + index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT; + if (unlikely(data->ipmi_resp[index] == 0)) { + status = -EIO; + goto exit; + } + + /* Get temperature in degree celsius */ + index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT; + status = data->ipmi_resp[index] * 1000; + + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as5916_54xl_thermal_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as5916_54xl_thermal_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as5916_54xl_thermal_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as5916_54xl_thermal_group); + + return 0; +} + +static int __init as5916_54xl_thermal_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as5916_54xl_thermal_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as5916_54xl_thermal_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as5916_54xl_thermal_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as5916_54xl_thermal_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as5916_54xl_thermal_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS5916 54XL Thermal driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xl_thermal_init); +module_exit(as5916_54xl_thermal_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/PKG.yml new file mode 100755 index 00000000..c4e7f1a4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-revision.yml PLATFORM=x86-64-accton-as5916-54xl ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/lib/Makefile new file mode 100755 index 00000000..63db397f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-as5916-54xl +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_as5916_54xl onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-as5916-54xl.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..ff9f8fa7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_as5916_54xl onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/.gitignore new file mode 100755 index 00000000..e69de29b diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/.module new file mode 100755 index 00000000..028a2bc0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_as5916_54xl diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/Makefile new file mode 100755 index 00000000..8c7393f3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as5916_54xl +AUTOMODULE := x86_64_accton_as5916_54xl +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/README new file mode 100755 index 00000000..49861bc1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as5916_54xl README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..2cc43b08 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_as5916_54xl Autogeneration +# +############################################################################### +x86_64_accton_as5916_54xl_AUTO_DEFS := module/auto/x86_64_accton_as5916_54xl.yml +x86_64_accton_as5916_54xl_AUTO_DIRS := module/inc/x86_64_accton_as5916_54xl module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/x86_64_accton_as5916_54xl.yml b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/x86_64_accton_as5916_54xl.yml new file mode 100755 index 00000000..d7e48101 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/auto/x86_64_accton_as5916_54xl.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as5916_54xl Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_ACCTON_AS5916_54XL_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as5916_54xl_config + + portingmacro: + x86_64_accton_as5916_54xl: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl.x b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl.x new file mode 100755 index 00000000..a5f44509 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_config.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_config.h new file mode 100755 index 00000000..0fc2c50e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as5916_54xl Configuration Header + * + * @addtogroup x86_64_accton_as5916_54xl-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS5916_54XL_CONFIG_H__ +#define __X86_64_ACCTON_AS5916_54XL_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as5916_54xl_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as5916_54xl_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as5916_54xl_config_settings table. */ +extern x86_64_accton_as5916_54xl_config_settings_t x86_64_accton_as5916_54xl_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as5916_54xl_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as5916_54xl_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as5916_54xl_porting.h" + +#endif /* __X86_64_ACCTON_AS5916_54XL_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_dox.h new file mode 100755 index 00000000..c39570a6 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as5916_54xl Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS5916_54XL_DOX_H__ +#define __X86_64_ACCTON_AS5916_54XL_DOX_H__ + +/** + * @defgroup x86_64_accton_as5916_54xl x86_64_accton_as5916_54xl - x86_64_accton_as5916_54xl Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as5916_54xl-x86_64_accton_as5916_54xl Public Interface + * @defgroup x86_64_accton_as5916_54xl-config Compile Time Configuration + * @defgroup x86_64_accton_as5916_54xl-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS5916_54XL_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_porting.h new file mode 100755 index 00000000..0dd5667e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/inc/x86_64_accton_as5916_54xl/x86_64_accton_as5916_54xl_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as5916_54xl Porting Macros. + * + * @addtogroup x86_64_accton_as5916_54xl-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS5916_54XL_PORTING_H__ +#define __X86_64_ACCTON_AS5916_54XL_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS5916_54XL_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS5916_54XL_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS5916_54XL_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_FREE free + #else + #error The macro X86_64_ACCTON_AS5916_54XL_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS5916_54XL_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS5916_54XL_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS5916_54XL_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS5916_54XL_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_ACCTON_AS5916_54XL_STRNCPY GLOBAL_STRNCPY + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_STRNCPY strncpy + #else + #error The macro X86_64_ACCTON_AS5916_54XL_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS5916_54XL_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS5916_54XL_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS5916_54XL_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS5916_54XL_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS5916_54XL_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS5916_54XL_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS5916_54XL_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS5916_54XL_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS5916_54XL_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..9b80644e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as5916_54xl_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as5916_54xl_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as5916_54xl_DEPENDMODULE_ENTRIES := init:x86_64_accton_as5916_54xl ucli:x86_64_accton_as5916_54xl + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..6b372705 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as5916_54xl_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..c649abc8 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/fani.c @@ -0,0 +1,235 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define MAX_FAN_SPEED 25500 +#define MAX_PSU_FAN_SPEED 25500 + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +#define PSU_FAN_INFO(pid, fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5), + CHASSIS_FAN_INFO(6), + PSU_FAN_INFO(1, 1), + PSU_FAN_INFO(2, 1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + + /* get fan present status + */ + ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; /* fan is not present */ + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""fan%d_input", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + return ONLP_STATUS_OK; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int value, ret; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", PSU_SYSFS_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED; + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int fid; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) + { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + if (fid < FAN_1_ON_FAN_BOARD || fid > FAN_6_ON_FAN_BOARD) { + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, "%s""fan%d_pwm", FAN_BOARD_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to write data to file %s""fan%d_pwm", FAN_BOARD_PATH, fid); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..fc9a7651 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,247 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define LED_FORMAT "/sys/devices/platform/as5916_54xl_led/%s" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_LOC, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN, +}; + +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 +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_ORANGE_BLINKING, ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE}, +{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} +}; + +static char *leds[] = /* must map with onlp_led_id */ +{ + NULL, + "led_loc", + "led_diag", + "led_psu1", + "led_psu2", + "led_fan" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 5 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + /* + * Turn off the LOCATION and DIAG LEDs at startup + */ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF); + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_LOC), ONLP_LED_MODE_OFF); + + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int lid, value; + + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Get LED mode */ + if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) { + DEBUG_PRINT("Unable to read status from file "LED_FORMAT, leds[lid]); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(lid, value); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF && info->mode != ONLP_LED_MODE_AUTO) { + info->status |= ONLP_LED_STATUS_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int lid; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), LED_FORMAT, leds[lid]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..8e64a6ec --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as5916_54xl +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..66c2ed64 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,65 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_accton_as5916_54xl_log.h" + +#define CHASSIS_FAN_COUNT 6 +#define CHASSIS_THERMAL_COUNT 5 +#define CHASSIS_LED_COUNT 5 +#define CHASSIS_PSU_COUNT 2 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_SYSFS_PATH "/sys/devices/platform/as5916_54xl_psu/" +#define FAN_BOARD_PATH "/sys/devices/platform/as5916_54xl_fan/" +#define IDPROM_PATH "/sys/devices/platform/as5916_54xl_sys/eeprom" + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..8a2e715c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/psui.c @@ -0,0 +1,154 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int pid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[pid]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + ret = onlp_file_read_int(&val, "%s""psu%d_present", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_present)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + ret = onlp_file_read_int(&val, "%s""psu%d_power_good", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_power_good)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Read voltage, current and power */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vin", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_iout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_pout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + /* Set the associated oid_table */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(pid + CHASSIS_FAN_COUNT); + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_temp1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(pid + CHASSIS_THERMAL_COUNT); + } + + /* Read model */ + char *string = NULL; + int len = onlp_file_read_str(&string, "%s""psu%d_model", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->model, string, len); + aim_free(string); + } + + /* Read serial */ + len = onlp_file_read_str(&string, "%s""psu%d_serial", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->serial, string, len); + aim_free(string); + } + + return ret; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..4817d3b8 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,289 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_as5916_54xl_int.h" +#include "x86_64_accton_as5916_54xl_log.h" + +#define PORT_EEPROM_FORMAT "/sys/devices/platform/as5916_54xl_sfp/module_eeprom_%d" +#define MODULE_PRESENT_FORMAT "/sys/devices/platform/as5916_54xl_sfp/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/devices/platform/as5916_54xl_sfp/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/devices/platform/as5916_54xl_sfp/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/devices/platform/as5916_54xl_sfp/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/devices/platform/as5916_54xl_sfp/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/devices/platform/as5916_54xl_sfp/module_rxlos_all" + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 54} + */ + int p; + + for(p = 0; p < 54; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[7]; + FILE* fp; + + /* Read present status of port 0~54 */ + int count = 0; + + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file from (%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x %x %x %x", bytes+0, bytes+1, bytes+2, bytes+3, + bytes+4, bytes+5, bytes+6); + fclose(fp); + if(count != 7) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file from(%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant QSFP ports */ + bytes[6] &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[6]; + FILE* fp; + + /* Read present status of port 0~25 */ + int count = 0; + + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rxlos_all device file from (%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x %x %x", bytes+0, bytes+1, bytes+2, + bytes+3, bytes+4, bytes+5); + fclose(fp); + if(count != 6) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rxlos_all device file from(%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t rx_los_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + rx_los_all <<= 8; + rx_los_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, (port+1)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + + if (port < 0) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + switch(control) + { + case ONLP_SFP_CONTROL_RX_LOS: + { + if (port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + if (port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..0b4852be --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,132 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_as5916_54xl_int.h" +#include "x86_64_accton_as5916_54xl_log.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as5916-54xl-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 5 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 6 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +#define CPLD_VERSION_FORMAT "/sys/devices/platform/as5916_54xl_sys/%s" + +typedef struct cpld_version { + char *attr_name; + int version; + char *description; +} cpld_version_t; + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, ret; + cpld_version_t cplds[] = { { "mb_cpld1_ver", 0, "Mainboard-CPLD#1"}, + { "mb_cpld2_ver", 0, "Mainboard-CPLD#2"}, + { "cpu_cpld_ver", 0, "CPU-CPLD"}, + { "fan_cpld_ver", 0, "FAN-CPLD"} }; + /* Read CPLD version + */ + for (i = 0; i < AIM_ARRAYSIZE(cplds); i++) { + ret = onlp_file_read_int(&cplds[i].version, CPLD_VERSION_FORMAT, cplds[i].attr_name); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read version from CPLD(%s)\r\n", cplds[i].attr_name); + return ONLP_STATUS_E_INTERNAL; + } + } + + pi->cpld_versions = aim_fstrdup("%s:%d, %s:%d, %s:%d, %s:%d", + cplds[0].description, cplds[0].version, + cplds[1].description, cplds[1].version, + cplds[2].description, cplds[2].version, + cplds[3].description, cplds[3].version); + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..5e399c4d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,129 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* ipmi_devfiles__[] = /* must map with onlp_thermal_id */ +{ + NULL, + NULL, /* CPU_CORE files */ + "/sys/devices/platform/as5916_54xl_thermal/temp1_input", + "/sys/devices/platform/as5916_54xl_thermal/temp2_input", + "/sys/devices/platform/as5916_54xl_thermal/temp3_input", + "/sys/devices/platform/as5916_54xl_thermal/temp4_input", + "/sys/devices/platform/as5916_54xl_psu/psu1_temp1_input", + "/sys/devices/platform/as5916_54xl_psu/psu2_temp1_input", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0*temp2_input", + "/sys/devices/platform/coretemp.0*temp3_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if(tid == THERMAL_CPU_CORE) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + return onlp_file_read_int(&info->mcelsius, ipmi_devfiles__[tid]); + +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_config.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_config.c new file mode 100755 index 00000000..1ad1aa85 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(_x) __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(_x) +x86_64_accton_as5916_54xl_config_settings_t x86_64_accton_as5916_54xl_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_STDLIB(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_UCLI(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS5916_54XL_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as5916_54xl_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as5916_54xl_config_STRINGIFY_VALUE +#undef __x86_64_accton_as5916_54xl_config_STRINGIFY_NAME + +const char* +x86_64_accton_as5916_54xl_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as5916_54xl_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as5916_54xl_config_settings[i].name, setting)) { + return x86_64_accton_as5916_54xl_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as5916_54xl_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as5916_54xl_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as5916_54xl_config_settings[i].name, x86_64_accton_as5916_54xl_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_enums.c new file mode 100755 index 00000000..d9a866d9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_int.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_int.h new file mode 100755 index 00000000..dc1c4a96 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as5916_54xl Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as5916_54xl_INT_H__ +#define __x86_64_accton_as5916_54xl_INT_H__ + +#include + + +#endif /* __x86_64_accton_as5916_54xl_INT_H__ */ \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.c new file mode 100755 index 00000000..c3a824e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as5916_54xl_log.h" +/* + * x86_64_accton_as5916_54xl log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS5916_54XL_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.h b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.h new file mode 100755 index 00000000..c3b1aba5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as5916_54xl_LOG_H__ +#define __x86_64_accton_as5916_54xl_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as5916_54xl +#include + +#endif /* __x86_64_accton_as5916_54xl_LOG_H__ */ \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_module.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_module.c new file mode 100755 index 00000000..01c63919 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as5916_54xl_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as5916_54xl_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_as5916_54xl_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_ucli.c new file mode 100755 index 00000000..2e3ea63f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/onlp/builds/src/module/src/x86_64_accton_as5916_54xl_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as5916_54xl_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as5916_54xl_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as5916_54xl) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as5916_54xl_ucli_module__ = + { + "x86_64_accton_as5916_54xl_ucli", + NULL, + x86_64_accton_as5916_54xl_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as5916_54xl_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as5916_54xl_ucli_module__); + n = ucli_node_create("x86_64_accton_as5916_54xl", NULL, &x86_64_accton_as5916_54xl_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as5916_54xl")); + return n; +} + +#else +void* +x86_64_accton_as5916_54xl_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/PKG.yml new file mode 100755 index 00000000..3c906377 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as5916-54xl REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/lib/x86-64-accton-as5916-54xl-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/lib/x86-64-accton-as5916-54xl-r0.yml new file mode 100755 index 00000000..16fa7cee --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/lib/x86-64-accton-as5916-54xl-r0.yml @@ -0,0 +1,33 @@ +--- + +###################################################################### +# +# platform-config for AS5916 +# +###################################################################### + +x86-64-accton-as5916-54xl-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS0,115200n8 + tg3.short_preamble=1 + tg3.bcm5718s_reset=1 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/python/x86_64_accton_as5916_54xl_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/python/x86_64_accton_as5916_54xl_r0/__init__.py new file mode 100755 index 00000000..5c3cd165 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xl/platform-config/r0/src/python/x86_64_accton_as5916_54xl_r0/__init__.py @@ -0,0 +1,15 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as5916_54xl_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x10_6x100): + PLATFORM='x86-64-accton-as5916-54xl-r0' + MODEL="AS5916-54XL" + SYS_OBJECT_ID=".5916.54" + + def baseconfig(self): + for m in [ 'fan', 'psu', 'leds', 'sfp', 'sys', 'thermal' ]: + self.insmod("x86-64-accton-as5916-54xl-%s.ko" % m) + + return True + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/onlp/builds/src/module/src/thermali.c old mode 100644 new mode 100755 index 742a4dd1..1e9f4161 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/onlp/builds/src/module/src/thermali.c @@ -26,6 +26,7 @@ #include #include #include "platform_lib.h" +#include #define VALIDATE(_id) \ do { \ @@ -34,11 +35,16 @@ } \ } while(0) + +/*Thermal 1 can be at 0x48 for R0A board, or 0x4C otherwise.*/ +static int thermal1_addrs[] = {0x4c, 0x48}; +static int thermal1_addr = -1; + static char* devfiles__[] = /* must map with onlp_thermal_id */ { NULL, NULL, /* CPU_CORE files */ - "/sys/bus/i2c/devices/10-0048*temp1_input", + "/sys/bus/i2c/devices/10-00%2x*temp1_input", "/sys/bus/i2c/devices/10-0049*temp1_input", "/sys/bus/i2c/devices/10-004a*temp1_input", "/sys/bus/i2c/devices/10-004b*temp1_input", @@ -62,7 +68,7 @@ static onlp_thermal_info_t linfo[] = { ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, - { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-48", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-%2X", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, @@ -97,6 +103,30 @@ onlp_thermali_init(void) return ONLP_STATUS_OK; } +/*check which addr of thermal1_addrs[] can be read.*/ +static int +_get_valid_t1_addr(char *path, int *addr) +{ + char fname[PATH_MAX]; + int i, rv, tmp; + if (thermal1_addr > 0){ + *addr = thermal1_addr; + return ONLP_STATUS_OK; + } + + for (i=0; imcelsius, cpu_coretemp_files); return rv; } - return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); + if (tid >= AIM_ARRAYSIZE(devfiles__)){ + return ONLP_STATUS_E_PARAM; + } + + devfile = devfiles__[tid]; + if (tid == THERMAL_1_ON_MAIN_BROAD) + { + onlp_oid_desc_t *des = &info->hdr.description; + char tmp[PATH_MAX]; + int t1_addr = thermal1_addrs[0]; + int rv; + + rv = _get_valid_t1_addr(devfiles__[tid], &t1_addr); + if(rv != ONLP_STATUS_OK) + return rv; + + /*Get real path of THERMAL_1 dev file*/ + snprintf(fname, sizeof(fname), devfiles__[tid], t1_addr); + devfile = fname; + + /*Replace description*/ + strncpy(tmp, *des, sizeof(tmp)); + snprintf(*des, sizeof(*des), tmp, t1_addr); + } + + return onlp_file_read_int(&info->mcelsius, devfile); } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/platform-config/r0/src/python/x86_64_accton_as5916_54xm_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/platform-config/r0/src/python/x86_64_accton_as5916_54xm_r0/__init__.py index e8b16a74..b4a6e226 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/platform-config/r0/src/python/x86_64_accton_as5916_54xm_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xm/platform-config/r0/src/python/x86_64_accton_as5916_54xm_r0/__init__.py @@ -27,7 +27,8 @@ class OnlPlatform_x86_64_accton_as5916_54xm_r0(OnlPlatformAccton, ('as5916_54xm_fan', 0x66, 9), # inititate LM75 - ('lm75', 0x48, 10), + ('lm75', 0x48, 10), #For R0A + ('lm75', 0x4c, 10), #For R0B or later ('lm75', 0x49, 10), ('lm75', 0x4a, 10), ('lm75', 0x4b, 10), diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/PKG.yml new file mode 100755 index 00000000..bb3b97b9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as7112-54x ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/Makefile new file mode 100755 index 00000000..1d60f75c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-as7112-54x +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-cpld.c new file mode 100755 index 00000000..6764bcdb --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-cpld.c @@ -0,0 +1,1155 @@ +/* + * 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 as7112_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 { + as7112_54x_cpld1, + as7112_54x_cpld2, + as7112_54x_cpld3 +}; + +struct as7112_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7112_54x_cpld_id[] = { + { "as7112_54x_cpld1", as7112_54x_cpld1 }, + { "as7112_54x_cpld2", as7112_54x_cpld2 }, + { "as7112_54x_cpld3", as7112_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7112_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 + +enum as7112_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 as7112_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7112_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 *as7112_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7112_54x_cpld1_group = { + .attrs = as7112_54x_cpld1_attributes, +}; + +static struct attribute *as7112_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 as7112_54x_cpld2_group = { + .attrs = as7112_54x_cpld2_attributes, +}; + +static struct attribute *as7112_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 as7112_54x_cpld3_group = { + .attrs = as7112_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[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7112_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7112_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + + if (data->type == as7112_54x_cpld2) + { + if (2 == i) + { + values[3] = 0 ; + goto only_read_three; + } + } + } +only_read_three: + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as7112_54x_cpld3) { + // u8 t1; + values[3] &= 0x3F; + #if 0 + t1 = values[3]; + values[3] = 0; + if ( t1 & 0x01 ) // port 49 + values[3] = 0x01; + if ( t1 & 0x04 ) // port 50 + values[3] |= 0x02; + if ( t1 & 0x10 ) // port 51 + values[3] |= 0x04; + if ( t1 & 0x02 ) // port 52 + values[3] |= 0x08; + if ( t1 & 0x08 ) // port 53 + values[3] |= 0x10; + if ( t1 & 0x20 ) // port 54 + values[3] |= 0x20; + #endif + } + + 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[] = {0x0f, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct as7112_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7112_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 as7112_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 = 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 = 0x2; + break; + case MODULE_PRESENT_51: + reg = 0x14; + mask = 0x4; + break; + case MODULE_PRESENT_52: + reg = 0x14; + mask = 0x8; + break; + case MODULE_PRESENT_53: + reg = 0x14; + mask = 0x10; + 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 = 0x0f; + 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 = 0x0f; + 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 = as7112_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 as7112_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 = 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 = as7112_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7112_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 as7112_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 = as7112_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 as7112_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 as7112_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 as7112_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7112_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 as7112_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 as7112_54x_cpld1: + group = &as7112_54x_cpld1_group; + break; + case as7112_54x_cpld2: + group = &as7112_54x_cpld2_group; + break; + case as7112_54x_cpld3: + group = &as7112_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7112_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7112_54x_cpld_remove(struct i2c_client *client) +{ + struct as7112_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7112_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7112_54x_cpld1: + group = &as7112_54x_cpld1_group; + break; + case as7112_54x_cpld2: + group = &as7112_54x_cpld2_group; + break; + case as7112_54x_cpld3: + group = &as7112_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7112_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 as7112_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 as7112_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 = as7112_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7112_54x_cpld_read); + +int as7112_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 = as7112_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7112_54x_cpld_write); + +static struct i2c_driver as7112_54x_cpld_driver = { + .driver = { + .name = "as7112_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7112_54x_cpld_probe, + .remove = as7112_54x_cpld_remove, + .id_table = as7112_54x_cpld_id, +}; + +static int __init as7112_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7112_54x_cpld_driver); +} + +static void __exit as7112_54x_cpld_exit(void) +{ + i2c_del_driver(&as7112_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7112_54x_cpld_init); +module_exit(as7112_54x_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-fan.c new file mode 100755 index 00000000..e7c83620 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-fan.c @@ -0,0 +1,494 @@ +/* + * A hwmon driver for the Accton as7112 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 + +#define DRVNAME "as7112_54x_fan" + +static struct as7112_54x_fan_data *as7112_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 as7112_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FRONT_FAULT, + FAN2_FRONT_FAULT, + FAN3_FRONT_FAULT, + FAN4_FRONT_FAULT, + FAN5_FRONT_FAULT, + FAN1_REAR_FAULT, + FAN2_REAR_FAULT, + FAN3_REAR_FAULT, + FAN4_REAR_FAULT, + FAN5_REAR_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_front_fault.dev_attr.attr,\ + &sensor_dev_attr_fan##index##_rear_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +static struct attribute *as7112_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MIN_DUTY_CYCLE 20 +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as7112_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7112_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 as7112_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; + } + + as7112_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 as7112_54x_fan_data *data = as7112_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FRONT_FAULT: + case FAN2_FRONT_FAULT: + case FAN3_FRONT_FAULT: + case FAN4_FRONT_FAULT: + case FAN5_FRONT_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_FRONT_FAULT_REG], + attr->index - FAN1_FRONT_FAULT)); + break; + case FAN1_REAR_FAULT: + case FAN2_REAR_FAULT: + case FAN3_REAR_FAULT: + case FAN4_REAR_FAULT: + case FAN5_REAR_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_REAR_FAULT_REG], + attr->index - FAN1_REAR_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7112_54x_fan_group = { + .attrs = as7112_54x_fan_attributes, +}; + +static struct as7112_54x_fan_data *as7112_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7112_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 as7112_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7112_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 as7112_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7112_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 as7112_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, &as7112_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, &as7112_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7112_54x_fan_remove(struct i2c_client *client) +{ + struct as7112_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7112_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7112_54x_fan_id[] = { + { "as7112_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7112_54x_fan_id); + +static struct i2c_driver as7112_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7112_54x_fan_probe, + .remove = as7112_54x_fan_remove, + .id_table = as7112_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7112_54x_fan_init(void) +{ +#if 0 + extern int platform_accton_as7112_54x(void); + if (!platform_accton_as7112_54x()) { + return -ENODEV; + } +#endif + return i2c_add_driver(&as7112_54x_fan_driver); +} + +static void __exit as7112_54x_fan_exit(void) +{ + i2c_del_driver(&as7112_54x_fan_driver); +} + +module_init(as7112_54x_fan_init); +module_exit(as7112_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7112_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-led.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-led.c new file mode 100755 index 00000000..cac138c2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-led.c @@ -0,0 +1,410 @@ +/* + * A LED driver for the accton_as7112_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 "as7112_54x_led" + +#define DEBUG_MODE 0 +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as7112_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7112_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct as7112_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 as7112_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 as7112_54x_led_read_value(u8 reg) +{ + return as7112_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} +static int as7112_54x_led_write_value(u8 reg, u8 value) +{ + return as7112_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} +static void as7112_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_as7112_54x_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7112_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 as7112_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 = as7112_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); + as7112_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} +static void as7112_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7112_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} +static enum led_brightness as7112_54x_led_diag_get(struct led_classdev *cdev) +{ + as7112_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} +static void as7112_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7112_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} +static enum led_brightness as7112_54x_led_loc_get(struct led_classdev *cdev) +{ + as7112_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} +static void as7112_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7112_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} +static enum led_brightness as7112_54x_led_fan_get(struct led_classdev *cdev) +{ + as7112_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} +static void as7112_54x_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7112_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} +static enum led_brightness as7112_54x_led_psu1_get(struct led_classdev *cdev) +{ + as7112_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} +static void as7112_54x_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7112_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} +static enum led_brightness as7112_54x_led_psu2_get(struct led_classdev *cdev) +{ + as7112_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} +static struct led_classdev as7112_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7112_54x_led::diag", + .default_trigger = "unused", + .brightness_set = as7112_54x_led_diag_set, + .brightness_get = as7112_54x_led_diag_get, + .max_brightness = LED_MODE_YELLOW, + }, + [LED_TYPE_LOC] = { + .name = "as7112_54x_led::loc", + .default_trigger = "unused", + .brightness_set = as7112_54x_led_loc_set, + .brightness_get = as7112_54x_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "as7112_54x_led::fan", + .default_trigger = "unused", + .brightness_set = as7112_54x_led_fan_set, + .brightness_get = as7112_54x_led_fan_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7112_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7112_54x_led_psu1_set, + .brightness_get = as7112_54x_led_psu1_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7112_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7112_54x_led_psu2_set, + .brightness_get = as7112_54x_led_psu2_get, + .max_brightness = LED_MODE_AUTO, + }, +}; +static int as7112_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + for (i = 0; i < ARRAY_SIZE(as7112_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7112_54x_leds[i]); + if (ret < 0) { + break; + } + } + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7112_54x_leds)){ + int j; + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7112_54x_leds[i]); + } + } + return ret; +} +static int as7112_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7112_54x_leds); i++) { + led_classdev_unregister(&as7112_54x_leds[i]); + } + + return 0; +} +static struct platform_driver as7112_54x_led_driver = { + .probe = as7112_54x_led_probe, + .remove = as7112_54x_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; +static int __init as7112_54x_led_init(void) +{ + int ret; + +#if 0 + extern int platform_accton_as7112_54x(void); + if (!platform_accton_as7112_54x()) { + return -ENODEV; + } +#endif + + ret = platform_driver_register(&as7112_54x_led_driver); + if (ret < 0) { + goto exit; + } + ledctl = kzalloc(sizeof(struct as7112_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(&as7112_54x_led_driver); +exit: + return ret; +} +static void __exit as7112_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7112_54x_led_driver); + kfree(ledctl); +} + +module_init(as7112_54x_led_init); +module_exit(as7112_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7112_54x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-psu.c new file mode 100755 index 00000000..f5e53982 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/modules/builds/x86-64-accton-as7112-54x-psu.c @@ -0,0 +1,369 @@ +/* + * An hwmon driver for accton as7112_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 as7112_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7112_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static unsigned int as7112_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 as7112_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 as7112_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 *as7112_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 i2c_client *client = to_i2c_client(dev); + struct as7112_54x_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned int ret = as7112_54x_psu_update_device(dev, 0); + u8 status = 0; + + if (ret == 0) { + return -ENXIO; + } + + 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 i2c_client *client = to_i2c_client(dev); + struct as7112_54x_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned int ret; + u8 update_eeprom; + char *ptr = NULL; + + if (attr->index == PSU_MODEL_NAME) { + + ptr = data->model_name; + update_eeprom = 1; + } + else { /* PSU_SERIAL_NUBMER */ + ptr = data->serial; + update_eeprom = 2; + } + + ret = as7112_54x_psu_update_device(dev, update_eeprom); + + if (ret == 0) { + return -ENXIO; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as7112_54x_psu_group = { + .attrs = as7112_54x_psu_attributes, +}; + +static int as7112_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7112_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 as7112_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, &as7112_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, &as7112_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7112_54x_psu_remove(struct i2c_client *client) +{ + struct as7112_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7112_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7112_54x_psu1, + as7112_54x_psu2 +}; + +static const struct i2c_device_id as7112_54x_psu_id[] = { + { "as7112_54x_psu1", as7112_54x_psu1 }, + { "as7112_54x_psu2", as7112_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7112_54x_psu_id); + +static struct i2c_driver as7112_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7112_54x_psu", + }, + .probe = as7112_54x_psu_probe, + .remove = as7112_54x_psu_remove, + .id_table = as7112_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7112_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 unsigned int as7112_54x_psu_update_device(struct device *dev, u8 update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7112_54x_psu_data *data = i2c_get_clientdata(client); + unsigned int ret = 1; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { + int status; + data->valid = 0; + ret = 0; + dev_dbg(&client->dev, "Starting as7112_54x update\n"); + //printk(" %s update <%d> \n", dev_name(dev),update_time); + /* Read psu status */ + status = as7112_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; + } + + if ( !IS_POWER_GOOD(data->index, data->status) ) // if not power good force to re-read + { + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + } + + if ((update_eeprom==1) || (data->model_name[0]==0)) { + + memset(data->model_name, 0, sizeof(data->model_name)); + if ( IS_PRESENT(data->index, data->status) ) + { + /* Read model name */ + status = as7112_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'; + } + } + }//update_eeprom == 1 + + if ((update_eeprom == 2) || (data->serial[0]== 0) ) { + + memset(data->serial, 0, sizeof(data->serial)); + if ( IS_PRESENT(data->index, data->status) ) + { + /* Read serial number */ + status = as7112_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'; + } + }//IS_PRESENT + }//update_eeprom == 2 + + data->last_updated = jiffies; + data->valid = 1; + ret = 1; + }//time_after +exit: + mutex_unlock(&data->update_lock); + return ret; +} + +static int __init as7112_54x_psu_init(void) +{ + //extern int platform_accton_as7112_54x(void); + //if (!platform_accton_as7112_54x()) { + // return -ENODEV; + //} + + return i2c_add_driver(&as7112_54x_psu_driver); +} + +static void __exit as7112_54x_psu_exit(void) +{ + i2c_del_driver(&as7112_54x_psu_driver); +} + +module_init(as7112_54x_psu_init); +module_exit(as7112_54x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7112_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/PKG.yml new file mode 100755 index 00000000..e496845e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as7112-54x ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/lib/Makefile new file mode 100755 index 00000000..a401dca2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-as7112-54x +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_as7112_54x onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-as7112-54x.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..4efbb417 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_as7112_54x onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/.module new file mode 100755 index 00000000..09bc6834 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_as7112_54x diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/Makefile new file mode 100755 index 00000000..45a5d5d5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as7112_54x +AUTOMODULE := x86_64_accton_as7112_54x +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/README new file mode 100755 index 00000000..45d24080 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as7112_54x README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..e70ae989 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_as7112_54x Autogeneration +# +############################################################################### +x86_64_accton_as7112_54x_AUTO_DEFS := module/auto/x86_64_accton_as7112_54x.yml +x86_64_accton_as7112_54x_AUTO_DIRS := module/inc/x86_64_accton_as7112_54x module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/x86_64_accton_as7112_64x.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/x86_64_accton_as7112_64x.yml new file mode 100755 index 00000000..fa5fe1ef --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/auto/x86_64_accton_as7112_64x.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as7112_54x Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_accton_as7112_54x_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_accton_as7112_54x_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as7112_54x_config + + portingmacro: + x86_64_accton_as7112_54x: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x.x b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x.x new file mode 100755 index 00000000..7cd38c22 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_config.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_config.h new file mode 100755 index 00000000..5464c156 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7112_54x Configuration Header + * + * @addtogroup x86_64_accton_as7112_54x-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7112_54X_CONFIG_H__ +#define __X86_64_ACCTON_AS7112_54X_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS7112_54X_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_accton_as7112_54x_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as7112_54x_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as7112_54x_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as7112_54x_config_settings table. */ +extern x86_64_accton_as7112_54x_config_settings_t x86_64_accton_as7112_54x_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as7112_54x_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as7112_54x_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as7112_54x_porting.h" + +#endif /* __X86_64_ACCTON_AS7112_54X_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_dox.h new file mode 100755 index 00000000..81ed2d26 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as7112_54x Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7112_54X_DOX_H__ +#define __X86_64_ACCTON_AS7112_54X_DOX_H__ + +/** + * @defgroup x86_64_accton_as7112_54x x86_64_accton_as7112_54x - x86_64_accton_as7112_54x Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as7112_54x-x86_64_accton_as7112_54x Public Interface + * @defgroup x86_64_accton_as7112_54x-config Compile Time Configuration + * @defgroup x86_64_accton_as7112_54x-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS7112_54X_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_porting.h new file mode 100755 index 00000000..de7205ec --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/inc/x86_64_accton_as7112_54x/x86_64_accton_as7112_54x_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7112_54x Porting Macros. + * + * @addtogroup x86_64_accton_as7112_54x-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7112_54X_PORTING_H__ +#define __X86_64_ACCTON_AS7112_54X_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS7112_54X_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS7112_54X_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS7112_54X_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_FREE free + #else + #error The macro X86_64_ACCTON_AS7112_54X_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS7112_54X_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS7112_54X_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS7112_54X_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS7112_54X_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_ACCTON_AS7112_54X_STRNCPY GLOBAL_STRNCPY + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_STRNCPY strncpy + #else + #error The macro X86_64_ACCTON_AS7112_54X_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS7112_54X_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS7112_54X_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS7112_54X_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS7112_54X_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7112_54X_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS7112_54X_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7112_54X_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS7112_54X_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS7112_54X_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..c02bb873 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as7112_54x_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as7112_54x_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as7112_54x_DEPENDMODULE_ENTRIES := init:x86_64_accton_as7112_54x ucli:x86_64_accton_as7112_54x diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..1a4a8554 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as7112_54x_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/debug.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/debug.c new file mode 100755 index 00000000..ea8024a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_accton_as7112_54x_int.h" + +#if x86_64_accton_as7112_54x_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_accton_as7112_54x_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..13b4487b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/fani.c @@ -0,0 +1,397 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include "platform_lib.h" + +#define PREFIX_PATH_ON_MAIN_BOARD "/sys/bus/i2c/devices/0-0063/" +#define PREFIX_PATH_ON_PSU "/sys/bus/i2c/devices/" + +#define MAX_FAN_SPEED 18000 +#define MAX_PSU_FAN_SPEED 25500 + +#define PROJECT_NAME +#define LEN_FILE_NAME 80 + +#define FAN_RESERVED 0 +#define FAN_1_ON_MAIN_BOARD 1 +#define FAN_2_ON_MAIN_BOARD 2 +#define FAN_3_ON_MAIN_BOARD 3 +#define FAN_4_ON_MAIN_BOARD 4 +#define FAN_5_ON_MAIN_BOARD 5 +#define FAN_1_ON_PSU1 6 +#define FAN_1_ON_PSU2 7 + +typedef struct fan_path_S +{ + char present[LEN_FILE_NAME]; + char status[LEN_FILE_NAME]; + char speed[LEN_FILE_NAME]; + char direction[LEN_FILE_NAME]; + char ctrl_speed[LEN_FILE_NAME]; + char r_speed[LEN_FILE_NAME]; +}fan_path_T; + +#define _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) \ + { #prj"fan"#id"_present", #prj"fan"#id"_front_fault", #prj"fan"#id"_front_speed_rpm", \ + #prj"fan"#id"_direction", #prj"fan_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" } + +#define MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) + +#define MAKE_FAN_PATH_ON_PSU(folder) \ + {"", #folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ + "", #folder"/psu_fan1_duty_cycle_percentage", "" } + +static fan_path_T fan_path[] = /* must map with onlp_fan_id */ +{ + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_RESERVED), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_1_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_2_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_3_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_4_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_5_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_PSU(3-0058), + MAKE_FAN_PATH_ON_PSU(4-005b) +}; + +#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define OPEN_READ_FILE(fd,fullpath,data,nbytes,len) \ + DEBUG_PRINT("[Debug][%s][%d][openfile: %s]\n", __FUNCTION__, __LINE__, fullpath); \ + if ((fd = open(fullpath, O_RDONLY)) == -1) \ + return ONLP_STATUS_E_INTERNAL; \ + if ((len = read(fd, r_data, nbytes)) <= 0){ \ + close(fd); \ + return ONLP_STATUS_E_INTERNAL;} \ + DEBUG_PRINT("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, r_data); \ + if (close(fd) == -1) \ + return ONLP_STATUS_E_INTERNAL + +static uint32_t +_onlp_fani_info_get_psu_fan_direction(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) { + continue; + } + + switch (psu_type) { + case PSU_TYPE_AC_F2B: + case PSU_TYPE_DC_48V_F2B: + case PSU_TYPE_DC_12V_F2B: + return ONLP_FAN_STATUS_F2B; + case PSU_TYPE_AC_B2F: + case PSU_TYPE_DC_48V_B2F: + case PSU_TYPE_DC_12V_B2F: + return ONLP_FAN_STATUS_B2F; + default: + return 0; + }; + } + + return 0; +} + +static int +_onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info) +{ + int fd, len, nbytes = 10; + char r_data[10] = {0}; + char fullpath[65] = {0}; + + /* check if fan is present + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].present); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + if (atoi(r_data) == 0) { + return ONLP_STATUS_OK; + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan fault status (turn on when any one fails) + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].status); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + if (atoi(r_data) > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + /* get fan/fanr direction (both : the same) + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].direction); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + + if (atoi(r_data) == 0) /*B2F*/ + info->status |= ONLP_FAN_STATUS_B2F; + else + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan speed (take the min from two speeds) + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + info->rpm = atoi(r_data); + + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].r_speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + if (info->rpm > atoi(r_data)) { + info->rpm = atoi(r_data); + } + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +static int +_onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) +{ + int fd, len, nbytes = 10; + char r_data[10] = {0}; + char fullpath[80] = {0}; + + /* get fan direction + */ + info->status |= _onlp_fani_info_get_psu_fan_direction(); + + /* get fan fault status + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].status); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + info->status |= (atoi(r_data) > 0) ? ONLP_FAN_STATUS_FAILED : 0; + + /* get fan speed + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].speed); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + info->rpm = atoi(r_data); + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= ONLP_FAN_STATUS_PRESENT; + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + rc = _onlp_fani_info_get_fan_on_psu(local_id, info); + break; + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + rc =_onlp_fani_info_get_fan(local_id, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fd, len, nbytes=10, local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + /* get fullpath */ + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed); + break; + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].ctrl_speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + sprintf(data, "%d", p); + DEBUG_PRINT("[Debug][%s][%d][openfile: %s][data=%s]\n", __FUNCTION__, __LINE__, fullpath, data); + + /* Create output file descriptor */ + fd = open(fullpath, O_WRONLY, 0644); + if (fd == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + len = write (fd, data, (ssize_t) nbytes); + if (len != nbytes) { + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + close(fd); + return ONLP_STATUS_OK; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..9a108a99 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,259 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +#define prefix_path "/sys/class/leds/as7112_54x_led::" +#define filename "brightness" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_DIAG, + LED_LOC, + LED_FAN, + LED_PSU1, + LED_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_BLUE, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_DIAG, LED_MODE_YELLOW,ONLP_LED_MODE_YELLOW}, +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_LOC, LED_MODE_AMBER ,ONLP_LED_MODE_ORANGE}, +{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} +}; + +static char last_path[][10] = /* must map with onlp_led_id */ +{ + "reserved", + "diag", + "loc", + "fan", + "psu1", + "psu2" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 1 (DIAG LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 2 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 3 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 4 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + char data[2] = {0}; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Set LED mode */ + if (onlp_file_read_string(fullpath, data, sizeof(data), 0) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(local_id, atoi(data)); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int local_id; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + + if (onlp_file_write_integer(fullpath, onlp_to_driver_led_mode(local_id, mode)) != 0) + { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..37e5e214 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as7112_54x +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..d747c970 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,246 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +int _onlp_file_write(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_WRONLY, S_IWUSR)) == -1) { + return -1; + } + + if ((len = write(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_write_integer(char *filename, int value) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return _onlp_file_write(filename, buf, (int)strlen(buf), 0); +} + +#if 0 +int deviceNodeWriteInt(char *filename, int value, int data_len) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return _onlp_file_write(filename, buf, (int)strlen(buf), data_len); +} +#endif + +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 11 +#define I2C_PSU_FAN_DIR_LEN 3 +#include +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + char fan_dir[I2C_PSU_FAN_DIR_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name); + + if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if(isspace(model_name[strlen(model_name)-1])) { + model_name[strlen(model_name)-1] = 0; + } + + if ( (strncmp(model_name, "YM-2651Y", 8) == 0) || + (strncmp(model_name, "DPS400AB", 8) == 0) || + (strncmp(model_name, "YM-2401J", 8) == 0) + ) + { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + //printf("Vic Said It is AC Type %s\n",modelname); + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + //return PSU_TYPE_UNKNOWN; + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F; + } + return PSU_TYPE_AC_F2B; + } + + if (strncmp(model_name, "YM-2651V", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_DC_48V_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_DC_48V_B2F; + } + } + + if (strncmp(model_name, "PSU-12V-750", 11) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); + } + + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", 3) == 0) { + return PSU_TYPE_DC_12V_F2B; + } + + if (strncmp(fan_dir, "B2F", 3) == 0) { + return PSU_TYPE_DC_12V_B2F; + } + + if (strncmp(fan_dir, "NON", 3) == 0) { + return PSU_TYPE_DC_12V_FANLESS; + } + } + + return PSU_TYPE_UNKNOWN; +} + +#define PSU_SERIAL_NUMBER_LEN 18 + +int psu_serial_number_get(int id, char *serial, int serial_len) +{ + int size = 0; + int ret = ONLP_STATUS_OK; + char *prefix = NULL; + + if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) { + return ONLP_STATUS_E_PARAM; + } + + prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; + + ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_mfr_serial"); + if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) { + return ONLP_STATUS_E_INTERNAL; + + } + + serial[PSU_SERIAL_NUMBER_LEN] = '\0'; + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..e25f2e12 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,85 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_accton_as7112_54x_log.h" + +#define CHASSIS_FAN_COUNT 5 +#define CHASSIS_THERMAL_COUNT 3 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/3-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/4-005b/" + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/3-0050/" +#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/4-0053/" + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +#define IDPROM_PATH "/sys/bus/i2c/devices/1-0057/eeprom" + +#if 0 +int deviceNodeWriteInt(char *filename, int value, int data_len); +int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len); +int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_len); +#endif + +int onlp_file_write_integer(char *filename, int value); +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F, + PSU_TYPE_DC_48V_F2B, + PSU_TYPE_DC_48V_B2F, + PSU_TYPE_DC_12V_FANLESS, + PSU_TYPE_DC_12V_F2B, + PSU_TYPE_DC_12V_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +int psu_serial_number_get(int id, char *serial, int serial_len); + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..fb10b679 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/psui.c @@ -0,0 +1,273 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, "%s%s", PSU1_AC_HWMON_PREFIX, node); + } + else if (PSU2_ID == id) { + sprintf(node_path, "%s%s", PSU2_AC_HWMON_PREFIX, node); + } + + ret = onlp_file_read_string(node_path, buf, sizeof(buf), 0); + + if (ret == 0) { + *value = atoi(buf); + } + + return ret; +} + +static int +psu_ym2651_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + } + else { + sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + ret = onlp_file_read_string(node_path, buf, sizeof(buf), 0); + + if (ret == 0) { + *value = atoi(buf); + } + + return ret; +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_ym2651_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + psu_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + +#include +#define DC12V_750_REG_TO_CURRENT(low, high) (((low << 4 | high >> 4) * 20 * 1000) / 754) +#define DC12V_750_REG_TO_VOLTAGE(low, high) ((low << 4 | high >> 4) * 25) + +static int +psu_dc12v_750_info_get(onlp_psu_info_t* info) +{ + int pid = ONLP_OID_ID_GET(info->hdr.id); + int bus = (PSU1_ID == pid) ? 18 : 17; + int iout_low, iout_high; + int vout_low, vout_high; + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_DC12; + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Get current + */ + iout_low = onlp_i2c_readb(bus, 0x6f, 0x0, ONLP_I2C_F_FORCE); + iout_high = onlp_i2c_readb(bus, 0x6f, 0x1, ONLP_I2C_F_FORCE); + + if ((iout_low >= 0) && (iout_high >= 0)) { + info->miout = DC12V_750_REG_TO_CURRENT(iout_low, iout_high); + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + /* Get voltage + */ + vout_low = onlp_i2c_readb(bus, 0x6f, 0x2, ONLP_I2C_F_FORCE); + vout_high = onlp_i2c_readb(bus, 0x6f, 0x3, ONLP_I2C_F_FORCE); + + if ((vout_low >= 0) && (vout_high >= 0)) { + info->mvout = DC12V_750_REG_TO_VOLTAGE(vout_low, vout_high); + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + /* Get power based on current and voltage + */ + if ((info->caps & ONLP_PSU_CAPS_IOUT) && (info->caps & ONLP_PSU_CAPS_VOUT)) { + info->mpout = (info->miout * info->mvout) / 1000; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + + /* Get PSU type + */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + + switch (psu_type) { + case PSU_TYPE_AC_F2B: + case PSU_TYPE_AC_B2F: + info->caps = ONLP_PSU_CAPS_AC; + ret = psu_ym2651_info_get(info); + break; + case PSU_TYPE_DC_48V_F2B: + case PSU_TYPE_DC_48V_B2F: + info->caps = ONLP_PSU_CAPS_DC48; + ret = psu_ym2651_info_get(info); + break; + case PSU_TYPE_DC_12V_F2B: + case PSU_TYPE_DC_12V_B2F: + case PSU_TYPE_DC_12V_FANLESS: + ret = psu_dc12v_750_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..8a96dfaa --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,379 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_as7112_54x_int.h" +#include "x86_64_accton_as7112_54x_log.h" + +#define PORT_BUS_INDEX(port) (port<48)?(port+30):(port-48+14) + +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/1-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/1-00%d/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/1-0061/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/1-0062/module_rx_los_all" + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 54} + */ + int p; + + for(p = 0; p < 54; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + int addr; + + addr = (port < 24) ? 61 : 62; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[8], *ptr = NULL; + FILE* fp; + int addr; + + ptr = bytes; + + for (addr = 61; addr <= 62; addr++) { + /* Read present status of port 0~53 */ + char file[64] = {0}; + + sprintf(file, MODULE_PRESENT_ALL_ATTR, addr); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD3."); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD3."); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; + } + + /* Mask out non-existant QSFP ports */ + // bytes[3] &= 0x00; + bytes[7] &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0 ; + presence_all |= bytes[7]; + presence_all <<= 8; + + for(i = 6; i >= 4; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + for(i = 2; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[6]; + uint32_t *ptr = bytes; + FILE* fp; + + /* Read present status of port 0~23 */ + int addr, i = 0; + + for (addr = 61; addr <= 62; addr+=1) { + if (addr == 61) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; + } + + /* Convert to 64 bit integer in port order */ + i = 0; + uint64_t rx_los_all = 0 ; + for(i = 5; i >= 0; i--) { + rx_los_all <<= 8; + rx_los_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 61 : 62; + int bus = 1; + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 61 : 62; + int bus = 1; + + switch(control) + { + case ONLP_SFP_CONTROL_RX_LOS: + { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..bb7a9245 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,258 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "x86_64_accton_as7112_54x_int.h" +#include "x86_64_accton_as7112_54x_log.h" + +#include "platform_lib.h" + +#define NUM_OF_THERMAL_ON_MAIN_BROAD 3 +#define NUM_OF_FAN_ON_MAIN_BROAD 5 +#define NUM_OF_PSU_ON_MAIN_BROAD 2 +#define NUM_OF_LED_ON_MAIN_BROAD 5 + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as7112-54x-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 4 Thermal sensors on the chassis */ + for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 4 Fans on the chassis */ + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +typedef struct fan_ctrl_policy { + int duty_cycle; + int temp_down_adjust; /* The boundary temperature to down adjust fan speed */ + int temp_up_adjust; /* The boundary temperature to up adjust fan speed */ +} fan_ctrl_policy_t; + +fan_ctrl_policy_t fan_ctrl_policy_f2b[] = { +{32, 0, 174000}, +{38, 170000, 182000}, +{50, 178000, 190000}, +{63, 186000, 0} +}; + +fan_ctrl_policy_t fan_ctrl_policy_b2f[] = { +{32, 0, 140000}, +{38, 135000, 150000}, +{50, 145000, 160000}, +{69, 155000, 0} +}; + +#define FAN_DUTY_CYCLE_MAX 100 +#define FAN_SPEED_CTRL_PATH "/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage" + +/* + * 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 + */ +int +onlp_sysi_platform_manage_fans(void) +{ + int i = 0, arr_size, temp; + fan_ctrl_policy_t *policy; + int cur_duty_cycle, new_duty_cycle; + onlp_thermal_info_t thermal_1, thermal_2, thermal_3; + + int fd, len; + char buf[10] = {0}; + + /* Get each fan status + */ + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + onlp_fan_info_t fan_info; + + if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); + return ONLP_STATUS_E_INTERNAL; + } + + /* Decision 1: Set fan as full speed if any fan is failed. + */ + if (fan_info.status & ONLP_FAN_STATUS_FAILED || !(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { + AIM_LOG_ERROR("Fan(%d) is not working, set the other fans as full speed\r\n", i); + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); + } + + /* Get fan direction (Only get the first one since all fan direction are the same) + */ + if (i == 1) { + if (fan_info.status & ONLP_FAN_STATUS_F2B) { + policy = fan_ctrl_policy_f2b; + arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_f2b); + } + else { + policy = fan_ctrl_policy_b2f; + arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_b2f); + } + } + } + + /* Get current fan speed + */ + fd = open(FAN_SPEED_CTRL_PATH, O_RDONLY); + if (fd == -1){ + AIM_LOG_ERROR("Unable to open fan speed control node (%s)", FAN_SPEED_CTRL_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + len = read(fd, buf, sizeof(buf)); + close(fd); + if (len <= 0) { + AIM_LOG_ERROR("Unable to read fan speed from (%s)", FAN_SPEED_CTRL_PATH); + return ONLP_STATUS_E_INTERNAL; + } + cur_duty_cycle = atoi(buf); + + + /* Decision 2: If no matched fan speed is found from the policy, + * use FAN_DUTY_CYCLE_MIN as default speed + */ + for (i = 0; i < arr_size; i++) { + if (policy[i].duty_cycle != cur_duty_cycle) + continue; + + break; + } + + if (i == arr_size) { + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), policy[0].duty_cycle); + } + + /* Get current temperature + */ + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(1), &thermal_1) != ONLP_STATUS_OK || + onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(2), &thermal_2) != ONLP_STATUS_OK || + onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(3), &thermal_3) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + temp = thermal_1.mcelsius + thermal_2.mcelsius + thermal_3.mcelsius; + + + /* Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + */ + new_duty_cycle = cur_duty_cycle; + + if ((temp >= policy[i].temp_up_adjust) && (i != (arr_size-1))) { + new_duty_cycle = policy[i+1].duty_cycle; + } + else if ((temp <= policy[i].temp_down_adjust) && (i != 0)) { + new_duty_cycle = policy[i-1].duty_cycle; + } + + if (new_duty_cycle == cur_duty_cycle) { + /* Duty cycle does not change, just return */ + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), new_duty_cycle); +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..4e707751 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,114 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" +#include + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +static char* devfiles__[] = /* must map with onlp_thermal_id */ +{ + "reserved", + "/sys/bus/i2c/devices/10-004b*temp1_input", + "/sys/bus/i2c/devices/12-0049*temp1_input", + "/sys/bus/i2c/devices/13-004a*temp1_input", + "/sys/bus/i2c/devices/3-0058*psu_temp1_input", + "/sys/bus/i2c/devices/4-005b*psu_temp1_input", +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "Chassis Thermal Sensor 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "Chassis Thermal Sensor 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id; + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[local_id]; + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]); +} diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_config.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_config.c new file mode 100755 index 00000000..99cd1a54 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(_x) #_x +#define __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(_x) __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(_x) +x86_64_accton_as7112_54x_config_settings_t x86_64_accton_as7112_54x_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_LOGGING(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_STDLIB(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE(X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_VALUE +#undef __X86_64_ACCTON_AS7112_54X_CONFIG_STRINGIFY_NAME + +const char* +x86_64_accton_as7112_54x_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as7112_54x_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as7112_54x_config_settings[i].name, setting)) { + return x86_64_accton_as7112_54x_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as7112_54x_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as7112_54x_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as7112_54x_config_settings[i].name, x86_64_accton_as7112_54x_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_enums.c new file mode 100755 index 00000000..3ca8adce --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_int.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_int.h new file mode 100755 index 00000000..bb3dde43 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as7112_54x Internal Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7112_54X_INT_H__ +#define __X86_64_ACCTON_AS7112_54X_INT_H__ + +#include + + +#endif /* __X86_64_ACCTON_AS7112_54X_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.c new file mode 100755 index 00000000..a0ff9d7b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.c @@ -0,0 +1,17 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7112_54x_log.h" +/* + * x86_64_accton_as7112_54x log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS7112_54X_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS7112_54X_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS7112_54X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.h b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.h new file mode 100755 index 00000000..bf2f3049 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7112_54X_LOG_H__ +#define __X86_64_ACCTON_AS7112_54X_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as7112_54x +#include + +#endif /* __X86_64_ACCTON_AS7112_54X_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_module.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_module.c new file mode 100755 index 00000000..3d73ab72 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7112_54x_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as7112_54x_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_as7112_54x_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_ucli.c new file mode 100755 index 00000000..3eda6e26 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/module/src/x86_64_accton_as7112_54x_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_ACCTON_AS7112_54X_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as7112_54x_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as7112_54x) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as7112_54x_ucli_module__ = + { + "x86_64_accton_as7112_54x_ucli", + NULL, + x86_64_accton_as7112_54x_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as7112_54x_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as7112_54x_ucli_module__); + n = ucli_node_create("x86_64_accton_as7112_54x", NULL, &x86_64_accton_as7112_54x_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as7112_54x")); + return n; +} + +#else +void* +x86_64_accton_as7112_54x_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/x86_64_accton_as7112_54x.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/x86_64_accton_as7112_54x.mk new file mode 100644 index 00000000..914ed9e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/onlp/builds/src/x86_64_accton_as7112_54x.mk @@ -0,0 +1,13 @@ + +############################################################################### +# +# Inclusive Makefile for the x86_64_accton_as7112_54x module. +# +# Autogenerated 2018-09-12 02:07:07.665347 +# +############################################################################### +x86_64_accton_as7112_54x_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(x86_64_accton_as7112_54x_BASEDIR)module/make.mk +include $(x86_64_accton_as7112_54x_BASEDIR)module/src/make.mk +include $(x86_64_accton_as7112_54x_BASEDIR)module/auto/make.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/PKG.yml new file mode 100755 index 00000000..8525b410 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as7112-54x REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/lib/x86-64-accton-as7112-54x-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/lib/x86-64-accton-as7112-54x-r0.yml new file mode 100755 index 00000000..b434332f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/lib/x86-64-accton-as7112-54x-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for AS7112 +# +###################################################################### + +x86-64-accton-as7112-54x-r0: + + grub: + + serial: >- + --port=0x2f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS1,115200n8 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/python/x86_64_accton_as7112_54x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/python/x86_64_accton_as7112_54x_r0/__init__.py new file mode 100755 index 00000000..fd0644fe --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7112-54x/platform-config/r0/src/python/x86_64_accton_as7112_54x_r0/__init__.py @@ -0,0 +1,68 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as7112_54x_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x25_6x100): + PLATFORM='x86-64-accton-as7112-54x-r0' + MODEL="AS7112-54X" + SYS_OBJECT_ID=".7112.54" + + def baseconfig(self): + self.insmod('optoe') + self.insmod('ym2651y') + for m in [ 'cpld', 'fan', 'psu', 'led' ]: + self.insmod("x86-64-accton-as7112-54x-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + self.new_i2c_devices([ + + ('pca9548', 0x70, 0), + ('pca9545', 0x71, 0), + ('pca9548', 0x72, 0), + ('as7112_54x_fan', 0x63, 0), + + # initiate psu + ('as7112_54x_psu1', 0x50, 3), + ('ym2401', 0x58, 3), + ('as7112_54x_psu2', 0x53, 4), + ('ym2401', 0x5b, 4), + + # initiate lm75 + ('lm75', 0x4b, 10), + ('lm75', 0x4c, 11), + ('lm75', 0x49, 12), + ('lm75', 0x4a, 13), + + # initiate cpld + ('as7112_54x_cpld1', 0x60, 1), + ('as7112_54x_cpld2', 0x61, 1), + ('as7112_54x_cpld3', 0x62, 1), + + + # initiate 9548 + ('pca9548', 0x70, 1), + ('pca9548', 0x71, 22), + ('pca9548', 0x72, 23), + ('pca9548', 0x73, 24), + ('pca9548', 0x74, 25), + ('pca9548', 0x75, 26), + ('pca9548', 0x76, 27), + + # System EEPROM + ('24c02', 0x57, 1), + ]) + + # initialize QSFP port 1~54 + for port in range(1, 49): + self.new_i2c_device('optoe2', 0x50, port-1+30) + + for port in range(49, 55): + self.new_i2c_device('optoe1', 0x50, port-49+14) + + for port in range(1, 49): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-1+30), shell=True) + + for port in range(49, 55): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-49+14), shell=True) + + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml index cc11bcf6..45051486 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml @@ -23,6 +23,8 @@ x86-64-accton-as7312-54x-r0: args: >- nopat console=ttyS1,115200n8 + i2c-ismt.bus_speed=100 + i2c-ismt.delay=100 ##network ## interfaces: diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml index d649eb5c..a1d10a4b 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml @@ -23,6 +23,8 @@ x86-64-accton-as7312-54xs-r0: args: >- nopat console=ttyS1,115200n8 + i2c-ismt.bus_speed=100 + i2c-ismt.delay=100 ##network ## interfaces: diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/.gitignore new file mode 100644 index 00000000..4b3c4900 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/.gitignore @@ -0,0 +1,2 @@ +*x86*64*accton*as7316*26xb*.mk +onlpdump.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/PKG.yml new file mode 100644 index 00000000..b5ffdb46 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as7316-26xb ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/Makefile new file mode 100644 index 00000000..651cefdc --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-as7316-26xb +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-fan.c new file mode 100644 index 00000000..ca804007 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-fan.c @@ -0,0 +1,457 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_fan" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_FAN_READ_CMD 0x14 +#define IPMI_FAN_WRITE_CMD 0x15 +#define IPMI_TIMEOUT (5 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf); +static int as7316_26xb_fan_probe(struct platform_device *pdev); +static int as7316_26xb_fan_remove(struct platform_device *pdev); + +enum fan_id { + FAN_1, + FAN_2, + FAN_3, + FAN_4, + FAN_5, + NUM_OF_FAN +}; + +enum fan_data_index { + FAN_PRESENT, + FAN_PWM, + FAN_SPEED0, + FAN_SPEED1, + FAN_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as7316_26xb_fan_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[20]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[3]; /* 0: FAN id, 1: 0x02, 2: PWM */ +}; + +struct as7316_26xb_fan_data *data = NULL; + +static struct platform_driver as7316_26xb_fan_driver = { + .probe = as7316_26xb_fan_probe, + .remove = as7316_26xb_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define FAN_PRESENT_ATTR_ID(index) FAN##index##_PRESENT +#define FAN_PWM_ATTR_ID(index) FAN##index##_PWM +#define FAN_RPM_ATTR_ID(index) FAN##index##_INPUT + +#define FAN_ATTR(fan_id) \ + FAN_PRESENT_ATTR_ID(fan_id), \ + FAN_PWM_ATTR_ID(fan_id), \ + FAN_RPM_ATTR_ID(fan_id) + +enum as7316_54x_fan_sysfs_attrs { + FAN_ATTR(1), + FAN_ATTR(2), + FAN_ATTR(3), + FAN_ATTR(4), + FAN_ATTR(5), + NUM_OF_FAN_ATTR, + NUM_OF_PER_FAN_ATTR = (NUM_OF_FAN_ATTR/NUM_OF_FAN) +}; + +/* fan attributes */ +#define DECLARE_FAN_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, show_fan, NULL, FAN##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, show_fan, set_fan, FAN##index##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, show_fan, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr + +DECLARE_FAN_SENSOR_DEVICE_ATTR(1); +DECLARE_FAN_SENSOR_DEVICE_ATTR(2); +DECLARE_FAN_SENSOR_DEVICE_ATTR(3); +DECLARE_FAN_SENSOR_DEVICE_ATTR(4); +DECLARE_FAN_SENSOR_DEVICE_ATTR(5); + +static struct attribute *as7316_26xb_fan_attributes[] = { + /* fan attributes */ + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_ATTR(4), + DECLARE_FAN_ATTR(5), + NULL +}; + +static const struct attribute_group as7316_26xb_fan_group = { + .attrs = as7316_26xb_fan_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as7316_26xb_fan_data *as7316_26xb_fan_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + struct as7316_26xb_fan_data *data = NULL; + int value = 0; + int index = 0; + int present = 0; + + data = as7316_26xb_fan_update_device(); + if (!data->valid) { + return -EIO; + } + + index = fid * FAN_DATA_COUNT; /* base index */ + present = !data->ipmi_resp[index + FAN_PRESENT]; + + switch (attr->index) { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + value = !data->ipmi_resp[index + FAN_PRESENT]; + break; + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + value = (data->ipmi_resp[index + FAN_PWM] + 1) * 625 / 100; + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", present ? value : 0); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long pwm; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + + status = kstrtol(buf, 10, &pwm); + if (status) { + return status; + } + + pwm = (pwm * 100) / 625 - 1; /* Convert pwm to register value */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = fid + 1; /* FAN ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x02; + data->ipmi_tx_data[2] = pwm; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm; + + return count; +} + +static int as7316_26xb_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as7316_26xb_fan_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as7316_26xb_fan_group); + + return 0; +} + +static int __init as7316_26xb_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as7316_26xb_fan_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_fan_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_fan_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB fan driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_fan_init); +module_exit(as7316_26xb_fan_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-led.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-led.c new file mode 100644 index 00000000..8b9e3fe1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-led.c @@ -0,0 +1,465 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_led" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_LED_READ_CMD 0x1A +#define IPMI_LED_WRITE_CMD 0x1B +#define IPMI_TIMEOUT (5 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_led(struct device *dev, struct device_attribute *attr, char *buf); +static int as7316_26xb_led_probe(struct platform_device *pdev); +static int as7316_26xb_led_remove(struct platform_device *pdev); + +enum led_data_index { + LOC_INDEX, + DIAG_RED_INDEX, + DIAG_GREEN_INDEX +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as7316_26xb_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[3]; /* 0: LOC LED, 1: DIAG Red LED, 2: DIAG Green LED */ + struct ipmi_data ipmi; +}; + +struct as7316_26xb_led_data *data = NULL; + +static struct platform_driver as7316_26xb_led_driver = { + .probe = as7316_26xb_led_probe, + .remove = as7316_26xb_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +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 +}; + +enum as7316_54x_led_sysfs_attrs { + LED_LOC, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN +}; + +static SENSOR_DEVICE_ATTR(led_loc, S_IWUSR | S_IRUGO, show_led, set_led, LED_LOC); +static SENSOR_DEVICE_ATTR(led_diag, S_IWUSR | S_IRUGO, show_led, set_led, LED_DIAG); +static SENSOR_DEVICE_ATTR(led_psu1, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IWUSR | S_IRUGO, show_led, set_led, LED_PSU2); +static SENSOR_DEVICE_ATTR(led_fan, S_IWUSR | S_IRUGO, show_led, set_led, LED_FAN); + +static struct attribute *as7316_26xb_led_attributes[] = { + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_diag.dev_attr.attr, + &sensor_dev_attr_led_psu1.dev_attr.attr, + &sensor_dev_attr_led_psu2.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7316_26xb_led_group = { + .attrs = as7316_26xb_led_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as7316_26xb_led_data *as7316_26xb_led_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_LED_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_led(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7316_26xb_led_data *data = NULL; + int value; + + data = as7316_26xb_led_update_device(); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case LED_LOC: + value = data->ipmi_resp[LOC_INDEX] ? LED_MODE_ORANGE_BLINKING : LED_MODE_OFF; + break; + case LED_DIAG: + { + if (data->ipmi_resp[DIAG_GREEN_INDEX] && data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (!data->ipmi_resp[DIAG_GREEN_INDEX] && !data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_OFF; + else if (data->ipmi_resp[DIAG_RED_INDEX]) + value = LED_MODE_ORANGE; + else if (data->ipmi_resp[DIAG_GREEN_INDEX] == 1) + value = LED_MODE_GREEN_BLINKING; + else + value = LED_MODE_GREEN; + break; + } + case LED_PSU1: + case LED_PSU2: + case LED_FAN: + value = LED_MODE_AUTO; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = kstrtol(buf, 10, &mode); + if (status) { + return status; + } + + data = as7316_26xb_led_update_device(); + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case LED_LOC: + data->ipmi_resp[LOC_INDEX] = !!mode; + break; + case LED_DIAG: + { + if (mode == LED_MODE_GREEN_BLINKING) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 1; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + else if (mode == LED_MODE_GREEN) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 2; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + else if (mode == LED_MODE_ORANGE) { + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 1; + } + else { /* OFF */ + data->ipmi_resp[DIAG_GREEN_INDEX] = 0; + data->ipmi_resp[DIAG_RED_INDEX] = 0; + } + + break; + } + default: + return -EINVAL; + } + + /* Send IPMI write command */ + status = ipmi_send_message(&data->ipmi, IPMI_LED_WRITE_CMD, + data->ipmi_resp, sizeof(data->ipmi_resp), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + return count; +} + +static int as7316_26xb_led_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as7316_26xb_led_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_led_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as7316_26xb_led_group); + + return 0; +} + +static int __init as7316_26xb_led_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_led_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as7316_26xb_led_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_led_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_led_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_led_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB led driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_led_init); +module_exit(as7316_26xb_led_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-psu.c new file mode 100644 index 00000000..a96a5da7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-psu.c @@ -0,0 +1,547 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_psu" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_PSU_READ_CMD 0x16 +#define IPMI_PSU_MODEL_NAME_CMD 0x10 +#define IPMI_PSU_SERIAL_NUM_CMD 0x11 +#define IPMI_TIMEOUT (5 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_psu(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *attr, char *buf); +static int as7316_26xb_psu_probe(struct platform_device *pdev); +static int as7316_26xb_psu_remove(struct platform_device *pdev); + +enum psu_id { + PSU_1, + PSU_2, + NUM_OF_PSU +}; + +enum psu_data_index { + PSU_PRESENT = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD_CPLD, + PSU_POWER_GOOD_PMBUS, + PSU_OVER_VOLTAGE, + PSU_OVER_CURRENT, + PSU_POWER_ON, + PSU_VIN0, + PSU_VIN1, + PSU_VOUT0, + PSU_VOUT1, + PSU_IOUT0, + PSU_IOUT1, + PSU_TEMP0, + PSU_TEMP1, + PSU_FAN0, + PSU_FAN1, + PSU_POUT0, + PSU_POUT1, + PSU_STATUS_COUNT, + PSU_MODEL = 0, + PSU_SERIAL = 0 +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct ipmi_psu_resp_data { + char status[19]; + char serial[20]; + char model[9]; +}; + +struct as7316_26xb_psu_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid[2]; /* != 0 if registers are valid, 0: PSU1, 1: PSU2 */ + unsigned long last_updated[2]; /* In jiffies, 0: PSU1, 1: PSU2 */ + struct ipmi_data ipmi; + struct ipmi_psu_resp_data ipmi_resp[2]; /* 0: PSU1, 1: PSU2 */ + unsigned char ipmi_tx_data[2]; +}; + +struct as7316_26xb_psu_data *data = NULL; + +static struct platform_driver as7316_26xb_psu_driver = { + .probe = as7316_26xb_psu_probe, + .remove = as7316_26xb_psu_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define PSU_PRESENT_ATTR_ID(index) PSU##index##_PRESENT +#define PSU_POWERGOOD_ATTR_ID(index) PSU##index##_POWER_GOOD +#define PSU_VIN_ATTR_ID(index) PSU##index##_VIN +#define PSU_VOUT_ATTR_ID(index) PSU##index##_VOUT +#define PSU_IOUT_ATTR_ID(index) PSU##index##_IOUT +#define PSU_POUT_ATTR_ID(index) PSU##index##_POUT +#define PSU_MODEL_ATTR_ID(index) PSU##index##_MODEL +#define PSU_SERIAL_ATTR_ID(index) PSU##index##_SERIAL +#define PSU_TEMP_INPUT_ATTR_ID(index) PSU##index##_TEMP_INPUT +#define PSU_FAN_INPUT_ATTR_ID(index) PSU##index##_FAN_INPUT + +#define PSU_ATTR(psu_id) \ + PSU_PRESENT_ATTR_ID(psu_id), \ + PSU_POWERGOOD_ATTR_ID(psu_id), \ + PSU_VIN_ATTR_ID(psu_id), \ + PSU_VOUT_ATTR_ID(psu_id), \ + PSU_IOUT_ATTR_ID(psu_id), \ + PSU_POUT_ATTR_ID(psu_id), \ + PSU_MODEL_ATTR_ID(psu_id), \ + PSU_SERIAL_ATTR_ID(psu_id), \ + PSU_TEMP_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_INPUT_ATTR_ID(psu_id) + +enum as7316_54x_psu_sysfs_attrs { + /* psu attributes */ + PSU_ATTR(1), + PSU_ATTR(2), + NUM_OF_PSU_ATTR, + NUM_OF_PER_PSU_ATTR = (NUM_OF_PSU_ATTR/NUM_OF_PSU) +}; + +/* psu attributes */ +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, PSU##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL, PSU##index##_POWER_GOOD); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin, S_IRUGO, show_psu, NULL, PSU##index##_VIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_psu, NULL, PSU##index##_VOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_psu, NULL, PSU##index##_IOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_psu, NULL, PSU##index##_POUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, PSU##index##_MODEL); \ + static SENSOR_DEVICE_ATTR(psu##index##_serial, S_IRUGO, show_string, NULL, PSU##index##_SERIAL);\ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input, S_IRUGO, show_psu, NULL, PSU##index##_TEMP_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan1_input, S_IRUGO, show_psu, NULL, PSU##index##_FAN_INPUT) +#define DECLARE_PSU_ATTR(index) \ + &sensor_dev_attr_psu##index##_present.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_power_good.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_model.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_serial.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_temp1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan1_input.dev_attr.attr + +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); + +static struct attribute *as7316_26xb_psu_attributes[] = { + /* psu attributes */ + DECLARE_PSU_ATTR(1), + DECLARE_PSU_ATTR(2), + NULL +}; + +static const struct attribute_group as7316_26xb_psu_group = { + .attrs = as7316_26xb_psu_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as7316_26xb_psu_data *as7316_26xb_psu_update_device(struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int status = 0; + + if (time_before(jiffies, data->last_updated[pid] + HZ * 5) && data->valid[pid]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->valid[pid] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */ + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 1, + data->ipmi_resp[pid].status, sizeof(data->ipmi_resp[pid].status)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get model name from ipmi */ + data->ipmi_tx_data[1] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].model, sizeof(data->ipmi_resp[pid].model) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get serial number from ipmi */ + data->ipmi_tx_data[1] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].serial, sizeof(data->ipmi_resp[pid].serial) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated[pid] = jiffies; + data->valid[pid] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +#define VALIDATE_PRESENT_RETURN(id) \ +{ \ + if (data->ipmi_resp[id].status[PSU_PRESENT] != 0) { \ + return -ENXIO; \ + } \ +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + struct as7316_26xb_psu_data *data = NULL; + int value = 0; + + data = as7316_26xb_psu_update_device(da); + if (!data->valid[pid]) { + return -EIO; + } + + switch (attr->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + value = !(data->ipmi_resp[pid].status[PSU_PRESENT]); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + VALIDATE_PRESENT_RETURN(pid); + value = data->ipmi_resp[pid].status[PSU_POWER_GOOD_CPLD]; + break; + case PSU1_VIN: + case PSU2_VIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_VIN0] | + (int)data->ipmi_resp[pid].status[PSU_VIN1] << 8) * 1000; + break; + case PSU1_VOUT: + case PSU2_VOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_VOUT0] | + (int)data->ipmi_resp[pid].status[PSU_VOUT1] << 8) * 1000; + break; + case PSU1_IOUT: + case PSU2_IOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_IOUT0] | + (int)data->ipmi_resp[pid].status[PSU_IOUT1] << 8) * 1000; + break; + case PSU1_POUT: + case PSU2_POUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_POUT0] | + (int)data->ipmi_resp[pid].status[PSU_POUT1] << 8) * 1000; + break; + case PSU1_TEMP_INPUT: + case PSU2_TEMP_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((int)data->ipmi_resp[pid].status[PSU_TEMP0] | + (int)data->ipmi_resp[pid].status[PSU_TEMP1] << 8) * 1000; + break; + case PSU1_FAN_INPUT: + case PSU2_FAN_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = (((unsigned char)data->ipmi_resp[pid].status[PSU_FAN0]) | + ((unsigned char)data->ipmi_resp[pid].status[PSU_FAN1]) << 8); + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + struct as7316_26xb_psu_data *data; + char *str = NULL; + + data = as7316_26xb_psu_update_device(da); + if (!data->valid[pid]) { + return -EIO; + } + + switch (attr->index) { + case PSU1_MODEL: + case PSU2_MODEL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].model; + break; + case PSU1_SERIAL: + case PSU2_SERIAL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].serial; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", str); +} + +static int as7316_26xb_psu_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as7316_26xb_psu_group); + if (status) { + goto exit; + } + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_psu_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as7316_26xb_psu_group); + return 0; +} + +static int __init as7316_26xb_psu_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_psu_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as7316_26xb_psu_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_psu_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_psu_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_psu_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB PSU driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_psu_init); +module_exit(as7316_26xb_psu_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sfp.c new file mode 100644 index 00000000..8d30fef3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sfp.c @@ -0,0 +1,1169 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_sfp" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_QSFP_READ_CMD 0x10 +#define IPMI_QSFP_WRITE_CMD 0x11 +#define IPMI_SFP_READ_CMD 0x1C +#define IPMI_SFP_WRITE_CMD 0x1D +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +#define NUM_OF_SFP 24 +#define NUM_OF_QSFP 2 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_sfp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_sfp_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_qsfp_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static int as7316_26xb_sfp_probe(struct platform_device *pdev); +static int as7316_26xb_sfp_remove(struct platform_device *pdev); +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf); +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_present(void); +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_txdisable(void); +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_txfault(void); +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_rxlos(void); +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_present(void); +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_txdisable(void); +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_reset(void); +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_eeprom(int port); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +enum module_status { + SFP_PRESENT = 0, + SFP_TXDISABLE, + SFP_TXFAULT, + SFP_RXLOS, + NUM_OF_SFP_STATUS, + + QSFP_PRESENT = 0, + QSFP_TXDISABLE, + QSFP_RESET, + NUM_OF_QSFP_STATUS, + + PRESENT_ALL = 0, + RXLOS_ALL +}; + +struct ipmi_sfp_resp_data { + unsigned char eeprom[EEPROM_SIZE]; + char eeprom_valid; + + char sfp_valid[NUM_OF_SFP_STATUS]; /* != 0 if registers are valid */ + unsigned long sfp_last_updated[NUM_OF_SFP_STATUS]; /* In jiffies */ + unsigned char sfp_resp[NUM_OF_SFP_STATUS][NUM_OF_SFP]; /* 0: present, 1: tx-disable + 2: tx-fault, 3: rx-los */ + char qsfp_valid[NUM_OF_QSFP_STATUS]; /* != 0 if registers are valid */ + unsigned long qsfp_last_updated[NUM_OF_SFP_STATUS]; /* In jiffies */ + unsigned char qsfp_resp[NUM_OF_QSFP_STATUS][NUM_OF_QSFP]; /* 0: present, 1: tx-disable, 2: reset */ +}; + +struct as7316_26xb_sfp_data { + struct platform_device *pdev; + struct mutex update_lock; + struct ipmi_data ipmi; + struct ipmi_sfp_resp_data ipmi_resp; + unsigned char ipmi_tx_data[3]; +}; + +struct as7316_26xb_sfp_data *data = NULL; + +static struct platform_driver as7316_26xb_sfp_driver = { + .probe = as7316_26xb_sfp_probe, + .remove = as7316_26xb_sfp_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define SFP_PRESENT_ATTR_ID(port) SFP##port##_PRESENT +#define SFP_TXDISABLE_ATTR_ID(port) SFP##port##_TXDISABLE +#define SFP_TXFAULT_ATTR_ID(port) SFP##port##_TXFAULT +#define SFP_RXLOS_ATTR_ID(port) SFP##port##_RXLOS +#define SFP_EEPROM_ATTR_ID(port) SFP##port##_EEPROM + +#define SFP_ATTR(port) \ + SFP_PRESENT_ATTR_ID(port), \ + SFP_TXDISABLE_ATTR_ID(port), \ + SFP_TXFAULT_ATTR_ID(port), \ + SFP_RXLOS_ATTR_ID(port), \ + SFP_EEPROM_ATTR_ID(port) + +#define QSFP_PRESENT_ATTR_ID(port) QSFP##port##_PRESENT +#define QSFP_TXDISABLE_ATTR_ID(port) QSFP##port##_TXDISABLE +#define QSFP_RESET_ATTR_ID(port) QSFP##port##_RESET +#define QSFP_EEPROM_ATTR_ID(port) QSFP##port##_EEPROM + +#define QSFP_ATTR(port) \ + QSFP_PRESENT_ATTR_ID(port), \ + QSFP_TXDISABLE_ATTR_ID(port), \ + QSFP_RESET_ATTR_ID(port), \ + QSFP_EEPROM_ATTR_ID(port) + +enum as7316_54x_sfp_sysfs_attrs { + SFP_ATTR(1), + SFP_ATTR(2), + SFP_ATTR(3), + SFP_ATTR(4), + SFP_ATTR(5), + SFP_ATTR(6), + SFP_ATTR(7), + SFP_ATTR(8), + SFP_ATTR(9), + SFP_ATTR(10), + SFP_ATTR(11), + SFP_ATTR(12), + SFP_ATTR(13), + SFP_ATTR(14), + SFP_ATTR(15), + SFP_ATTR(16), + SFP_ATTR(17), + SFP_ATTR(18), + SFP_ATTR(19), + SFP_ATTR(20), + SFP_ATTR(21), + SFP_ATTR(22), + SFP_ATTR(23), + SFP_ATTR(24), + NUM_OF_SFP_ATTR, + NUM_OF_PER_SFP_ATTR = (NUM_OF_SFP_ATTR/NUM_OF_SFP), +}; + +enum as7316_54x_qsfp_sysfs_attrs { + QSFP_ATTR(25), + QSFP_ATTR(26), + NUM_OF_QSFP_ATTR, + NUM_OF_PER_QSFP_ATTR = (NUM_OF_QSFP_ATTR/NUM_OF_QSFP), +}; + +/* sfp attributes */ +#define DECLARE_SFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_sfp, NULL, SFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_sfp, set_sfp, SFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##port, S_IRUGO, show_sfp, NULL, SFP##port##_TXFAULT); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##port, S_IRUGO, show_sfp, NULL, SFP##port##_RXLOS); \ + static SENSOR_DEVICE_ATTR(module_eeprom_##port, S_IRUGO, show_sfp_eeprom, NULL, SFP##port##_EEPROM) +#define DECLARE_SFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##port.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##port.dev_attr.attr, \ + &sensor_dev_attr_module_eeprom_##port.dev_attr.attr + +/* qsfp attributes */ +#define DECLARE_QSFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_qsfp, NULL, QSFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_txdisable, QSFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_reset_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_reset, QSFP##port##_RESET); \ + static SENSOR_DEVICE_ATTR(module_eeprom_##port, S_IRUGO, show_qsfp_eeprom, NULL, QSFP##port##_EEPROM) +#define DECLARE_QSFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##port.dev_attr.attr, \ + &sensor_dev_attr_module_eeprom_##port.dev_attr.attr + +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_all, NULL, PRESENT_ALL); \ +static SENSOR_DEVICE_ATTR(module_rxlos_all, S_IRUGO, show_all, NULL, RXLOS_ALL); \ + +DECLARE_SFP_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_SENSOR_DEVICE_ATTR(24); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(25); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(26); + +static struct attribute *as7316_26xb_sfp_attributes[] = { + /* sfp attributes */ + DECLARE_SFP_ATTR(1), + DECLARE_SFP_ATTR(2), + DECLARE_SFP_ATTR(3), + DECLARE_SFP_ATTR(4), + DECLARE_SFP_ATTR(5), + DECLARE_SFP_ATTR(6), + DECLARE_SFP_ATTR(7), + DECLARE_SFP_ATTR(8), + DECLARE_SFP_ATTR(9), + DECLARE_SFP_ATTR(10), + DECLARE_SFP_ATTR(11), + DECLARE_SFP_ATTR(12), + DECLARE_SFP_ATTR(13), + DECLARE_SFP_ATTR(14), + DECLARE_SFP_ATTR(15), + DECLARE_SFP_ATTR(16), + DECLARE_SFP_ATTR(17), + DECLARE_SFP_ATTR(18), + DECLARE_SFP_ATTR(19), + DECLARE_SFP_ATTR(20), + DECLARE_SFP_ATTR(21), + DECLARE_SFP_ATTR(22), + DECLARE_SFP_ATTR(23), + DECLARE_SFP_ATTR(24), + DECLARE_QSFP_ATTR(25), + DECLARE_QSFP_ATTR(26), + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rxlos_all.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7316_26xb_sfp_group = { + .attrs = as7316_26xb_sfp_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_PRESENT] + HZ) && + data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_PRESENT], + sizeof(data->ipmi_resp.sfp_resp[SFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_PRESENT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXDISABLE], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_txfault(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXFAULT], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXFAULT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_rxlos(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_RXLOS] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x13; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_RXLOS], + sizeof(data->ipmi_resp.sfp_resp[SFP_RXLOS])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_RXLOS] = jiffies; + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] + HZ) && + data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_PRESENT], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_qsfp_update_reset(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_RESET] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return data; + } + + mutex_lock(&data->update_lock); + + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_RESET], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_RESET])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_RESET] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct as7316_26xb_sfp_data *as7316_26xb_sfp_update_eeprom(int port) +{ + int status = 0, i = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_READ_CMD : IPMI_QSFP_READ_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + + mutex_lock(&data->update_lock); + + data->ipmi_resp.eeprom_valid = 0; + + for (i = 0; i <= 1; i++) { + data->ipmi_tx_data[0] = ipmi_port_id; + data->ipmi_tx_data[1] = i; /* 0: Get eeprom byte (0~127) from ipmi + 1: Get eeprom byte (128~255) from ipmi */ + status = ipmi_send_message(&data->ipmi, cmd, data->ipmi_tx_data, 2, + data->ipmi_resp.eeprom + i*128, 128); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + } + + data->ipmi_resp.eeprom_valid = 1; + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7316_26xb_sfp_data *data = NULL; + u32 values = 0; + int i; + + switch (attr->index) { + case PRESENT_ALL: + { + data = as7316_26xb_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return -EIO; + } + + data = as7316_26xb_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + /* Update qsfp present status */ + for (i = (NUM_OF_QSFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.qsfp_resp[QSFP_PRESENT][i] & 0x1); + } + + /* Update sfp present status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.sfp_resp[SFP_PRESENT][i] & 0x1); + } + + /* Return values 1 -> 26 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + 0xFF & values, + 0xFF & (values >> 8), + 0xFF & (values >> 16), + 0x3 & (values >> 24)); + } + case RXLOS_ALL: + { + data = as7316_26xb_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return -EIO; + } + + /* Update sfp rxlos status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= !(data->ipmi_resp.sfp_resp[SFP_RXLOS][i] & 0x1); + } + + /* Return values 1 -> 26 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", + 0xFF & values, + 0xFF & (values >> 8), + 0xFF & (values >> 16)); + } + default: + break; + } + + return 0; +} + +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + struct as7316_26xb_sfp_data *data = NULL; + int value = 0; + + switch (attr->index) { + case SFP1_PRESENT: + case SFP2_PRESENT: + case SFP3_PRESENT: + case SFP4_PRESENT: + case SFP5_PRESENT: + case SFP6_PRESENT: + case SFP7_PRESENT: + case SFP8_PRESENT: + case SFP9_PRESENT: + case SFP10_PRESENT: + case SFP11_PRESENT: + case SFP12_PRESENT: + case SFP13_PRESENT: + case SFP14_PRESENT: + case SFP15_PRESENT: + case SFP16_PRESENT: + case SFP17_PRESENT: + case SFP18_PRESENT: + case SFP19_PRESENT: + case SFP20_PRESENT: + case SFP21_PRESENT: + case SFP22_PRESENT: + case SFP23_PRESENT: + case SFP24_PRESENT: + { + data = as7316_26xb_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return -EIO; + } + + value = data->ipmi_resp.sfp_resp[SFP_PRESENT][pid]; + break; + } + case SFP1_TXDISABLE: + case SFP2_TXDISABLE: + case SFP3_TXDISABLE: + case SFP4_TXDISABLE: + case SFP5_TXDISABLE: + case SFP6_TXDISABLE: + case SFP7_TXDISABLE: + case SFP8_TXDISABLE: + case SFP9_TXDISABLE: + case SFP10_TXDISABLE: + case SFP11_TXDISABLE: + case SFP12_TXDISABLE: + case SFP13_TXDISABLE: + case SFP14_TXDISABLE: + case SFP15_TXDISABLE: + case SFP16_TXDISABLE: + case SFP17_TXDISABLE: + case SFP18_TXDISABLE: + case SFP19_TXDISABLE: + case SFP20_TXDISABLE: + case SFP21_TXDISABLE: + case SFP22_TXDISABLE: + case SFP23_TXDISABLE: + case SFP24_TXDISABLE: + { + data = as7316_26xb_sfp_update_txdisable(); + if (!data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return -EIO; + } + + value = !data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid]; + break; + } + case SFP1_TXFAULT: + case SFP2_TXFAULT: + case SFP3_TXFAULT: + case SFP4_TXFAULT: + case SFP5_TXFAULT: + case SFP6_TXFAULT: + case SFP7_TXFAULT: + case SFP8_TXFAULT: + case SFP9_TXFAULT: + case SFP10_TXFAULT: + case SFP11_TXFAULT: + case SFP12_TXFAULT: + case SFP13_TXFAULT: + case SFP14_TXFAULT: + case SFP15_TXFAULT: + case SFP16_TXFAULT: + case SFP17_TXFAULT: + case SFP18_TXFAULT: + case SFP19_TXFAULT: + case SFP20_TXFAULT: + case SFP21_TXFAULT: + case SFP22_TXFAULT: + case SFP23_TXFAULT: + case SFP24_TXFAULT: + { + data = as7316_26xb_sfp_update_txfault(); + if (!data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return -EIO; + } + + value = data->ipmi_resp.sfp_resp[SFP_TXFAULT][pid]; + break; + } + case SFP1_RXLOS: + case SFP2_RXLOS: + case SFP3_RXLOS: + case SFP4_RXLOS: + case SFP5_RXLOS: + case SFP6_RXLOS: + case SFP7_RXLOS: + case SFP8_RXLOS: + case SFP9_RXLOS: + case SFP10_RXLOS: + case SFP11_RXLOS: + case SFP12_RXLOS: + case SFP13_RXLOS: + case SFP14_RXLOS: + case SFP15_RXLOS: + case SFP16_RXLOS: + case SFP17_RXLOS: + case SFP18_RXLOS: + case SFP19_RXLOS: + case SFP20_RXLOS: + case SFP21_RXLOS: + case SFP22_RXLOS: + case SFP23_RXLOS: + case SFP24_RXLOS: + { + data = as7316_26xb_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return -EIO; + } + + value = !data->ipmi_resp.sfp_resp[SFP_RXLOS][pid]; + break; + } + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t show_sfp_eeprom(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + struct as7316_26xb_sfp_data *data = NULL; + + data = as7316_26xb_sfp_update_eeprom(pid + 1); + if (!data->ipmi_resp.eeprom_valid) { + return -EIO; + } + + memcpy(buf, data->ipmi_resp.eeprom, sizeof(data->ipmi_resp.eeprom)); + return sizeof(data->ipmi_resp.eeprom); +} + +static ssize_t set_sfp(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); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + disable = !disable; /* the IPMI cmd is 0 for tx-disable and 1 for tx-enable */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* FAN ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid] = disable; + + return count; +} + +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + struct as7316_26xb_sfp_data *data = NULL; + int value = 0; + + switch (attr->index) { + case QSFP25_PRESENT: + case QSFP26_PRESENT: + { + data = as7316_26xb_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]; + break; + } + case QSFP25_TXDISABLE: + case QSFP26_TXDISABLE: + { + data = as7316_26xb_qsfp_update_txdisable(); + if (!data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return -EIO; + } + + value = !!data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid]; + break; + } + case QSFP25_RESET: + case QSFP26_RESET: + { + data = as7316_26xb_qsfp_update_reset(); + if (!data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return -EIO; + } + + value = !data->ipmi_resp.qsfp_resp[QSFP_RESET][pid]; + break; + } + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t set_qsfp_txdisable(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); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + struct as7316_26xb_sfp_data *data = NULL; + + data = as7316_26xb_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return -EIO; + } + + if (!data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]) { + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* FAN ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable ? 0xf : 0; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid] = disable; + + return count; +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + reset = !reset; /* the IPMI cmd is 0 for reset and 1 for out of reset */ + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* FAN ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x11; + data->ipmi_tx_data[2] = reset; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + return status; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + return -EIO; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_RESET][pid] = reset; + + return count; +} + +static ssize_t show_qsfp_eeprom(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + struct as7316_26xb_sfp_data *data = NULL; + + data = as7316_26xb_sfp_update_eeprom(pid + 1 + NUM_OF_SFP); + if (!data->ipmi_resp.eeprom_valid) { + return -EIO; + } + + memcpy(buf, data->ipmi_resp.eeprom, sizeof(data->ipmi_resp.eeprom)); + return sizeof(data->ipmi_resp.eeprom); +} + +static int as7316_26xb_sfp_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as7316_26xb_sfp_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_sfp_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as7316_26xb_sfp_group); + return 0; +} + +static int __init as7316_26xb_sfp_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_sfp_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as7316_26xb_sfp_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_sfp_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_sfp_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_sfp_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_sfp_init); +module_exit(as7316_26xb_sfp_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sys.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sys.c new file mode 100644 index 00000000..aa5fef32 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-sys.c @@ -0,0 +1,368 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_sys" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_SYSEEPROM_READ_CMD 0x18 +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_NAME "eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static int as7316_26xb_sys_probe(struct platform_device *pdev); +static int as7316_26xb_sys_remove(struct platform_device *pdev); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as7316_26xb_sys_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[256]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[2]; + struct bin_attribute eeprom; /* eeprom data */ +}; + +struct as7316_26xb_sys_data *data = NULL; + +static struct platform_driver as7316_26xb_sys_driver = { + .probe = as7316_26xb_sys_probe, + .remove = as7316_26xb_sys_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) +{ + int status = 0; + + if ((off + count) > EEPROM_SIZE) { + return -EINVAL; + } + + data->ipmi_tx_data[0] = off; + data->ipmi_tx_data[1] = (count >= IPMI_READ_MAX_LEN) ? IPMI_READ_MAX_LEN : count; + data->ipmi.rx_msg_data = data->ipmi_resp + off; + data->ipmi.rx_msg_len = data->ipmi_tx_data[1]; + + status = ipmi_send_message(&data->ipmi, IPMI_SYSEEPROM_READ_CMD, data->ipmi_tx_data, sizeof(data->ipmi_tx_data), + data->ipmi_resp + off, data->ipmi_tx_data[1]); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = data->ipmi_tx_data[1]; + memcpy(buf, data->ipmi_resp + off, data->ipmi_tx_data[1]); + +exit: + return status; +} + +static ssize_t sysfs_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + 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 + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sys_eeprom_read(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 int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IRUGO; + eeprom->read = sysfs_bin_read; + eeprom->write = NULL; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + return sysfs_create_bin_file(kobj, eeprom); +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static int as7316_26xb_sys_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_sys_remove(struct platform_device *pdev) +{ + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom); + + return 0; +} + +static int __init as7316_26xb_sys_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_sys_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as7316_26xb_sys_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_sys_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_sys_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_sys_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB System driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_sys_init); +module_exit(as7316_26xb_sys_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-thermal.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-thermal.c new file mode 100644 index 00000000..2fd8fded --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/modules/builds/x86-64-accton-as7316-26xb-thermal.c @@ -0,0 +1,358 @@ +/* + * 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 as7316_54x CPLD1/CPLD2 + * + * 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 +#include + +#define DRVNAME "as7316_26xb_thermal" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_THERMAL_READ_CMD 0x12 +#define IPMI_TIMEOUT (5 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf); +static int as7316_26xb_thermal_probe(struct platform_device *pdev); +static int as7316_26xb_thermal_remove(struct platform_device *pdev); + +enum temp_data_index { + TEMP_ADDR, + TEMP_FAULT, + TEMP_INPUT, + TEMP_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as7316_26xb_thermal_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + char ipmi_resp[18]; + struct ipmi_data ipmi; +}; + +struct as7316_26xb_thermal_data *data = NULL; + +static struct platform_driver as7316_26xb_thermal_driver = { + .probe = as7316_26xb_thermal_probe, + .remove = as7316_26xb_thermal_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as7316_54x_thermal_sysfs_attrs { + TEMP1_INPUT, + TEMP2_INPUT, + TEMP3_INPUT, + TEMP4_INPUT, + TEMP5_INPUT, + TEMP6_INPUT +}; + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, TEMP4_INPUT); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, TEMP5_INPUT); +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, TEMP6_INPUT); + +static struct attribute *as7316_26xb_thermal_attributes[] = { + &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, + NULL +}; + +static const struct attribute_group as7316_26xb_thermal_group = { + .attrs = as7316_26xb_thermal_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = 0; + int index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 5) || !data->valid) { + data->valid = 0; + + status = ipmi_send_message(&data->ipmi, IPMI_THERMAL_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + /* Get temp fault status */ + index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT; + if (unlikely(data->ipmi_resp[index] == 0)) { + status = -EIO; + goto exit; + } + + /* Get temperature in degree celsius */ + index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT; + status = data->ipmi_resp[index] * 1000; + + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7316_26xb_thermal_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as7316_26xb_thermal_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as7316_26xb_thermal_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as7316_26xb_thermal_group); + + return 0; +} + +static int __init as7316_26xb_thermal_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as7316_26xb_thermal_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as7316_26xb_thermal_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as7316_26xb_thermal_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as7316_26xb_thermal_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as7316_26xb_thermal_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7316 26XB Thermal driver"); +MODULE_LICENSE("GPL"); + +module_init(as7316_26xb_thermal_init); +module_exit(as7316_26xb_thermal_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/PKG.yml new file mode 100644 index 00000000..6145f512 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as7316-26xb ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/lib/Makefile new file mode 100644 index 00000000..175beb76 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-as7316-26xb +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_as7316_26xb onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-as7316-26xb.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..40787128 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_as7316_26xb onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.gitignore new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.gitignore @@ -0,0 +1 @@ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.module new file mode 100644 index 00000000..713c25bb --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_as7316_26xb diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/Makefile new file mode 100644 index 00000000..67994555 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as7316_26xb +AUTOMODULE := x86_64_accton_as7316_26xb +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/README new file mode 100644 index 00000000..fe2480a8 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as7316_26xb README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..39491a06 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_as7316_54x Autogeneration +# +############################################################################### +x86_64_accton_as7316_54x_AUTO_DEFS := module/auto/x86_64_accton_as7316_54x.yml +x86_64_accton_as7316_54x_AUTO_DIRS := module/inc/x86_64_accton_as7316_54x module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/x86_64_accton_as7316_26xb.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/x86_64_accton_as7316_26xb.yml new file mode 100644 index 00000000..cec22856 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/auto/x86_64_accton_as7316_26xb.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as7316_26xb Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_ACCTON_AS7316_26xb_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as7316_26xb_config + + portingmacro: + x86_64_accton_as7316_26xb: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb.x b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb.x new file mode 100644 index 00000000..db908fd6 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_config.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_config.h new file mode 100644 index 00000000..8ba4dd97 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7316_26xb Configuration Header + * + * @addtogroup x86_64_accton_as7316_26xb-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7316_26XB_CONFIG_H__ +#define __X86_64_ACCTON_AS7316_26XB_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as7316_26xb_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as7316_26xb_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as7316_26xb_config_settings table. */ +extern x86_64_accton_as7316_26xb_config_settings_t x86_64_accton_as7316_26xb_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as7316_26xb_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as7316_26xb_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as7316_26xb_porting.h" + +#endif /* __X86_64_ACCTON_AS7316_26XB_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_dox.h new file mode 100644 index 00000000..404cc800 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as7316_26xb Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7316_26XB_DOX_H__ +#define __X86_64_ACCTON_AS7316_26XB_DOX_H__ + +/** + * @defgroup x86_64_accton_as7316_26xb x86_64_accton_as7316_26xb - x86_64_accton_as7316_26xb Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as7316_26xb-x86_64_accton_as7316_26xb Public Interface + * @defgroup x86_64_accton_as7316_26xb-config Compile Time Configuration + * @defgroup x86_64_accton_as7316_26xb-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS7316_26XB_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_porting.h new file mode 100644 index 00000000..331e1693 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/inc/x86_64_accton_as7316_26xb/x86_64_accton_as7316_26xb_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7316_26xb Porting Macros. + * + * @addtogroup x86_64_accton_as7316_26xb-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS7316_26XB_PORTING_H__ +#define __X86_64_ACCTON_AS7316_26XB_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS7316_26XB_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS7316_26XB_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS7316_26XB_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_FREE free + #else + #error The macro X86_64_ACCTON_AS7316_26XB_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS7316_26XB_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS7316_26XB_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS7316_26XB_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS7316_26XB_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_ACCTON_AS7316_26XB_STRNCPY GLOBAL_STRNCPY + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_STRNCPY strncpy + #else + #error The macro X86_64_ACCTON_AS7316_26XB_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS7316_26XB_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS7316_26XB_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS7316_26XB_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS7316_26XB_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7316_26XB_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS7316_26XB_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7316_26XB_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS7316_26XB_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS7316_26XB_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..ea3e92a2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as7316_26xb_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as7316_26xb_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as7316_26xb_DEPENDMODULE_ENTRIES := init:x86_64_accton_as7316_26xb ucli:x86_64_accton_as7316_26xb + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..0c183113 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as7316_26xb_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..bcd6b60e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/fani.c @@ -0,0 +1,232 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define MAX_FAN_SPEED 25500 +#define MAX_PSU_FAN_SPEED 25500 + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +#define PSU_FAN_INFO(pid, fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5), + PSU_FAN_INFO(1, 1), + PSU_FAN_INFO(2, 1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + + /* get fan present status + */ + ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; /* fan is not present */ + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""fan%d_input", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + return ONLP_STATUS_OK; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int value, ret; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", PSU_SYSFS_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED; + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int fid; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) + { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + if (fid < FAN_1_ON_FAN_BOARD || fid > FAN_5_ON_FAN_BOARD) { + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, "%s""fan%d_pwm", FAN_BOARD_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to write data to file %s""fan%d_pwm", FAN_BOARD_PATH, fid); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..73af2b35 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,248 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define LED_FORMAT "/sys/devices/platform/as7316_26xb_led/%s" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_LOC, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN, +}; + +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 +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_ORANGE_BLINKING, ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_GREEN_BLINKING, ONLP_LED_MODE_GREEN_BLINKING}, +{LED_DIAG, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE}, +{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} +}; + +static char *leds[] = /* must map with onlp_led_id */ +{ + NULL, + "led_loc", + "led_diag", + "led_psu1", + "led_psu2", + "led_fan" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 5 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + /* + * Turn off the LOCATION and DIAG LEDs at startup + */ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF); + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_LOC), ONLP_LED_MODE_OFF); + + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int lid, value; + + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Get LED mode */ + if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) { + DEBUG_PRINT("Unable to read status from file "LED_FORMAT, leds[lid]); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(lid, value); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int lid; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), LED_FORMAT, leds[lid]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..ac1b2da4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as7316_26xb +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..3df87934 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,70 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_accton_as7316_26xb_log.h" + +#define CHASSIS_FAN_COUNT 5 +#define CHASSIS_THERMAL_COUNT 7 +#define CHASSIS_LED_COUNT 5 +#define CHASSIS_PSU_COUNT 2 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_SYSFS_PATH "/sys/devices/platform/as7316_26xb_psu/" + +#define FAN_BOARD_PATH "/sys/devices/platform/as7316_26xb_fan/" +#define FAN_NODE(node) FAN_BOARD_PATH#node + +#define IDPROM_PATH "/sys/devices/platform/as7316_26xb_sys/eeprom" + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_6_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..15c2c7f6 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/psui.c @@ -0,0 +1,171 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +static int +get_DCorAC_cap(char *model) +{ + const char *dc_models[] = {"YM-2401U", "um400d", NULL }; + int i; + + i = 0; + while(dc_models[i]) { + if (!strncasecmp(model, dc_models[i], strlen(dc_models[i]))){ + return ONLP_PSU_CAPS_DC12; + } + i++; + } + return ONLP_PSU_CAPS_AC; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int pid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[pid]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + ret = onlp_file_read_int(&val, "%s""psu%d_present", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_present)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + ret = onlp_file_read_int(&val, "%s""psu%d_power_good", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_power_good)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Read voltage, current and power */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vin", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_iout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_pout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + /* Set the associated oid_table */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(pid + CHASSIS_FAN_COUNT); + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_temp1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(pid + CHASSIS_THERMAL_COUNT); + } + + /* Read model */ + char *string = NULL; + int len = onlp_file_read_str(&string, "%s""psu%d_model", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->model, string, len); + aim_free(string); + info->caps |= get_DCorAC_cap (info->model); + } + + /* Read serial */ + len = onlp_file_read_str(&string, "%s""psu%d_serial", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->serial, string, len); + aim_free(string); + } + + return ret; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..65d7f766 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,287 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_as7316_26xb_int.h" +#include "x86_64_accton_as7316_26xb_log.h" + +#define PORT_EEPROM_FORMAT "/sys/devices/platform/as7316_26xb_sfp/module_eeprom_%d" +#define MODULE_PRESENT_FORMAT "/sys/devices/platform/as7316_26xb_sfp/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/devices/platform/as7316_26xb_sfp/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/devices/platform/as7316_26xb_sfp/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/devices/platform/as7316_26xb_sfp/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/devices/platform/as7316_26xb_sfp/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/devices/platform/as7316_26xb_sfp/module_rxlos_all" + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 54} + */ + int p; + + for(p = 0; p < 26; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[4]; + FILE* fp; + + /* Read present status of port 0~25 */ + int count = 0; + + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file from (%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x", bytes+0, bytes+1, bytes+2, bytes+3); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file from(%s).", MODULE_PRESENT_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant QSFP ports */ + bytes[3] &= 0x3; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[3]; + FILE* fp; + + /* Read present status of port 0~25 */ + int count = 0; + + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rxlos_all device file from (%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rxlos_all device file from(%s).", MODULE_RXLOS_ALL_ATTR); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t rx_los_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + rx_los_all <<= 8; + rx_los_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, (port+1)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + + if (port < 0) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + switch(control) + { + case ONLP_SFP_CONTROL_RX_LOS: + { + if (port >= 24) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + if (port >= 24) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..11d534de --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,103 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_as7316_26xb_int.h" +#include "x86_64_accton_as7316_26xb_log.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as7316-26xb-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 5 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 6 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/thermali.c new file mode 100644 index 00000000..028dd310 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,138 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[] = /* must map with onlp_thermal_id */ +{ + NULL, + NULL, /* CPU_CORE files */ + "/sys/devices/platform/as7316_26xb_thermal/temp1_input", + "/sys/devices/platform/as7316_26xb_thermal/temp2_input", + "/sys/devices/platform/as7316_26xb_thermal/temp3_input", + "/sys/devices/platform/as7316_26xb_thermal/temp4_input", + "/sys/devices/platform/as7316_26xb_thermal/temp5_input", + "/sys/devices/platform/as7316_26xb_thermal/temp6_input", + "/sys/devices/platform/as7316_26xb_psu/psu1_temp1_input", + "/sys/devices/platform/as7316_26xb_psu/psu2_temp1_input", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0*temp2_input", + "/sys/devices/platform/coretemp.0*temp3_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "LM75-5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BROAD), "LM75-6", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if(tid == THERMAL_CPU_CORE) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_config.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_config.c new file mode 100644 index 00000000..fbf6a34e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(_x) __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(_x) +x86_64_accton_as7316_26xb_config_settings_t x86_64_accton_as7316_26xb_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_STDLIB(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_UCLI(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS7316_26XB_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as7316_26xb_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as7316_26xb_config_STRINGIFY_VALUE +#undef __x86_64_accton_as7316_26xb_config_STRINGIFY_NAME + +const char* +x86_64_accton_as7316_26xb_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as7316_26xb_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as7316_26xb_config_settings[i].name, setting)) { + return x86_64_accton_as7316_26xb_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as7316_26xb_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as7316_26xb_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as7316_26xb_config_settings[i].name, x86_64_accton_as7316_26xb_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_enums.c new file mode 100644 index 00000000..713aa2ca --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_int.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_int.h new file mode 100644 index 00000000..65b96b54 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as7316_26xb Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7316_26xb_INT_H__ +#define __x86_64_accton_as7316_26xb_INT_H__ + +#include + + +#endif /* __x86_64_accton_as7316_26xb_INT_H__ */ \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.c new file mode 100644 index 00000000..d38ffa9e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7316_26xb_log.h" +/* + * x86_64_accton_as7316_26xb log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS7316_26XB_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.h b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.h new file mode 100644 index 00000000..e063f0b2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7316_26xb_LOG_H__ +#define __x86_64_accton_as7316_26xb_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as7316_26xb +#include + +#endif /* __x86_64_accton_as7316_26xb_LOG_H__ */ \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_module.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_module.c new file mode 100644 index 00000000..3b331e41 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7316_26xb_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as7316_26xb_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_as7316_26xb_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_ucli.c new file mode 100644 index 00000000..039ca3fa --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/onlp/builds/src/module/src/x86_64_accton_as7316_26xb_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as7316_26xb_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as7316_26xb_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as7316_26xb) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as7316_26xb_ucli_module__ = + { + "x86_64_accton_as7316_26xb_ucli", + NULL, + x86_64_accton_as7316_26xb_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as7316_26xb_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as7316_26xb_ucli_module__); + n = ucli_node_create("x86_64_accton_as7316_26xb", NULL, &x86_64_accton_as7316_26xb_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as7316_26xb")); + return n; +} + +#else +void* +x86_64_accton_as7316_26xb_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/PKG.yml new file mode 100644 index 00000000..777b1693 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as7316-26xb REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/lib/x86-64-accton-as7316-26xb-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/lib/x86-64-accton-as7316-26xb-r0.yml new file mode 100644 index 00000000..c4902697 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/lib/x86-64-accton-as7316-26xb-r0.yml @@ -0,0 +1,33 @@ +--- + +###################################################################### +# +# platform-config for AS7316 +# +###################################################################### + +x86-64-accton-as7316-26xb-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS0,115200n8 + tg3.short_preamble=1 + tg3.bcm5718s_reset=1 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/python/x86_64_accton_as7316_26xb_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/python/x86_64_accton_as7316_26xb_r0/__init__.py new file mode 100644 index 00000000..584199e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7316-26xb/platform-config/r0/src/python/x86_64_accton_as7316_26xb_r0/__init__.py @@ -0,0 +1,13 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as7316_26xb_r0(OnlPlatformAccton, + OnlPlatformPortConfig_16x10_8x25_2x100): + PLATFORM='x86-64-accton-as7316-26xb-r0' + MODEL="AS7316-26XB" + SYS_OBJECT_ID=".7316.26" + + def baseconfig(self): + self.insmod_platform() + return True + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/modules/builds/x86-64-accton-as7326-56x-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/modules/builds/x86-64-accton-as7326-56x-leds.c index 49689f11..aac08e9e 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/modules/builds/x86-64-accton-as7326-56x-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/modules/builds/x86-64-accton-as7326-56x-leds.c @@ -40,7 +40,7 @@ struct accton_as7326_56x_led_data { struct mutex update_lock; char valid; /* != 0 if registers are valid */ unsigned long last_updated; /* In jiffies */ - u8 reg_val[1]; /* only 1 register*/ + u8 reg_val[2]; }; static struct accton_as7326_56x_led_data *ledctl = NULL; @@ -48,18 +48,17 @@ static struct accton_as7326_56x_led_data *ledctl = NULL; /* LED related data */ +/* LED has only red, green and blue. + * Amber = red + green. + * Purple = red + blue. + */ + #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) +#define LED_TYPE_DIAG_REG_MASK (0x3F) +#define LED_MODE_DIAG_OFF_VALUE (0x07) +#define LED_TYPE_LOC_REG_MASK (0x3F) +#define LED_MODE_LOC_OFF_VALUE (0x07) enum led_type { LED_TYPE_DIAG, @@ -75,20 +74,23 @@ struct led_reg { }; static const struct led_reg led_reg_map[] = { - {(1<update_lock); if( !accton_getLedReg(type, ®)) @@ -283,7 +303,7 @@ static struct led_classdev accton_as7326_56x_leds[] = { .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, + .max_brightness = LED_MODE_PURPLE_BLINK, }, [LED_TYPE_LOC] = { .name = "accton_as7326_56x_led::loc", @@ -291,7 +311,7 @@ static struct led_classdev accton_as7326_56x_leds[] = { .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, + .max_brightness = LED_MODE_PURPLE_BLINK, }, [LED_TYPE_FAN] = { .name = "accton_as7326_56x_led::fan", diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/onlp/builds/src/module/src/ledi.c index de35ecc6..7d6b6dca 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7326-56x/onlp/builds/src/module/src/ledi.c @@ -53,19 +53,21 @@ enum onlp_led_id LED_PSU1, LED_PSU2 }; - + enum led_light_mode { - LED_MODE_OFF = 0, - LED_MODE_GREEN, - LED_MODE_AMBER, - LED_MODE_RED, - LED_MODE_BLUE, - LED_MODE_GREEN_BLINK, - LED_MODE_AMBER_BLINK, - LED_MODE_RED_BLINK, - LED_MODE_BLUE_BLINK, - LED_MODE_AUTO, - LED_MODE_UNKNOWN + LED_MODE_OFF = 0, + LED_MODE_RED, + LED_MODE_GREEN, + LED_MODE_BLUE, + LED_MODE_AMBER, + LED_MODE_PURPLE, + LED_MODE_RED_BLINK, + LED_MODE_GREEN_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_PURPLE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN }; typedef struct led_light_mode_map { @@ -75,12 +77,28 @@ typedef struct led_light_mode_map { } led_light_mode_map_t; led_light_mode_map_t led_map[] = { -{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, -{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, -{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED}, -{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, +{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED}, +{LED_DIAG, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, +{LED_DIAG, LED_MODE_PURPLE, ONLP_LED_MODE_PURPLE}, +{LED_DIAG, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, +{LED_DIAG, LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_DIAG, LED_MODE_RED_BLINK, ONLP_LED_MODE_RED_BLINKING}, +{LED_DIAG, LED_MODE_BLUE_BLINK, ONLP_LED_MODE_BLUE_BLINKING}, +{LED_DIAG, LED_MODE_PURPLE_BLINK, ONLP_LED_MODE_PURPLE_BLINKING}, +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_LOC, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_LOC, LED_MODE_RED, ONLP_LED_MODE_RED}, +{LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, +{LED_LOC, LED_MODE_PURPLE, ONLP_LED_MODE_PURPLE}, +{LED_LOC, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, +{LED_LOC, LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_LOC, LED_MODE_RED_BLINK, ONLP_LED_MODE_RED_BLINKING}, +{LED_LOC, LED_MODE_BLUE_BLINK, ONLP_LED_MODE_BLUE_BLINKING}, +{LED_LOC, LED_MODE_PURPLE_BLINK, ONLP_LED_MODE_PURPLE_BLINKING}, {LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, {LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, {LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} @@ -105,12 +123,20 @@ static onlp_led_info_t linfo[] = { { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 1 (DIAG LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_BLUE | ONLP_LED_CAPS_PURPLE| + ONLP_LED_CAPS_GREEN_BLINKING | ONLP_LED_CAPS_RED_BLINKING | + ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_BLUE_BLINKING | + ONLP_LED_CAPS_PURPLE_BLINKING, }, { { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 2 (LOC LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_BLUE | ONLP_LED_CAPS_PURPLE| + ONLP_LED_CAPS_GREEN_BLINKING | ONLP_LED_CAPS_RED_BLINKING | + ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_BLUE_BLINKING | + ONLP_LED_CAPS_PURPLE_BLINKING, }, { { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 3 (FAN LED)", 0 }, diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c index e3802603..83833c35 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c @@ -35,6 +35,7 @@ #include #define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 #define DC12V_FAN_DIR_OFFSET 0x34 #define DC12V_FAN_DIR_LEN 3 @@ -47,6 +48,13 @@ extern int as7712_32x_cpld_read (unsigned short cpld_addr, u8 reg); */ static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V, + PSU_TYPE_AC_ACBEL_FSF019, +}; + /* Each client has this additional data */ struct as7712_32x_psu_data { @@ -58,6 +66,8 @@ struct as7712_32x_psu_data { u8 status; /* Status(present/power_good) register read from CPLD */ char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ + char serial_number[MAX_SERIAL_NUMBER]; + enum psu_type type; }; static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); @@ -66,6 +76,7 @@ static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *d enum as7712_32x_psu_sysfs_attributes { PSU_PRESENT, PSU_MODEL_NAME, + PSU_SERIAL_NUMBER, /* For ACBEL PSU only */ PSU_POWER_GOOD, PSU_FAN_DIR /* For DC12V only */ }; @@ -74,12 +85,14 @@ enum as7712_32x_psu_sysfs_attributes { */ 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_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); 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 *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_serial_number.dev_attr.attr, &sensor_dev_attr_psu_power_good.dev_attr.attr, &sensor_dev_attr_psu_fan_dir.dev_attr.attr, NULL @@ -117,12 +130,19 @@ static ssize_t show_string(struct device *dev, struct device_attribute *da, return -EIO; } - if (attr->index == PSU_MODEL_NAME) { - ptr = data->model_name; - } - else { /* PSU_FAN_DIR */ - ptr = data->fan_dir; - } + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + case PSU_FAN_DIR: + ptr = data->fan_dir; + break; + default: + return -EINVAL; + } return sprintf(buf, "%s\n", ptr); } @@ -245,12 +265,6 @@ static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 * 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; @@ -258,10 +272,38 @@ struct model_name_info { char* model_name; }; +static int acbel_psu_serial_number_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + memset(data->serial_number, 0, sizeof(data->serial_number)); + + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as7712_32x_psu_read_block(client, 0x2e,data->serial_number, 16); + if (status < 0) { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + return status; + } + + /* Read from offset 0x4f ~ 0x50 (2 bytes) */ + status = as7712_32x_psu_read_block(client, 0x4f, data->serial_number + 16, 2); + if (status < 0) { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x4f)\n", client->addr); + return status; + } + + return 0; +} + 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"}, +{PSU_TYPE_AC_ACBEL_FSF019, 0x15, 7, "FSF019-"}, }; static int as7712_32x_psu_model_name_get(struct device *dev) @@ -285,6 +327,20 @@ static int as7712_32x_psu_model_name_get(struct device *dev) data->model_name[models[i].length] = '\0'; } + /* Get the remaining model name for FSF019 */ + if (strncmp(data->model_name, "FSF019-", 7) == 0) { + char buf[5] = {0}; + + status = as7712_32x_psu_read_block(client, 0x48, data->model_name + models[i].length, 4); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x48)\n", client->addr); + return status; + } + + data->type = PSU_TYPE_AC_ACBEL_FSF019; + } + /* 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) { @@ -348,6 +404,11 @@ static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *d goto exit; } } + + if (data->type == PSU_TYPE_AC_ACBEL_FSF019 && + acbel_psu_serial_number_get(dev) < 0) { + goto exit; + } } data->last_updated = jiffies; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c index 5fd76b00..da2ac83f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c @@ -148,11 +148,13 @@ _onlp_fani_info_get_psu_fan_direction(void) } switch (psu_type) { - case PSU_TYPE_AC_F2B: + case PSU_TYPE_AC_F2B_3YPOWER: + case PSU_TYPE_AC_F2B_ACBEL: case PSU_TYPE_DC_48V_F2B: case PSU_TYPE_DC_12V_F2B: return ONLP_FAN_STATUS_F2B; - case PSU_TYPE_AC_B2F: + case PSU_TYPE_AC_B2F_3YPOWER: + case PSU_TYPE_AC_B2F_ACBEL: case PSU_TYPE_DC_48V_B2F: case PSU_TYPE_DC_12V_B2F: return ONLP_FAN_STATUS_B2F; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c index ea139ae7..0a2f5e68 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c @@ -148,11 +148,11 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { - return PSU_TYPE_AC_F2B; + return PSU_TYPE_AC_F2B_3YPOWER; } if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { - return PSU_TYPE_AC_B2F; + return PSU_TYPE_AC_B2F_3YPOWER; } } @@ -198,12 +198,37 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } } + if (strncmp(model_name, "FSF019", 6) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); /* Copy full model name */ + } + + /* Read model */ + char *string = NULL; + char *prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; + int len = onlp_file_read_str(&string, "%s""psu_fan_dir", prefix); + if (!string || len <= 0) { + return PSU_TYPE_UNKNOWN; + } + + strncpy(fan_dir, string, len); + aim_free(string); + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B_ACBEL; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F_ACBEL; + } + } + return PSU_TYPE_UNKNOWN; } #define PSU_SERIAL_NUMBER_LEN 18 -int psu_serial_number_get(int id, char *serial, int serial_len) +int psu_pmbus_serial_number_get(int id, char *serial, int serial_len) { int size = 0; int ret = ONLP_STATUS_OK; @@ -225,3 +250,20 @@ int psu_serial_number_get(int id, char *serial, int serial_len) return ONLP_STATUS_OK; } +int psu_acbel_serial_number_get(int id, char *serial, int serial_len) +{ + char *serial_number = NULL; + char *prefix = (id == PSU1_ID) ? PSU1_AC_HWMON_PREFIX : PSU2_AC_HWMON_PREFIX; + + int len = onlp_file_read_str(&serial_number, "%s""psu_serial_number", prefix); + if (!serial || len <= 0) { + return ONLP_STATUS_E_INTERNAL; + } + + strncpy(serial, serial_number, len); + aim_free(serial_number); + + serial[len] = '\0'; + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h index a1e32542..675ce207 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h @@ -54,8 +54,10 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le typedef enum psu_type { PSU_TYPE_UNKNOWN, - PSU_TYPE_AC_F2B, - PSU_TYPE_AC_B2F, + PSU_TYPE_AC_F2B_3YPOWER, + PSU_TYPE_AC_B2F_3YPOWER, + PSU_TYPE_AC_F2B_ACBEL, + PSU_TYPE_AC_B2F_ACBEL, PSU_TYPE_DC_48V_F2B, PSU_TYPE_DC_48V_B2F, PSU_TYPE_DC_12V_FANLESS, @@ -64,7 +66,8 @@ typedef enum psu_type { } psu_type_t; psu_type_t get_psu_type(int id, char* modelname, int modelname_len); -int psu_serial_number_get(int id, char *serial, int serial_len); +int psu_pmbus_serial_number_get(int id, char *serial, int serial_len); +int psu_acbel_serial_number_get(int id, char *serial, int serial_len); #define DEBUG_MODE 0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c index 9a1a1436..4c25eae7 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c @@ -68,7 +68,7 @@ psu_status_info_get(int id, char *node, int *value) } static int -psu_ym2651_pmbus_info_get(int id, char *node, int *value) +psu_pmbus_info_get(int id, char *node, int *value) { int ret = 0; char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; @@ -113,22 +113,57 @@ psu_ym2651_info_get(onlp_psu_info_t* info) info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); /* Read voltage, current and power */ - if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { info->mvout = val; info->caps |= ONLP_PSU_CAPS_VOUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { info->miout = val; info->caps |= ONLP_PSU_CAPS_IOUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { info->mpout = val; info->caps |= ONLP_PSU_CAPS_POUT; } - psu_serial_number_get(index, info->serial, sizeof(info->serial)); + psu_pmbus_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + +static int +psu_acbel_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + psu_acbel_serial_number_get(index, info->serial, sizeof(info->serial)); return ONLP_STATUS_OK; } @@ -237,11 +272,16 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) psu_type = get_psu_type(index, info->model, sizeof(info->model)); switch (psu_type) { - case PSU_TYPE_AC_F2B: - case PSU_TYPE_AC_B2F: + case PSU_TYPE_AC_F2B_3YPOWER: + case PSU_TYPE_AC_B2F_3YPOWER: info->caps = ONLP_PSU_CAPS_AC; ret = psu_ym2651_info_get(info); break; + case PSU_TYPE_AC_F2B_ACBEL: + case PSU_TYPE_AC_B2F_ACBEL: + info->caps = ONLP_PSU_CAPS_AC; + ret = psu_acbel_info_get(info); + break; case PSU_TYPE_DC_48V_F2B: case PSU_TYPE_DC_48V_B2F: info->caps = ONLP_PSU_CAPS_DC48; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/sysi.c old mode 100644 new mode 100755 index 32aa1030..93502cbb --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/sysi.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -52,17 +53,26 @@ onlp_sysi_platform_get(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { + int ret = ONLP_STATUS_OK; + int i = 0; uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { - *data = rdata; - return ONLP_STATUS_OK; + + for (i = 0; i < 128; i++) { + ret = onlp_i2c_readw(0, 0x56, i*2, ONLP_I2C_F_FORCE); + if (ret < 0) { + aim_free(rdata); + *size = 0; + return ret; } + + rdata[i*2] = ret & 0xff; + rdata[i*2+1] = (ret >> 8) & 0xff; } - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; + *size = 256; + *data = rdata; + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/platform-config/r0/src/python/x86_64_accton_as7716_32x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/platform-config/r0/src/python/x86_64_accton_as7716_32x_r0/__init__.py old mode 100644 new mode 100755 index 9ba0f66d..301e607f --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/platform-config/r0/src/python/x86_64_accton_as7716_32x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/platform-config/r0/src/python/x86_64_accton_as7716_32x_r0/__init__.py @@ -85,7 +85,7 @@ class OnlPlatform_x86_64_accton_as7716_32x_r0(OnlPlatformAccton, ('optoe1', 0x50, 54), ('optoe1', 0x50, 55), ('optoe1', 0x50, 56), - ('24c02', 0x56, 0), + #('24c02', 0x56, 0), ]) subprocess.call('echo port9 > /sys/bus/i2c/devices/25-0050/port_name', shell=True) diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/modules/builds/x86-64-accton-as7726-32x-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/modules/builds/x86-64-accton-as7726-32x-leds.c index 801cd9e3..b6e34ac4 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/modules/builds/x86-64-accton-as7726-32x-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/modules/builds/x86-64-accton-as7726-32x-leds.c @@ -53,7 +53,6 @@ static struct accton_as7726_32x_led_data *ledctl = NULL; #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) @@ -102,11 +101,11 @@ struct led_type_mode { static struct led_type_mode led_type_mode_data[] = { {LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, - {LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_VALUE}, + {LED_TYPE_LOC, LED_MODE_BLUE, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_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_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, {LED_TYPE_DIAG, LED_MODE_RED, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE}, - {LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, }; @@ -428,6 +427,6 @@ static void __exit accton_as7726_32x_led_exit(void) module_init(accton_as7726_32x_led_init); module_exit(accton_as7726_32x_led_exit); -MODULE_AUTHOR("Brandon Chuang "); +MODULE_AUTHOR("Jostar Yang "); MODULE_DESCRIPTION("accton_as7726_32x_led driver"); MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/ledi.c index 94926527..ad7437ed 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/ledi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/ledi.c @@ -77,7 +77,6 @@ typedef struct led_light_mode_map { led_light_mode_map_t led_map[] = { {LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, {LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, -{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, {LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED}, {LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, {LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, @@ -105,7 +104,7 @@ static onlp_led_info_t linfo[] = { { ONLP_LED_ID_CREATE(LED_DIAG), "LED 1 (DIAG LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, }, { { ONLP_LED_ID_CREATE(LED_LOC), "LED 2 (LOC LED)", 0 }, diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/sysi.c index 4e16b3ad..5105e3de 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7726-32x/onlp/builds/src/x86_64_accton_as7726_32x/module/src/sysi.c @@ -36,22 +36,12 @@ #include "x86_64_accton_as7726_32x_int.h" #include "x86_64_accton_as7726_32x_log.h" - +#define NUM_OF_FAN_ON_MAIN_BROAD 6 #define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/" #define NUM_OF_CPLD 3 #define FAN_DUTY_CYCLE_MAX (100) -#define FAN_DUTY_CYCLE_DEFAULT (32) -#define FAN_DUTY_PLUS_FOR_DIR (13) -/* Note, all chassis fans share 1 single duty setting. - * Here use fan 1 to represent global fan duty value.*/ -#define FAN_ID_FOR_SET_FAN_DUTY (1) -#define CELSIUS_RECORD_NUMBER (2) /*Must >= 2*/ +#define FAN_DUTY_CYCLE_DEFAULT (38) -typedef struct fan_ctrl_policy { - int duty_cycle; /* In percetage */ - int step_up_thermal; /* In mini-Celsius */ - int step_dn_thermal; /* In mini-Celsius */ -} fan_ctrl_policy_t; static char arr_cplddev_name[NUM_OF_CPLD][10] = { @@ -136,351 +126,244 @@ onlp_sysi_platform_info_free(onlp_platform_info_t* pi) aim_free(pi->cpld_versions); } -/* Thermal plan: - * $TMP = (CPU_core + LM75_1+ LM75_2 + LM75_3 + LM75_4)/5 - * 1. If any FAN failed, set all the other fans as full speed, 100%. - * 2. If any sensor is high than 45 degrees, set fan speed to duty 62.5%. - * 3. If any sensor is high than 50 degrees, set fan speed to duty 100%. - * 4. When $TMP >= 40 C, set fan speed to duty 62.5%. - * 5. When $TMP >= 45 C, set fan speed to duty 100%. - * 6. When $TMP < 35 C, set fan speed to duty 31.25%. - * 7. Direction factor, when B2F, duty + 12.5%. - * - * Note, all chassis fans share 1 single duty setting. +/* + * 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) */ -fan_ctrl_policy_t fan_ctrl_policy_avg[] = { -{FAN_DUTY_CYCLE_MAX , 45000, INT_MIN}, -{63 , 40000, INT_MIN}, -{32 , INT_MAX, 35000}, -}; -fan_ctrl_policy_t fan_ctrl_policy_single[] = { -{FAN_DUTY_CYCLE_MAX , 50000, INT_MIN}, -{63 , 45000, INT_MIN}, -}; -struct fan_control_data_s { +typedef struct fan_ctrl_policy { int duty_cycle; - int dir_plus; - int mc_avg_pre[CELSIUS_RECORD_NUMBER]; - int mc_high_pre[CELSIUS_RECORD_NUMBER]; + int pwm; + int temp_down; /* The boundary temperature to down adjust fan speed */ + int temp_up; /* The boundary temperature to up adjust fan speed */ + int state; +} fan_ctrl_policy_t; -} fan_control_data_pre = +enum { - .duty_cycle = FAN_DUTY_CYCLE_DEFAULT, - .dir_plus = 0, - .mc_avg_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/ - .mc_high_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/ - + LEVEL_FAN_DEF=0, + LEVEL_FAN_MID, + LEVEL_FAN_MAX, + LEVEL_TEMP_HIGH, + LEVEL_TEMP_CRITICAL }; -static int -sysi_check_fan(uint32_t *fan_dir){ - int i, present; +fan_ctrl_policy_t fan_thermal_policy_f2b[] = { +{38, 0x4, 0, 38000, LEVEL_FAN_DEF}, +{63, 0x8, 38000, 46000, LEVEL_FAN_MID}, +{100, 0xE, 46000, 58000, LEVEL_FAN_MAX}, +{100, 0xE, 58000, 66000, LEVEL_TEMP_HIGH}, +{100, 0xE, 66000, 200000, LEVEL_TEMP_CRITICAL} +}; - for (i = 1; i <= CHASSIS_FAN_COUNT; i++) +fan_ctrl_policy_t fan_thermal_policy_b2f[] = { +{38, 0x4, 0, 34000, LEVEL_FAN_DEF}, +{63, 0x8, 34000, 44000, LEVEL_FAN_MID}, +{100, 0xE, 44000, 59000, LEVEL_FAN_MAX}, +{100, 0xE, 59000, 67000, LEVEL_TEMP_HIGH}, +{100, 0xE, 67000, 200000, LEVEL_TEMP_CRITICAL} +}; + +#define FAN_SPEED_CTRL_PATH "/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage" +#define FAN_DIRECTION_PATH "/sys/bus/i2c/devices/54-0066/fan1_direction" + +static int fan_state=LEVEL_FAN_DEF; +static int alarm_state = 0; /* 0->default or clear, 1-->alarm detect */ +static int fan_fail = 0; + +int onlp_sysi_platform_manage_fans(void) +{ + int i=0, ori_state=LEVEL_FAN_DEF, current_state=LEVEL_FAN_DEF; + int fd, len, value=1; + int cur_duty_cycle, new_duty_cycle, temp=0; + onlp_thermal_info_t thermal_4, thermal_5; + char buf[10] = {0}; + fan_ctrl_policy_t *fan_thermal_policy; + + /* Get fan direction + */ + if (onlp_file_read_int(&value, FAN_DIRECTION_PATH) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", FAN_DIRECTION_PATH); + } + + if(value==1) + fan_thermal_policy=fan_thermal_policy_f2b; + else + fan_thermal_policy=fan_thermal_policy_b2f; + + /* Get current temperature + */ + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(4), &thermal_4) != ONLP_STATUS_OK ) + { + AIM_LOG_ERROR("Unable to read thermal status, set fans to 75% speed"); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fan_thermal_policy[LEVEL_FAN_MID].duty_cycle); + return ONLP_STATUS_E_INTERNAL; + } + if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(5), &thermal_5) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to read thermal status, set fans to 75% speed"); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fan_thermal_policy[LEVEL_FAN_MID].duty_cycle); + return ONLP_STATUS_E_INTERNAL; + } + + temp = (thermal_4.mcelsius + thermal_5.mcelsius)/2; + /* Get current fan pwm percent + */ + fd = open(FAN_SPEED_CTRL_PATH, O_RDONLY); + if (fd == -1){ + AIM_LOG_ERROR("Unable to open fan speed control node (%s)", FAN_SPEED_CTRL_PATH); + return ONLP_STATUS_E_INTERNAL; + } + len = read(fd, buf, sizeof(buf)); + close(fd); + if (len <= 0) { + AIM_LOG_ERROR("Unable to read fan speed from (%s)", FAN_SPEED_CTRL_PATH); + return ONLP_STATUS_E_INTERNAL; + } + cur_duty_cycle = atoi(buf); + ori_state=fan_state; + /* Inpunt temp to get theraml_polyc state and new pwm percent. */ + for(i=0; i < sizeof(fan_thermal_policy_f2b)/sizeof(fan_ctrl_policy_t); i++) + { + if (temp > fan_thermal_policy[i].temp_down) + { + if (temp <= fan_thermal_policy[i].temp_up) + { + current_state =i; + } + } + } + if(current_state > LEVEL_TEMP_CRITICAL || current_state < LEVEL_FAN_DEF) + { + AIM_LOG_ERROR("onlp_sysi_platform_manage_fans get error current_state\n"); + return 0; + } + /* Decision 3: Decide new fan pwm percent. + */ + if (fan_fail==0 &&cur_duty_cycle!=fan_thermal_policy[current_state].duty_cycle) + { + new_duty_cycle = fan_thermal_policy[current_state].duty_cycle; + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), new_duty_cycle); + } + + /* Get each fan status + */ + + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) { onlp_fan_info_t fan_info; if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); - return ONLP_STATUS_E_INTERNAL; + AIM_LOG_ERROR("Unable to get fan(%d) status, try to set the other fans as full speed\r\n", i); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); + fan_fail=1; + break; } - - present = fan_info.status & ONLP_FAN_STATUS_PRESENT; - if ((fan_info.status & ONLP_FAN_STATUS_FAILED) || !present) { - AIM_LOG_WARN("Fan(%d) is not working, set the other fans as full speed\r\n", i); - int ret = onlp_fani_percentage_set( - ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY), FAN_DUTY_CYCLE_MAX); - if (ret != ONLP_STATUS_OK) - return ret; - else - return ONLP_STATUS_E_MISSING; - } - - /* Get fan direction (Only get the first one since all fan direction are the same) + /* Decision 1: Set fan as full speed if any fan is failed. */ - if (i == 1) { - *fan_dir = fan_info.status & (ONLP_FAN_STATUS_F2B|ONLP_FAN_STATUS_B2F); - } - } - - return ONLP_STATUS_OK; -} - -static int -sysi_get_fan_duty(int *cur_duty_cycle){ - int fd, len; - char buf[10] = {0}; - char *node = FAN_NODE(fan_duty_cycle_percentage); - - /* Get current fan duty*/ - fd = open(node, O_RDONLY); - if (fd == -1){ - AIM_LOG_ERROR("Unable to open fan speed control node (%s)", node); - return ONLP_STATUS_E_INTERNAL; - } - - len = read(fd, buf, sizeof(buf)); - close(fd); - if (len <= 0) { - AIM_LOG_ERROR("Unable to read fan speed from (%s)", node); - return ONLP_STATUS_E_INTERNAL; - } - *cur_duty_cycle = atoi(buf); - - return ONLP_STATUS_OK; -} - -static int -sysi_get_thermal_sum(int *mcelsius){ - onlp_thermal_info_t thermal_info; - int i; - - *mcelsius = 0; - for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { - if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info) - != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to read thermal status"); - return ONLP_STATUS_E_INTERNAL; + if (fan_info.status & ONLP_FAN_STATUS_FAILED || !(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { + AIM_LOG_ERROR("Fan(%d) is not working, set the other fans as full speed\r\n", i); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); + fan_fail=1; + break; } - *mcelsius += thermal_info.mcelsius; + } - DEBUG_PRINT("Thermal %d: %d \n ", i, thermal_info.mcelsius); + if(current_state!=ori_state) + { + fan_state=current_state; + + switch (ori_state) + { + case LEVEL_FAN_DEF: + if(current_state==LEVEL_TEMP_HIGH) + { + if(alarm_state==0) + { + AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected"); + alarm_state=1; + } + } + if(current_state==LEVEL_TEMP_CRITICAL) + { + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", "Alarm for temperature critical is detected, reboot DUT"); + system("sync;sync;sync"); + system("reboot"); + } + break; + case LEVEL_FAN_MID: + if(current_state==LEVEL_TEMP_HIGH) + { + if(alarm_state==0) + { + AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected"); + alarm_state=1; + } + } + if(current_state==LEVEL_TEMP_CRITICAL) + { + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", "Alarm for temperature critical is detected, reboot DUT"); + system("sync;sync;sync"); + system("reboot"); + } + break; + case LEVEL_FAN_MAX: + if(current_state==LEVEL_TEMP_HIGH) + { + if(alarm_state==0) + { + AIM_SYSLOG_WARN("Temperature high", "Temperature high","Alarm for temperature high is detected"); + alarm_state=1; + } + } + if(current_state==LEVEL_TEMP_CRITICAL) + { + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical ", "Alarm for temperature critical is detected, reboot DUT"); + system("sync;sync;sync"); + system("reboot"); + } + break; + case LEVEL_TEMP_HIGH: + if(current_state==LEVEL_TEMP_CRITICAL) + { + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical ", "Alarm for temperature critical is detected, reboot DUT"); + system("sync;sync;sync"); + system("reboot"); + } + break; + case LEVEL_TEMP_CRITICAL: + break; + default: + AIM_SYSLOG_WARN("onlp_sysi_platform_manage_fans abnormal state", "onlp_sysi_platform_manage_fans abnormal state", "onlp_sysi_platform_manage_fans at abnormal state\n"); + break; + } } - - return ONLP_STATUS_OK; - -} - -static int -sysi_get_highest_thermal(int *mcelsius){ - onlp_thermal_info_t thermal_info; - int i, highest; - - highest = 0; - for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { - if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info) - != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to read thermal status"); - return ONLP_STATUS_E_INTERNAL; - } - highest = (thermal_info.mcelsius > highest)? - thermal_info.mcelsius : highest; - } - *mcelsius = highest; - return ONLP_STATUS_OK; -} - -/* Anaylze thermal changing history to judge if the change is a stable trend. */ -static int _is_thermal_a_trend(int *mc_history){ - int i, trend, trended; - - if (mc_history == NULL) { - AIM_LOG_ERROR("Unable to get history of thermal\n"); - return 0; - } - - /* Get heat up/down trend. */ - trend = 0; - for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { - if (( mc_history[i+1] < mc_history[i])){ - trend++; - }else if (( mc_history[i+1] > mc_history[i])){ - trend--; - } - } - - trended = (abs(trend) >= ((CELSIUS_RECORD_NUMBER+1)/2))? 1:0; -#if (DEBUG_MODE == 1) - DEBUG_PRINT("[INFO]%s#%d, trended: %d, UP/DW: %d mcelsius:", - __func__, __LINE__, trended, trend ); - for (i = 0; i <= CELSIUS_RECORD_NUMBER; i++) { - DEBUG_PRINT(" %d =>", mc_history[i]); - } - DEBUG_PRINT("%c\n", ' '); -#endif - - /*For more than half changes are same direction, it's a firm trend.*/ - return trended; -} - - -/* Decide duty by highest value of thermal sensors.*/ -static int -sysi_get_duty_by_highest(int *duty_cycle){ - int i, ret, maxtrix_len; - int new_duty_cycle = 0 ; - int mc_history[CELSIUS_RECORD_NUMBER+1] = {0}; - int *mcelsius_pre_p = &mc_history[1]; - int *mcelsius_now_p = &mc_history[0]; - - /* Fill up mcelsius array, - * [0] is current temperature, others are history. - */ - ret = sysi_get_highest_thermal(mcelsius_now_p); - if(ONLP_STATUS_OK != ret){ - return ret; - } - memcpy (mcelsius_pre_p, fan_control_data_pre.mc_high_pre, - sizeof(fan_control_data_pre.mc_high_pre)); - - DEBUG_PRINT("[INFO]%s#%d, highest mcelsius:%d!\n", - __func__, __LINE__, *mcelsius_now_p); - - /* Shift records to the right */ - for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { - fan_control_data_pre.mc_high_pre[i] = mc_history[i]; - } - - /* Only change duty on consecutive heat rising or falling.*/ - maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_single); - - /* Only change duty when the thermal changing are firm. */ - if (_is_thermal_a_trend(mc_history)) + if(alarm_state==1 && current_state < LEVEL_TEMP_HIGH) { - int matched = 0; - for (i = 0; i < maxtrix_len; i++) { - if ((*mcelsius_now_p > fan_ctrl_policy_single[i].step_up_thermal)) { - new_duty_cycle = fan_ctrl_policy_single[i].duty_cycle; - matched = !matched; - break; - } - } -/* if (!matched) { - DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n", - __func__, __LINE__, *mcelsius_now_p); - } */ - } - *duty_cycle = new_duty_cycle; - return ONLP_STATUS_OK; -} - -/* Decide duty by average value of thermal sensors.*/ -static int -sysi_get_duty_by_average(int *duty_cycle){ - int i, mcelsius_avg, ret, maxtrix_len; - int new_duty_cycle=0; - int mc_history[CELSIUS_RECORD_NUMBER+1] = {0}; - int *mcelsius_pre_p = &mc_history[1]; - int *mcelsius_now_p = &mc_history[0]; - - /* Fill up mcelsius array, - * [0] is current temperature, others are history. - */ - *mcelsius_now_p = 0; - ret = sysi_get_thermal_sum(mcelsius_now_p); - if(ONLP_STATUS_OK != ret){ - return ret; - } - mcelsius_avg = (*mcelsius_now_p)/CHASSIS_THERMAL_COUNT; - - memcpy (mcelsius_pre_p, fan_control_data_pre.mc_avg_pre, - sizeof(fan_control_data_pre.mc_avg_pre)); - - DEBUG_PRINT("[INFO]%s#%d, mcelsius:%d!\n", __func__, __LINE__, mcelsius_avg); - - /* Shift records to the right */ - for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { - fan_control_data_pre.mc_avg_pre[i] = mc_history[i]; - } - - /* Only change duty on consecutive heat rising or falling.*/ - maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_avg); - - /* Only change duty when the thermal changing are firm. */ - if (_is_thermal_a_trend(mc_history)) - { - int matched = 0; - for (i = 0; i < maxtrix_len; i++) { - if ((mcelsius_avg >= fan_ctrl_policy_avg[i].step_up_thermal)) { - new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle; - matched = !matched; - break; - } - } - for (i = maxtrix_len-1; i>=0; i--) { - if ((mcelsius_avg < fan_ctrl_policy_avg[i].step_dn_thermal)) { - new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle; - matched = !matched; - break; - } - } - /*if (!matched) { - DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n", - __func__, __LINE__, mcelsius_avg); - } */ + if (temp < (fan_thermal_policy[LEVEL_TEMP_HIGH].temp_down - 5000)) /*below 58 C, clear alarm*/ + { + AIM_SYSLOG_INFO("Temperature high is clean", "Temperature high is clear", "Alarm for temperature high is cleared"); + alarm_state=0; + } } - *duty_cycle = new_duty_cycle; - return ONLP_STATUS_OK; -} - -int -onlp_sysi_platform_manage_fans(void) -{ - uint32_t fan_dir; - int ret; - int cur_duty_cycle, new_duty_cycle, tmp; - int direct_addon = 0; - onlp_oid_t fan_duty_oid = ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY); - - /********************************************************** - * Decision 1: Set fan as full speed if any fan is failed. - **********************************************************/ - ret = sysi_check_fan(&fan_dir); - if(ONLP_STATUS_OK != ret){ - return ret; - } - - if (fan_dir & ONLP_FAN_STATUS_B2F) { - direct_addon = FAN_DUTY_PLUS_FOR_DIR; - } - - /********************************************************** - * Decision 2: If no matched fan speed is found from the policy, - * use FAN_DUTY_CYCLE_MIN as default speed - **********************************************************/ - ret = sysi_get_fan_duty(&cur_duty_cycle); - if(ONLP_STATUS_OK != ret){ - return ret; - } - - /********************************************************** - * Decision 3: Decide new fan speed depend on fan direction and temperature - **********************************************************/ - ret = sysi_get_duty_by_average(&new_duty_cycle); - if (ONLP_STATUS_OK != ret){ - return ret; - } - ret = sysi_get_duty_by_highest(&tmp); - if (ONLP_STATUS_OK != ret){ - return ret; - } - - new_duty_cycle = (tmp > new_duty_cycle)? tmp : new_duty_cycle; - if (new_duty_cycle == 0) - { - new_duty_cycle = fan_control_data_pre.duty_cycle; - } else { - fan_control_data_pre.duty_cycle = new_duty_cycle; - } - fan_control_data_pre.dir_plus = direct_addon; - DEBUG_PRINT("[INFO]%s#%d, new duty: %d = %d + %d (%d)!\n", __func__, __LINE__, - new_duty_cycle + direct_addon, new_duty_cycle, direct_addon, cur_duty_cycle); - - new_duty_cycle += direct_addon; - new_duty_cycle = (new_duty_cycle > FAN_DUTY_CYCLE_MAX)? - FAN_DUTY_CYCLE_MAX : new_duty_cycle; - - if (new_duty_cycle == cur_duty_cycle) { - /* Duty cycle does not change, just return */ - return ONLP_STATUS_OK; - } - - return onlp_fani_percentage_set(fan_duty_oid, new_duty_cycle); -} + return 0; +} int onlp_sysi_platform_manage_leds(void) @@ -488,3 +371,5 @@ onlp_sysi_platform_manage_leds(void) return ONLP_STATUS_E_UNSUPPORTED; } + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c old mode 100644 new mode 100755 index 76fc16b9..03d7c58b --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c @@ -162,6 +162,10 @@ _onlp_get_fan_direction_on_psu(void) } switch (psu_type) { + case PSU_TYPE_AC_DPS850_F2B: + return ONLP_FAN_STATUS_F2B; + case PSU_TYPE_AC_DPS850_B2F: + return ONLP_FAN_STATUS_B2F; case PSU_TYPE_AC_YM2851_F2B: return ONLP_FAN_STATUS_F2B; case PSU_TYPE_AC_YM2851_B2F: @@ -178,6 +182,7 @@ static int _onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) { int val = 0; + psu_type_t psu_type; info->status |= ONLP_FAN_STATUS_PRESENT; @@ -185,13 +190,33 @@ _onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) */ info->status |= _onlp_get_fan_direction_on_psu(); + + + psu_type = psu_type_get(pid, NULL, 0); + if (psu_type == PSU_TYPE_UNKNOWN) + return ONLP_FAN_STATUS_FAILED; + /* get fan speed */ - if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { + if (psu_type == PSU_TYPE_AC_DPS850_F2B || psu_type == PSU_TYPE_AC_DPS850_B2F) + { + if (psu_dps850_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) + { info->rpm = val; info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0; } + } + + if (psu_type == PSU_TYPE_AC_YM2851_F2B || psu_type == PSU_TYPE_AC_YM2851_B2F) + { + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) + { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0; + } + } return ONLP_STATUS_OK; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c old mode 100644 new mode 100755 index dffc3c46..52c64d94 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c @@ -37,15 +37,14 @@ int psu_serial_number_get(int id, char *serial, int serial_len) { int size = 0; int ret = ONLP_STATUS_OK; - char *prefix = NULL; + char *path = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_mfr_serial) : + PSU2_AC_PMBUS_NODE(psu_mfr_serial) ; if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_PARAM; } - prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; - - ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_mfr_serial"); + ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, path); if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_INTERNAL; @@ -89,6 +88,10 @@ psu_type_t psu_type_get(int id, char* modelname, int modelname_len) memcpy(modelname, model, sizeof(model)); } + if (strncmp(model, "DPS-850A", strlen("DPS-850A")) == 0) { + return PSU_TYPE_AC_DPS850_F2B; + } + if (strncmp(model, "YM-2851F", strlen("YM-2851F")) == 0) { return PSU_TYPE_AC_YM2851_F2B; } @@ -123,3 +126,19 @@ int psu_ym2651y_pmbus_info_set(int id, char *node, int value) return ONLP_STATUS_OK; } +int psu_dps850_pmbus_info_get(int id, char *node, int *value) +{ + char *prefix = NULL; + + *value = 0; + + prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; + if (onlp_file_read_int(value, "%s%s", prefix, node) < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s%s)\r\n", prefix, node); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h old mode 100644 new mode 100755 index 3a37a536..1aacc5ad --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h @@ -77,13 +77,17 @@ enum onlp_thermal_id typedef enum psu_type { PSU_TYPE_UNKNOWN, PSU_TYPE_AC_YM2851_F2B, - PSU_TYPE_AC_YM2851_B2F + PSU_TYPE_AC_YM2851_B2F, + PSU_TYPE_AC_DPS850_F2B, + PSU_TYPE_AC_DPS850_B2F } psu_type_t; psu_type_t psu_type_get(int id, char* modelname, int modelname_len); int psu_serial_number_get(int id, char *serial, int serial_len); int psu_ym2651y_pmbus_info_get(int id, char *node, int *value); int psu_ym2651y_pmbus_info_set(int id, char *node, int value); +int psu_dps850_pmbus_info_get(int id, char *node, int *value); + #define DEBUG_MODE 0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c old mode 100644 new mode 100755 index 6e347b6e..f0390173 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c @@ -82,6 +82,59 @@ psu_ym2651y_info_get(onlp_psu_info_t* info) return ONLP_STATUS_OK; } +static int +psu_dps850_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_dps850_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_v_in", &val) == 0) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (psu_dps850_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_i_in", &val) == 0) { + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (psu_dps850_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_p_in", &val) == 0) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + psu_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + + /* * Get all information about the given PSU oid. */ @@ -135,8 +188,11 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) /* Get PSU type */ psu_type = psu_type_get(index, info->model, sizeof(info->model)); - switch (psu_type) { + case PSU_TYPE_AC_DPS850_F2B: + case PSU_TYPE_AC_DPS850_B2F: + ret = psu_dps850_info_get(info); + break; case PSU_TYPE_AC_YM2851_F2B: case PSU_TYPE_AC_YM2851_B2F: ret = psu_ym2651y_info_get(info); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/sysi.c old mode 100644 new mode 100755 index ada5a5d2..52d939e7 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/sysi.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -57,17 +58,26 @@ onlp_sysi_platform_get(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { + int ret = ONLP_STATUS_OK; + int i = 0; uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { - *data = rdata; - return ONLP_STATUS_OK; + + for (i = 0; i < 128; i++) { + ret = onlp_i2c_readw(0, 0x56, i*2, ONLP_I2C_F_FORCE); + if (ret < 0) { + aim_free(rdata); + *size = 0; + return ret; } + + rdata[i*2] = ret & 0xff; + rdata[i*2+1] = (ret >> 8) & 0xff; } - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; + *size = 256; + *data = rdata; + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py old mode 100644 new mode 100755 index 163f3991..accf55b5 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py @@ -6,10 +6,16 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, PLATFORM='x86-64-accton-as7816-64x-r0' MODEL="AS7816-64x" SYS_OBJECT_ID=".7816.64" + PSU1_MODEL="/sys/bus/i2c/devices/i2c-10/10-005b/psu_mfr_model" + PSU2_MODEL="/sys/bus/i2c/devices/i2c-9/9-0058/psu_mfr_model" + PSU1_POWER="/sys/bus/i2c/devices/i2c-19/19-0060/psu1_power_good" + PSU2_POWER="/sys/bus/i2c/devices/i2c-19/19-0060/psu2_power_good" + def baseconfig(self): self.insmod('optoe') self.insmod('ym2651y') + self.insmod('dps850') self.insmod('accton_i2c_cpld') for m in [ 'fan', 'cpld1', 'leds' ]: self.insmod("x86-64-accton-as7816-64x-%s.ko" % m) @@ -26,11 +32,13 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, # initiate PSU-1 ('24c02', 0x53, 10), - ('ym2851', 0x5b, 10), + ('dps850', 0x5b, 10), + #('ym2851', 0x5b, 10), # initiate PSU-2 ('24c02', 0x50, 9), - ('ym2851', 0x58, 9), + ('dps850', 0x58, 9), + #('ym2851', 0x58, 9), # initiate chassis fan ('as7816_64x_fan', 0x68, 17), @@ -124,7 +132,7 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, ('optoe1', 0x50, 87), ('optoe1', 0x50, 88), - ('24c02', 0x56, 0), + #('24c02', 0x56, 0), ]) subprocess.call('echo port61 > /sys/bus/i2c/devices/25-0050/port_name', shell=True) @@ -193,4 +201,39 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, subprocess.call('echo port51 > /sys/bus/i2c/devices/87-0050/port_name', shell=True) subprocess.call('echo port52 > /sys/bus/i2c/devices/88-0050/port_name', shell=True) + PSU_DELTA="DPS-850" + PSU_3Y= "YM-2851F" + if os.path.exists(self.PSU2_POWER): + with open(self.PSU2_POWER, 'r') as fd: + val=int(fd.read()) + if val==1: + if os.path.exists(self.PSU2_MODEL): + with open(self.PSU2_MODEL, 'r') as fd: + f=open(self.PSU2_MODEL) + val_str=f.read() + if int(val_str.find(PSU_3Y))== 0: + subprocess.call('echo 0x58 > /sys/bus/i2c/devices/i2c-9/delete_device', shell=True) + subprocess.call('echo 0x5b > /sys/bus/i2c/devices/i2c-10/delete_device', shell=True) + self.new_i2c_devices([ + ('ym2851', 0x58, 9), + ('ym2851', 0x5b, 10), + ]) + return True + if os.path.exists(self.PSU1_POWER): + with open(self.PSU1_POWER, 'r') as fd: + val=int(fd.read()) + if val==1: + if os.path.exists(self.PSU1_MODEL): + with open(self.PSU1_MODEL, 'r') as fd: + f=open(self.PSU1_MODEL) + val_str=f.read() + if int(val_str.find(PSU_3Y))== 0: + subprocess.call('echo 0x58 > /sys/bus/i2c/devices/i2c-9/delete_device', shell=True) + subprocess.call('echo 0x5b > /sys/bus/i2c/devices/i2c-10/delete_device', shell=True) + self.new_i2c_devices([ + ('ym2851', 0x58, 9), + ('ym2851', 0x5b, 10), + ]) + return True + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/.gitignore new file mode 100755 index 00000000..38161e48 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*as7816*64x*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/PKG.yml new file mode 100755 index 00000000..b19154f4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as9716-32d ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/.gitignore new file mode 100755 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/Makefile new file mode 100755 index 00000000..d72b2fdc --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-as9716-32d +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-cpld.c new file mode 100755 index 00000000..0ea4b777 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-cpld.c @@ -0,0 +1,679 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as9716_32d CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as9716_32d_fpga, + as9716_32d_cpld1, + as9716_32d_cpld2, + as9716_32d_cpld_cpu +}; + +struct as9716_32d_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as9716_32d_cpld_id[] = { + { "as9716_32d_fpga", as9716_32d_fpga }, + { "as9716_32d_cpld1", as9716_32d_cpld1 }, + { "as9716_32d_cpld2", as9716_32d_cpld2 }, + { "as9716_32d_cpld_cpu", as9716_32d_cpld_cpu }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as9716_32d_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34) +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); + + +static struct attribute *as9716_32d_fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9716_32d_fpga_group = { + .attrs = as9716_32d_fpga_attributes, +}; + +static struct attribute *as9716_32d_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + NULL +}; + +static const struct attribute_group as9716_32d_cpld1_group = { + .attrs = as9716_32d_cpld1_attributes, +}; + +static struct attribute *as9716_32d_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + NULL +}; + +static const struct attribute_group as9716_32d_cpld2_group = { + .attrs = as9716_32d_cpld2_attributes, +}; + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x20; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x20; + mask = 0x8; + break; + case MODULE_RXLOS_33: + reg = 0x20; + mask = 0x2; + break; + case MODULE_RXLOS_34: + reg = 0x20; + mask = 0x10; + break; + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as9716_32d_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as9716_32d_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as9716_32d_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as9716_32d_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as9716_32d_cpld_data *data; + int ret = -ENODEV; + int status; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as9716_32d_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + + /* Register sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + case as9716_32d_cpld_cpu: + /* Disable CPLD reset to avoid DUT will be reset. + */ + status=as9716_32d_cpld_write_internal(client, 0x3, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpu_cpld reg 0x65 err %d\n", status); + } + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as9716_32d_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as9716_32d_cpld_remove(struct i2c_client *client) +{ + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as9716_32d_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_read); + +int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_write); + +static struct i2c_driver as9716_32d_cpld_driver = { + .driver = { + .name = "as9716_32d_cpld", + .owner = THIS_MODULE, + }, + .probe = as9716_32d_cpld_probe, + .remove = as9716_32d_cpld_remove, + .id_table = as9716_32d_cpld_id, +}; + +static int __init as9716_32d_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as9716_32d_cpld_driver); +} + +static void __exit as9716_32d_cpld_exit(void) +{ + i2c_del_driver(&as9716_32d_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as9716_32d_cpld_init); +module_exit(as9716_32d_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-fan.c new file mode 100755 index 00000000..e435c0a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-fan.c @@ -0,0 +1,472 @@ +/* + * 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 + +#define DRVNAME "as9716_32d_fan" + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as9716_32d_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +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) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6); +/* 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); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6); +/* 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(); + +static struct attribute *as9716_32d_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_FAULT_ATTR(6), + 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_SPEED_RPM_ATTR(6), + 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(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as9716_32d_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as9716_32d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as9716_32d_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as9716_32d_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as9716_32d_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as9716_32d_fan_group = { + .attrs = as9716_32d_fan_attributes, +}; + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as9716_32d_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as9716_32d_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as9716_32d_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_fan_remove(struct i2c_client *client) +{ + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as9716_32d_fan_id[] = { + { "as9716_32d_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_fan_id); + +static struct i2c_driver as9716_32d_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as9716_32d_fan_probe, + .remove = as9716_32d_fan_remove, + .id_table = as9716_32d_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as9716_32d_fan_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as9716_32d_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-leds.c new file mode 100755 index 00000000..fd3367d4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-leds.c @@ -0,0 +1,492 @@ +/* + * A LED driver for the accton_as9716_32d_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as9716_32d_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_as9716_32d_led" + +struct accton_as9716_32d_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as9716_32d_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x61) + +#define LED_TYPE_DIAG_REG_MASK (0x1|0x2|0x4) +#define LED_MODE_DIAG_GREEN_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x02) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0) + + +#define LED_TYPE_LOC_REG_MASK (0x80|0x40) +#define LED_MODE_LOC_GREEN_BLIKN_VALUE 0x80 +#define LED_MODE_LOC_AMBER_VALUE 0x40 +#define LED_MODE_LOC_OFF_VALUE (0x0) + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_AMBER_VALUE 0x20 +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) +#define LED_MODE_PSU2_AMBER_VALUE 0x8 +#define LED_MODE_PSU2_GREEN_VALUE 0x4 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) +#define LED_MODE_PSU1_AMBER_VALUE 0x2 +#define LED_MODE_PSU1_GREEN_VALUE 0x1 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as9716_32d_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as9716_32d_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as9716_32d_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as9716_32d_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_as9716_32d_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as9716_32d_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as9716_32d_led_diag_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as9716_32d_led_loc_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_as9716_32d_led_fan_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_as9716_32d_led_psu1_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_as9716_32d_led_psu2_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as9716_32d_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as9716_32d_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_diag_set, + .brightness_get = accton_as9716_32d_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "accton_as9716_32d_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_loc_set, + .brightness_get = accton_as9716_32d_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "accton_as9716_32d_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_fan_set, + .brightness_get = accton_as9716_32d_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as9716_32d_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu1_set, + .brightness_get = accton_as9716_32d_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as9716_32d_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu2_set, + .brightness_get = accton_as9716_32d_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, +}; + +static int accton_as9716_32d_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_suspend(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_resume(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as9716_32d_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as9716_32d_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + } + + return ret; +} + +static int accton_as9716_32d_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as9716_32d_led_driver = { + .probe = accton_as9716_32d_led_probe, + .remove = accton_as9716_32d_led_remove, + .suspend = accton_as9716_32d_led_suspend, + .resume = accton_as9716_32d_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as9716_32d_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as9716_32d_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as9716_32d_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as9716_32d_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as9716_32d_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); +} + +module_init(accton_as9716_32d_led_init); +module_exit(accton_as9716_32d_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as9716_32d_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-psu.c new file mode 100755 index 00000000..b5aa9b79 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/modules/builds/x86-64-accton-as9716-32d-psu.c @@ -0,0 +1,311 @@ +/* + * An hwmon driver for accton as9716_32d Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as9716_32d_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER]; +}; + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev); + +enum as9716_32d_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as9716_32d_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as9716_32d_psu_group = { + .attrs = as9716_32d_psu_attributes, +}; + +static int as9716_32d_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_psu_remove(struct i2c_client *client) +{ + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as9716_32d_psu1, + as9716_32d_psu2 +}; + +static const struct i2c_device_id as9716_32d_psu_id[] = { + { "as9716_32d_psu1", as9716_32d_psu1 }, + { "as9716_32d_psu2", as9716_32d_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_psu_id); + +static struct i2c_driver as9716_32d_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as9716_32d_psu", + }, + .probe = as9716_32d_psu_probe, + .remove = as9716_32d_psu_remove, + .id_table = as9716_32d_psu_id, + .address_list = normal_i2c, +}; + +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as9716_32d update\n"); + + /* Read psu status */ + status = as9716_32d_cpld_read(0x60, 0x3); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as9716_32d_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as9716_32d_psu_read_block(client, 0x2e,data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as9716_32d_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as9716_32d_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/PKG.yml new file mode 100755 index 00000000..ec571a66 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as9716-32d ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/lib/Makefile new file mode 100755 index 00000000..46bc4719 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-as9716-32d +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_as9716_32d onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-as9716-32d.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..190fe375 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_as9716_32d onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/.gitignore new file mode 100755 index 00000000..e69de29b diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/.module new file mode 100755 index 00000000..7c458ec7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_as9716_32d diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/Makefile new file mode 100755 index 00000000..6b34c9e1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as9716_32d +AUTOMODULE := x86_64_accton_as9716_32d +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/README new file mode 100755 index 00000000..952aeeb4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as9716_32x README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/auto/x86_64_accton_as9716_32d.yml b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/auto/x86_64_accton_as9716_32d.yml new file mode 100755 index 00000000..fedd53b0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/auto/x86_64_accton_as9716_32d.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as9716_32d Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_ACCTON_AS9716_32D_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as9716_32d_config + + portingmacro: + x86_64_accton_as9716_32d: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d.x b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d.x new file mode 100755 index 00000000..91cc5e6e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_config.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_config.h new file mode 100755 index 00000000..8f3103b1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as9716_32d Configuration Header + * + * @addtogroup x86_64_accton_as9716_32d-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS9716_32D_CONFIG_H__ +#define __X86_64_ACCTON_AS9716_32D_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS9716_32D_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as9716_32d_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as9716_32d_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as9716_32d_config_settings table. */ +extern x86_64_accton_as9716_32d_config_settings_t x86_64_accton_as9716_32d_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as9716_32d_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as9716_32d_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as9716_32d_porting.h" + +#endif /* __X86_64_ACCTON_AS9716_32D_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_dox.h new file mode 100755 index 00000000..bcd26d48 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as9716_32d Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS9716_32D_DOX_H__ +#define __X86_64_ACCTON_AS9716_32D_DOX_H__ + +/** + * @defgroup x86_64_accton_as9716_32d x86_64_accton_as9716_32d - x86_64_accton_as9716_32d Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as9716_32d-x86_64_accton_as9716_32d Public Interface + * @defgroup x86_64_accton_as9716_32d-config Compile Time Configuration + * @defgroup x86_64_accton_as9716_32d-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS9716_32D_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_porting.h new file mode 100755 index 00000000..a57299a2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/inc/x86_64_accton_as9716_32d/x86_64_accton_as9716_32d_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as9716_32d Porting Macros. + * + * @addtogroup x86_64_accton_as9716_32d-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS9716_32D_PORTING_H__ +#define __X86_64_ACCTON_AS9716_32D_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS9716_32D_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS9716_32D_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS9716_32D_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_FREE free + #else + #error The macro X86_64_ACCTON_AS9716_32D_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS9716_32D_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS9716_32D_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS9716_32D_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS9716_32D_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_ACCTON_AS9716_32D_STRNCPY GLOBAL_STRNCPY + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_STRNCPY strncpy + #else + #error The macro X86_64_ACCTON_AS9716_32D_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS9716_32D_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS9716_32D_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS9716_32D_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS9716_32D_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS9716_32D_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS9716_32D_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS9716_32D_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS9716_32D_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS9716_32D_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..2a274b71 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as9716_32d_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as9716_32d_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as9716_32d_DEPENDMODULE_ENTRIES := init:x86_64_accton_as9716_32d ucli:x86_64_accton_as9716_32d + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..e0738d2b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as9716_32d_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..e82f8a77 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/fani.c @@ -0,0 +1,367 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include "platform_lib.h" + +#define PSU_PREFIX_PATH "/sys/bus/i2c/devices/" + +#define MAX_FAN_SPEED 25500 +#define MAX_PSU_FAN_SPEED 25500 + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +#define PSU_FAN_INFO(pid, fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5), + CHASSIS_FAN_INFO(6), + PSU_FAN_INFO(1,1), + PSU_FAN_INFO(2,1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value; + char path[64] = {0}; + + /* get fan present status + */ + sprintf(path, "%s""fan%d_present", FAN_BOARD_PATH, fid); + DEBUG_PRINT("Fan(%d), present path = (%s)", fid, path); + + if (onlp_file_read_int(&value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get fan fault status (turn on when any one fails) + */ + sprintf(path, "%s""fan%d_fault", FAN_BOARD_PATH, fid); + DEBUG_PRINT("Fan(%d), fault path = (%s)", fid, path); + + if (onlp_file_read_int(&value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + if (value > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + + /* get fan direction (both : the same) + */ + sprintf(path, "%s""fan%d_direction", FAN_BOARD_PATH, fid); + DEBUG_PRINT("Fan(%d), direction path = (%s)", fid, path); + + if (onlp_file_read_int(&value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + info->status |= value ? ONLP_FAN_STATUS_F2B : ONLP_FAN_STATUS_B2F; + + + /* get front fan speed + */ + sprintf(path, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid); + DEBUG_PRINT("Fan (%d), front speed path = (%s)", fid, path); + + if (onlp_file_read_int(&value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get rear fan speed + */ + sprintf(path, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid); + DEBUG_PRINT("Fan (%d), rear speed path = (%s)", fid, path); + + if (onlp_file_read_int(&value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + /* take the min value from front/rear fan speed + */ + if (info->rpm > value) { + info->rpm = value; + } + + /* get speed percentage from rpm + */ + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +static uint32_t +_onlp_get_fan_direction_on_psu(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) { + continue; + } + + if (PSU_TYPE_AC_F2B == psu_type) { + return ONLP_FAN_STATUS_F2B; + } + else { + return ONLP_FAN_STATUS_B2F; + } + } + + return 0; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int val = 0; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= _onlp_get_fan_direction_on_psu(); + + /* get fan fault status + */ + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_fault", &val) == ONLP_STATUS_OK) { + info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + } + + /* get fan speed + */ + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int fid; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) + { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + switch (fid) + { + case FAN_1_ON_PSU_1: + return psu_ym2651y_pmbus_info_set(PSU1_ID, "psu_fan_duty_cycle_percentage", p); + case FAN_1_ON_PSU_2: + return psu_ym2651y_pmbus_info_set(PSU2_ID, "psu_fan_duty_cycle_percentage", p); + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + path = FAN_NODE(fan_duty_cycle_percentage); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + DEBUG_PRINT("Fan path = (%s)", path); + + if (onlp_file_write_integer(path, p) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..0f2194c5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,273 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +#define prefix_path "/sys/class/leds/accton_as9716_32d_led::" +#define filename "brightness" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_DIAG, + LED_LOC, + LED_FAN, + LED_PSU1, + LED_PSU2 +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_BLUE, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_DIAG, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, + +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_LOC, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, + + +{LED_FAN, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_FAN, LED_MODE_AMBER, ONLP_LED_MODE_GREEN}, +{LED_FAN, LED_MODE_GREEN, ONLP_LED_MODE_ORANGE}, + +{LED_PSU1, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_PSU1, LED_MODE_AMBER, ONLP_LED_MODE_GREEN}, +{LED_PSU1, LED_MODE_GREEN, ONLP_LED_MODE_ORANGE}, + +{LED_PSU2, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_PSU2, LED_MODE_AMBER, ONLP_LED_MODE_GREEN}, +{LED_PSU2, LED_MODE_GREEN, ONLP_LED_MODE_ORANGE} +}; + +static char last_path[][10] = /* must map with onlp_led_id */ +{ + "reserved", + "diag", + "loc", + "fan", + "psu1", + "psu2" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_DIAG), "LED 1 (DIAG LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF |ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_LOC), "LED 2 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "LED 3 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF |ONLP_LED_CAPS_GREEN| ONLP_LED_CAPS_ORANGE , + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "LED 4 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF |ONLP_LED_CAPS_GREEN| ONLP_LED_CAPS_ORANGE , + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF |ONLP_LED_CAPS_GREEN| ONLP_LED_CAPS_ORANGE , + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF); + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_LOC), ONLP_LED_MODE_OFF); + + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + char data[2] = {0}; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Set LED mode */ + if (onlp_file_read_string(fullpath, data, sizeof(data), 0) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(local_id, atoi(data)); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int local_id; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + + if (onlp_file_write_integer(fullpath, onlp_to_driver_led_mode(local_id, mode)) != 0) + { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..6ab6bdff --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as9716_32d +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..fd562d1e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_accton_as9716_32d_log.h" + + +static int _onlp_file_write(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_WRONLY, S_IWUSR)) == -1) { + return -1; + } + + if ((len = write(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_write_integer(char *filename, int value) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return _onlp_file_write(filename, buf, (int)strlen(buf), 0); +} + +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 9 +#define I2C_PSU_FAN_DIR_LEN 3 + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + + /* Check model name */ + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_mfr_model) : PSU2_AC_PMBUS_NODE(psu_mfr_model); + memset(model_name, 0x0, I2C_PSU_MODEL_NAME_LEN + 1); + memset(modelname, 0x0, modelname_len); + if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) { + + return PSU_TYPE_UNKNOWN; + } + + if (!strncmp(model_name, "FSH082", strlen("FSH082"))) + { + if (modelname) + strncpy(modelname, model_name, strlen("FSH082")<(modelname_len-1)?strlen("FSH082"):(modelname_len-1)); + + return PSU_TYPE_ACBEL; + } + if (!strncmp(model_name, "YM-2651Y", strlen("YM-2651Y"))) + { + if (modelname) + strncpy(modelname, model_name, modelname_len-1); + return PSU_TYPE_YM2651Y; + } + + return PSU_TYPE_UNKNOWN; +} +int +psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + } + else { + sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + + + +int psu_ym2651y_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + } + else { + sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int psu_ym2651y_pmbus_info_set(int id, char *node, int value) +{ + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + switch (id) { + case PSU1_ID: + sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + break; + case PSU2_ID: + sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + }; + + if (onlp_file_write_integer(path, value) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +#define PSU_SERIAL_NUMBER_LEN 19 + +int psu_serial_number_get(int id, char *serial, int serial_len) +{ + int size = 0; + int ret = ONLP_STATUS_OK; + char *prefix = NULL; + + if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) { + return ONLP_STATUS_E_PARAM; + } + + prefix = (id == PSU1_ID) ? PSU1_AC_HWMON_PREFIX : PSU2_AC_HWMON_PREFIX; + + ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_serial_number"); + if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) { + return ONLP_STATUS_E_INTERNAL; + + } + serial[PSU_SERIAL_NUMBER_LEN-1] = '\0'; + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..57edf621 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,91 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include +#include "x86_64_accton_as9716_32d_log.h" + +#define CHASSIS_FAN_COUNT 6 +#define CHASSIS_THERMAL_COUNT 8 +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_LED_COUNT 5 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/10-0059/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/9-0058/" + + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/10-0051/" +#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/9-0050/" + + + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +#define FAN_BOARD_PATH "/sys/bus/i2c/devices/17-0066/" +#define FAN_NODE(node) FAN_BOARD_PATH#node + +#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + +int onlp_file_write_integer(char *filename, int value); +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_ym2651y_pmbus_info_get(int id, char *node, int *value); +int psu_ym2651y_pmbus_info_set(int id, char *node, int value); + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_ACBEL, + PSU_TYPE_YM2651Y, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +int psu_serial_number_get(int id, char *serial, int serial_len); + +//#define DEBUG_MODE 1 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..30b94fc8 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/psui.c @@ -0,0 +1,245 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +//#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + + if (PSU1_ID == id) { + sprintf(path, "%s%s", PSU1_AC_HWMON_PREFIX, node); + } + else if (PSU2_ID == id) { + sprintf(path, "%s%s", PSU2_AC_HWMON_PREFIX, node); + } + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_ym2651y_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + psu_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + + + +static int +psu_data_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_pmbus_info_get(index, "psu_v_in", &val) == 0) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_pmbus_info_get(index, "psu_i_in", &val) == 0) { + info->miin = val; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + if (psu_pmbus_info_get(index, "psu_p_in", &val) == 0) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + psu_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_present)\r\n", index); + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + /* Get PSU type + */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + + + switch (psu_type) { + case PSU_TYPE_ACBEL: + ret = psu_data_info_get(info); + break; + case PSU_TYPE_YM2651Y: + ret = psu_ym2651y_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..5e03edb0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,331 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_as9716_32d_int.h" +#include "x86_64_accton_as9716_32d_log.h" + +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" + +int sfp_map_bus[] ={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}; + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ + +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} +int +onlp_sfpi_map_bus_index(int port) +{ + if(port < 0 || port >=34) + return ONLP_STATUS_E_INTERNAL; + return sfp_map_bus[port]; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 34} + */ + int p; + + for(p = 0; p < 34; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + int bus, addr; + + if(port <0 || port > 34) + return ONLP_STATUS_E_INTERNAL; + + if(port >=0 && port < 16) + { + addr = 61; + bus = 20; + } + else + { + addr = 62; + bus = 21; + } + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[5]; + int i = 0; + uint64_t rx_los_all = 0; + + bytes[0]=bytes[1]=bytes[2]=bytes[3]=0x0; + bytes[4]=0x03; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + rx_los_all <<= 8; + rx_los_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + if(port <0 || port > 34) + return ONLP_STATUS_E_INTERNAL; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + int addr = 62; + int bus = 21; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if(port==32 || port==33) { + if (onlp_file_write_int(0, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + int addr = 62; + int bus = 21; + + switch(control) + { + case ONLP_SFP_CONTROL_RX_LOS: + { + if(port==32 || port==33) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + if(port==32 || port==33) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if(port==32 || port==33) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..4dfaa129 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,490 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include "x86_64_accton_as9716_32d_int.h" +#include "x86_64_accton_as9716_32d_log.h" + + +#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/" +#define NUM_OF_CPLD 3 +#define FAN_DUTY_CYCLE_MAX (100) +#define FAN_DUTY_CYCLE_DEFAULT (32) +#define FAN_DUTY_PLUS_FOR_DIR (13) +/* Note, all chassis fans share 1 single duty setting. + * Here use fan 1 to represent global fan duty value.*/ +#define FAN_ID_FOR_SET_FAN_DUTY (1) +#define CELSIUS_RECORD_NUMBER (2) /*Must >= 2*/ + +typedef struct fan_ctrl_policy { + int duty_cycle; /* In percetage */ + int step_up_thermal; /* In mini-Celsius */ + int step_dn_thermal; /* In mini-Celsius */ +} fan_ctrl_policy_t; + +static char arr_cplddev_name[NUM_OF_CPLD][10] = +{ + "4-0060", + "5-0062", + "6-0064" +}; + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as9716-32d-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 6 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 6 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD]={0}; + + for (i = 0; i < NUM_OF_CPLD; i++) { + v[i] = 0; + + if(onlp_file_read_int(v+i, "%s%s/version", PREFIX_PATH_ON_CPLD_DEV, arr_cplddev_name[i]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + } + pi->cpld_versions = aim_fstrdup("%d.%d.%d", v[0], v[1], v[2]); + + return 0; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +/* Thermal plan: + * $TMP = (CPU_core + LM75_1+ LM75_2 + LM75_3 + LM75_4)/5 + * 1. If any FAN failed, set all the other fans as full speed, 100%. + * 2. If any sensor is high than 45 degrees, set fan speed to duty 62.5%. + * 3. If any sensor is high than 50 degrees, set fan speed to duty 100%. + * 4. When $TMP >= 40 C, set fan speed to duty 62.5%. + * 5. When $TMP >= 45 C, set fan speed to duty 100%. + * 6. When $TMP < 35 C, set fan speed to duty 31.25%. + * 7. Direction factor, when B2F, duty + 12.5%. + * + * Note, all chassis fans share 1 single duty setting. + */ +fan_ctrl_policy_t fan_ctrl_policy_avg[] = { +{FAN_DUTY_CYCLE_MAX , 45000, INT_MIN}, +{63 , 40000, INT_MIN}, +{32 , INT_MAX, 35000}, +}; + +fan_ctrl_policy_t fan_ctrl_policy_single[] = { +{FAN_DUTY_CYCLE_MAX , 50000, INT_MIN}, +{63 , 45000, INT_MIN}, +}; + +struct fan_control_data_s { + int duty_cycle; + int dir_plus; + int mc_avg_pre[CELSIUS_RECORD_NUMBER]; + int mc_high_pre[CELSIUS_RECORD_NUMBER]; + +} fan_control_data_pre = +{ + .duty_cycle = FAN_DUTY_CYCLE_DEFAULT, + .dir_plus = 0, + .mc_avg_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/ + .mc_high_pre = {INT_MIN+1, INT_MIN}, /*init as thermal rising to avoid full speed.*/ + +}; + +static int +sysi_check_fan(uint32_t *fan_dir){ + int i, present; + + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) + { + onlp_fan_info_t fan_info; + + if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); + return ONLP_STATUS_E_INTERNAL; + } + + present = fan_info.status & ONLP_FAN_STATUS_PRESENT; + if ((fan_info.status & ONLP_FAN_STATUS_FAILED) || !present) { + AIM_LOG_WARN("Fan(%d) is not working, set the other fans as full speed\r\n", i); + int ret = onlp_fani_percentage_set( + ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY), FAN_DUTY_CYCLE_MAX); + if (ret != ONLP_STATUS_OK) + return ret; + else + return ONLP_STATUS_E_MISSING; + } + + /* Get fan direction (Only get the first one since all fan direction are the same) + */ + if (i == 1) { + *fan_dir = fan_info.status & (ONLP_FAN_STATUS_F2B|ONLP_FAN_STATUS_B2F); + } + } + + return ONLP_STATUS_OK; +} + +static int +sysi_get_fan_duty(int *cur_duty_cycle){ + int fd, len; + char buf[10] = {0}; + char *node = FAN_NODE(fan_duty_cycle_percentage); + + /* Get current fan duty*/ + fd = open(node, O_RDONLY); + if (fd == -1){ + AIM_LOG_ERROR("Unable to open fan speed control node (%s)", node); + return ONLP_STATUS_E_INTERNAL; + } + + len = read(fd, buf, sizeof(buf)); + close(fd); + if (len <= 0) { + AIM_LOG_ERROR("Unable to read fan speed from (%s)", node); + return ONLP_STATUS_E_INTERNAL; + } + *cur_duty_cycle = atoi(buf); + + return ONLP_STATUS_OK; +} + +static int +sysi_get_thermal_sum(int *mcelsius){ + onlp_thermal_info_t thermal_info; + int i; + + *mcelsius = 0; + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info) + != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + *mcelsius += thermal_info.mcelsius; + + DEBUG_PRINT("Thermal %d: %d \n ", i, thermal_info.mcelsius); + + } + + return ONLP_STATUS_OK; + +} + +static int +sysi_get_highest_thermal(int *mcelsius){ + onlp_thermal_info_t thermal_info; + int i, highest; + + highest = 0; + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal_info) + != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + highest = (thermal_info.mcelsius > highest)? + thermal_info.mcelsius : highest; + } + *mcelsius = highest; + return ONLP_STATUS_OK; +} + +/* Anaylze thermal changing history to judge if the change is a stable trend. */ +static int _is_thermal_a_trend(int *mc_history){ + int i, trend, trended; + + if (mc_history == NULL) { + AIM_LOG_ERROR("Unable to get history of thermal\n"); + return 0; + } + + /* Get heat up/down trend. */ + trend = 0; + for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { + if (( mc_history[i+1] < mc_history[i])){ + trend++; + }else if (( mc_history[i+1] > mc_history[i])){ + trend--; + } + } + + trended = (abs(trend) >= ((CELSIUS_RECORD_NUMBER+1)/2))? 1:0; +#if (DEBUG_MODE == 1) + DEBUG_PRINT("[INFO]%s#%d, trended: %d, UP/DW: %d mcelsius:", + __func__, __LINE__, trended, trend ); + for (i = 0; i <= CELSIUS_RECORD_NUMBER; i++) { + DEBUG_PRINT(" %d =>", mc_history[i]); + } + DEBUG_PRINT("%c\n", ' '); +#endif + + /*For more than half changes are same direction, it's a firm trend.*/ + return trended; +} + + +/* Decide duty by highest value of thermal sensors.*/ +static int +sysi_get_duty_by_highest(int *duty_cycle){ + int i, ret, maxtrix_len; + int new_duty_cycle = 0 ; + int mc_history[CELSIUS_RECORD_NUMBER+1] = {0}; + int *mcelsius_pre_p = &mc_history[1]; + int *mcelsius_now_p = &mc_history[0]; + + /* Fill up mcelsius array, + * [0] is current temperature, others are history. + */ + ret = sysi_get_highest_thermal(mcelsius_now_p); + if(ONLP_STATUS_OK != ret){ + return ret; + } + memcpy (mcelsius_pre_p, fan_control_data_pre.mc_high_pre, + sizeof(fan_control_data_pre.mc_high_pre)); + + DEBUG_PRINT("[INFO]%s#%d, highest mcelsius:%d!\n", + __func__, __LINE__, *mcelsius_now_p); + + /* Shift records to the right */ + for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { + fan_control_data_pre.mc_high_pre[i] = mc_history[i]; + } + + /* Only change duty on consecutive heat rising or falling.*/ + maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_single); + + /* Only change duty when the thermal changing are firm. */ + if (_is_thermal_a_trend(mc_history)) + { + int matched = 0; + for (i = 0; i < maxtrix_len; i++) { + if ((*mcelsius_now_p > fan_ctrl_policy_single[i].step_up_thermal)) { + new_duty_cycle = fan_ctrl_policy_single[i].duty_cycle; + matched = !matched; + break; + } + } +/* if (!matched) { + DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n", + __func__, __LINE__, *mcelsius_now_p); + } */ + } + *duty_cycle = new_duty_cycle; + return ONLP_STATUS_OK; +} + +/* Decide duty by average value of thermal sensors.*/ +static int +sysi_get_duty_by_average(int *duty_cycle){ + int i, mcelsius_avg, ret, maxtrix_len; + int new_duty_cycle=0; + int mc_history[CELSIUS_RECORD_NUMBER+1] = {0}; + int *mcelsius_pre_p = &mc_history[1]; + int *mcelsius_now_p = &mc_history[0]; + + /* Fill up mcelsius array, + * [0] is current temperature, others are history. + */ + *mcelsius_now_p = 0; + ret = sysi_get_thermal_sum(mcelsius_now_p); + if(ONLP_STATUS_OK != ret){ + return ret; + } + mcelsius_avg = (*mcelsius_now_p)/CHASSIS_THERMAL_COUNT; + + memcpy (mcelsius_pre_p, fan_control_data_pre.mc_avg_pre, + sizeof(fan_control_data_pre.mc_avg_pre)); + + DEBUG_PRINT("[INFO]%s#%d, mcelsius:%d!\n", __func__, __LINE__, mcelsius_avg); + + /* Shift records to the right */ + for (i = 0; i < CELSIUS_RECORD_NUMBER; i++) { + fan_control_data_pre.mc_avg_pre[i] = mc_history[i]; + } + + /* Only change duty on consecutive heat rising or falling.*/ + maxtrix_len = AIM_ARRAYSIZE(fan_ctrl_policy_avg); + + /* Only change duty when the thermal changing are firm. */ + if (_is_thermal_a_trend(mc_history)) + { + int matched = 0; + for (i = 0; i < maxtrix_len; i++) { + if ((mcelsius_avg >= fan_ctrl_policy_avg[i].step_up_thermal)) { + new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle; + matched = !matched; + break; + } + } + for (i = maxtrix_len-1; i>=0; i--) { + if ((mcelsius_avg < fan_ctrl_policy_avg[i].step_dn_thermal)) { + new_duty_cycle = fan_ctrl_policy_avg[i].duty_cycle; + matched = !matched; + break; + } + } + /*if (!matched) { + DEBUG_PRINT("%s#%d, celsius(%d) falls into undefined range!!\n", + __func__, __LINE__, mcelsius_avg); + } */ + } + + *duty_cycle = new_duty_cycle; + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_fans(void) +{ + uint32_t fan_dir; + int ret; + int cur_duty_cycle, new_duty_cycle, tmp; + int direct_addon = 0; + onlp_oid_t fan_duty_oid = ONLP_FAN_ID_CREATE(FAN_ID_FOR_SET_FAN_DUTY); + + /********************************************************** + * Decision 1: Set fan as full speed if any fan is failed. + **********************************************************/ + ret = sysi_check_fan(&fan_dir); + if(ONLP_STATUS_OK != ret){ + return ret; + } + + if (fan_dir & ONLP_FAN_STATUS_B2F) { + direct_addon = FAN_DUTY_PLUS_FOR_DIR; + } + + /********************************************************** + * Decision 2: If no matched fan speed is found from the policy, + * use FAN_DUTY_CYCLE_MIN as default speed + **********************************************************/ + ret = sysi_get_fan_duty(&cur_duty_cycle); + if(ONLP_STATUS_OK != ret){ + return ret; + } + + /********************************************************** + * Decision 3: Decide new fan speed depend on fan direction and temperature + **********************************************************/ + ret = sysi_get_duty_by_average(&new_duty_cycle); + if (ONLP_STATUS_OK != ret){ + return ret; + } + ret = sysi_get_duty_by_highest(&tmp); + if (ONLP_STATUS_OK != ret){ + return ret; + } + + new_duty_cycle = (tmp > new_duty_cycle)? tmp : new_duty_cycle; + if (new_duty_cycle == 0) + { + new_duty_cycle = fan_control_data_pre.duty_cycle; + } else { + fan_control_data_pre.duty_cycle = new_duty_cycle; + } + fan_control_data_pre.dir_plus = direct_addon; + DEBUG_PRINT("[INFO]%s#%d, new duty: %d = %d + %d (%d)!\n", __func__, __LINE__, + new_duty_cycle + direct_addon, new_duty_cycle, direct_addon, cur_duty_cycle); + + new_duty_cycle += direct_addon; + new_duty_cycle = (new_duty_cycle > FAN_DUTY_CYCLE_MAX)? + FAN_DUTY_CYCLE_MAX : new_duty_cycle; + + if (new_duty_cycle == cur_duty_cycle) { + /* Duty cycle does not change, just return */ + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(fan_duty_oid, new_duty_cycle); +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..2cce397c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,188 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +//#include +#include +#include +#include "platform_lib.h" + +#define THERMAL_PATH_FORMAT "/sys/bus/i2c/devices/%s/*temp1_input" +#define PSU_THERMAL_PATH_FORMAT "/sys/bus/i2c/devices/%s/*psu_temp1_input" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_6_ON_MAIN_BROAD, + THERMAL_7_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +static char* directory[] = /* must map with onlp_thermal_id */ +{ + NULL, + NULL, /* CPU_CORE files */ + "18-0048", + "18-0049", + "18-004a", + "18-004b", + "18-004c", + "18-004e", + "18-004f", + "10-0059", + "9-0058", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0*temp2_input", + "/sys/devices/platform/coretemp.0*temp3_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-48", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2-49", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3-4A", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4-4B", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "LM75-5-4C", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BROAD), "LM75-6-4E", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_7_ON_MAIN_BROAD), "LM75-7-4F", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + char *format = NULL; + char path[64] = {0}; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + if(tid == THERMAL_CPU_CORE) { + return onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + } + + switch (tid) { + case THERMAL_1_ON_MAIN_BROAD: + case THERMAL_2_ON_MAIN_BROAD: + case THERMAL_3_ON_MAIN_BROAD: + case THERMAL_4_ON_MAIN_BROAD: + case THERMAL_5_ON_MAIN_BROAD: + case THERMAL_6_ON_MAIN_BROAD: + case THERMAL_7_ON_MAIN_BROAD: + format = THERMAL_PATH_FORMAT; + break; + case THERMAL_1_ON_PSU1: + case THERMAL_1_ON_PSU2: + format = PSU_THERMAL_PATH_FORMAT; + break; + default: + return ONLP_STATUS_E_INVALID; + }; + + /* get path */ + sprintf(path, format, directory[tid], tid); + if (onlp_file_read_int(&info->mcelsius, path) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_config.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_config.c new file mode 100755 index 00000000..ab3f5eca --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(_x) __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(_x) +x86_64_accton_as9716_32d_config_settings_t x86_64_accton_as9716_32d_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_STDLIB(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_UCLI(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as9716_32d_config_STRINGIFY_NAME(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE(X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS9716_32D_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as9716_32d_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as9716_32d_config_STRINGIFY_VALUE +#undef __x86_64_accton_as9716_32d_config_STRINGIFY_NAME + +const char* +x86_64_accton_as9716_32d_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as9716_32d_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as9716_32d_config_settings[i].name, setting)) { + return x86_64_accton_as9716_32d_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as9716_32d_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as9716_32d_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as9716_32d_config_settings[i].name, x86_64_accton_as9716_32d_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_enums.c new file mode 100755 index 00000000..d8a78052 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_int.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_int.h new file mode 100755 index 00000000..d7cdd0dc --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as9716_32x Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as9716_32d_INT_H__ +#define __x86_64_accton_as9716_32d_INT_H__ + +#include + + +#endif /* __x86_64_accton_as9716_32d_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.c new file mode 100755 index 00000000..1c574de5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as9716_32d_log.h" +/* + * x86_64_accton_as9716_32d log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS9716_32D_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS9716_32D_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS9716_32D_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.h b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.h new file mode 100755 index 00000000..63a4ae5d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as9716_32d_LOG_H__ +#define __x86_64_accton_as9716_32d_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as9716_32d +#include + +#endif /* __x86_64_accton_as9716_32d_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_module.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_module.c new file mode 100755 index 00000000..d3a8d966 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as9716_32d_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as9716_32d_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_as9716_32d_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_ucli.c new file mode 100755 index 00000000..25a3c13a --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/onlp/builds/src/module/src/x86_64_accton_as9716_32d_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as9716_32d_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as9716_32d_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as9716_32d) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as9716_32d_ucli_module__ = + { + "x86_64_accton_as9716_32d_ucli", + NULL, + x86_64_accton_as9716_32d_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as9716_32d_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as9716_32d_ucli_module__); + n = ucli_node_create("x86_64_accton_as9716_32d", NULL, &x86_64_accton_as9716_32d_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as9716_32d")); + return n; +} + +#else +void* +x86_64_accton_as9716_32d_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/PKG.yml new file mode 100755 index 00000000..26735549 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as9716-32d REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/lib/x86-64-accton-as9716-32d-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/lib/x86-64-accton-as9716-32d-r0.yml new file mode 100755 index 00000000..35f03e03 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/lib/x86-64-accton-as9716-32d-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for AS9716 +# +###################################################################### + +x86-64-accton-as9716-32d-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/python/x86_64_accton_as9716_32d_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/python/x86_64_accton_as9716_32d_r0/__init__.py new file mode 100755 index 00000000..197ea810 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as9716_32d/platform-config/r0/src/python/x86_64_accton_as9716_32d_r0/__init__.py @@ -0,0 +1,78 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as9716_32d_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x25_6x100): + + PLATFORM='x86-64-accton-as9716-32d-r0' + MODEL="AS9716-32D" + SYS_OBJECT_ID=".9716.32" + + def baseconfig(self): + self.insmod('optoe') + self.insmod('accton_i2c_psu') + for m in [ 'cpld', 'fan', 'psu', 'leds' ]: + self.insmod("x86-64-accton-as9716-32d-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + # initialize multiplexer (PCA9548) + self.new_i2c_device('pca9548', 0x77, 0) + # initiate multiplexer (PCA9548) + self.new_i2c_devices( + [ + # initiate multiplexer (PCA9548) + ('pca9548', 0x72, 1), + ('pca9548', 0x76, 1), + ] + ) + self.new_i2c_devices( + [ + # initiate multiplexer (PCA9548) + ('pca9548', 0x72, 2), + ('pca9548', 0x73, 2), + ('pca9548', 0x74, 2), + ('pca9548', 0x75, 2), + ('pca9548', 0x76, 2) + ] + ) + self.new_i2c_devices([ + # initialize CPLD + #initiate CPLD + ('as9716_32d_fpga', 0x60, 19), + ('as9716_32d_cpld1', 0x61, 20), + ('as9716_32d_cpld2', 0x62, 21), + ('as9716_32d_cpld_cpu', 0x65, 0), + ]) + self.new_i2c_devices([ + # initiate fan + # initiate chassis fan + ('as9716_32d_fan', 0x66, 17), + + # inititate LM75 + ('lm75', 0x48, 18), + ('lm75', 0x49, 18), + ('lm75', 0x4a, 18), + ('lm75', 0x4b, 18), + ('lm75', 0x4c, 18), + ('lm75', 0x4e, 18), + ('lm75', 0x4f, 18), + ]) + + self.new_i2c_devices([ + # initiate PSU-2 + ('as9716_32d_psu2', 0x51, 10), + ('acbel_fsh082', 0x59, 10), + + # initiate PSU-1 + ('as9716_32d_psu1', 0x50, 9), + ('acbel_fsh082', 0x58, 9), + ]) + + # initialize QSFP port 1~34 + for port in range(1, 35): + self.new_i2c_device('optoe1', 0x50, port+24) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+24), shell=True) + + + self.new_i2c_device('24c02', 0x56, 0) + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/.gitignore new file mode 100755 index 00000000..b8068c1f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*asxvolt16*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/PKG.yml new file mode 100755 index 00000000..396e1e17 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-asxvolt16 ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/.gitignore new file mode 100755 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/Makefile new file mode 100755 index 00000000..0f540925 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-asxvolt16 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-cpld.c new file mode 100755 index 00000000..7125c280 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-cpld.c @@ -0,0 +1,250 @@ +/* + * A hwmon driver for the asxvolt16_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 +#include + +#define CPLD_VERSION_REG 0x2 +#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; +}; + +/* Addresses scanned for asxvolt16_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, CPLD_VERSION_REG); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, CPLD_VERSION_REG, val); + } + + return sprintf(buf, "%d\n", val); +} + +static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); + +static void asxvolt16_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 asxvolt16_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 asxvolt16_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"); + asxvolt16_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int asxvolt16_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_file(&client->dev.kobj, &ver.attr); + asxvolt16_cpld_remove_client(client); + + return 0; +} + +enum cpld_chips +{ + asxvolt16_cpld, + asxvolt16_fpga +}; + +static const struct i2c_device_id asxvolt16_cpld_id[] = { + { "asxvolt16_cpld", asxvolt16_cpld }, + { "asxvolt16_fpga", asxvolt16_fpga }, + {} +}; +MODULE_DEVICE_TABLE(i2c, asxvolt16_cpld_id); + +static struct i2c_driver asxvolt16_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "asxvolt16_cpld", + }, + .probe = asxvolt16_cpld_probe, + .remove = asxvolt16_cpld_remove, + .id_table = asxvolt16_cpld_id, + .address_list = normal_i2c, +}; + +int asxvolt16_cpld_read(unsigned short cpld_addr, u8 reg) +{ + 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) { + int retry = I2C_RW_RETRY_COUNT; + + while (retry) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + if (unlikely(ret < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(asxvolt16_cpld_read); + +int asxvolt16_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) { + int retry = I2C_RW_RETRY_COUNT; + + while (retry) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + if (unlikely(ret < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(asxvolt16_cpld_write); + +static int __init asxvolt16_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&asxvolt16_cpld_driver); +} + +static void __exit asxvolt16_cpld_exit(void) +{ + i2c_del_driver(&asxvolt16_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_asxvolt16 driver"); +MODULE_LICENSE("GPL"); + +module_init(asxvolt16_cpld_init); +module_exit(asxvolt16_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-fan.c new file mode 100755 index 00000000..83744397 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-fan.c @@ -0,0 +1,513 @@ +/* + * A hwmon driver for the Accton asxvolt16 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 + +#define DRVNAME "asxvolt16_fan" + +static struct asxvolt16_fan_data *asxvolt16_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[] = { + 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 asxvolt16_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, + 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) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6); +/* 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); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6); +/* 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(); + +static struct attribute *asxvolt16_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_FAULT_ATTR(6), + 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_SPEED_RPM_ATTR(6), + 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(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static int asxvolt16_fan_read_value(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 asxvolt16_fan_write_value(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; +} + +/* 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 asxvolt16_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; + + asxvolt16_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + asxvolt16_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 asxvolt16_fan_data *data = asxvolt16_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 asxvolt16_fan_group = { + .attrs = asxvolt16_fan_attributes, +}; + +static struct asxvolt16_fan_data *asxvolt16_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct asxvolt16_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 asxvolt16_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = asxvolt16_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 asxvolt16_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct asxvolt16_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct asxvolt16_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, &asxvolt16_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, &asxvolt16_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int asxvolt16_fan_remove(struct i2c_client *client) +{ + struct asxvolt16_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &asxvolt16_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id asxvolt16_fan_id[] = { + { "asxvolt16_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, asxvolt16_fan_id); + +static struct i2c_driver asxvolt16_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = asxvolt16_fan_probe, + .remove = asxvolt16_fan_remove, + .id_table = asxvolt16_fan_id, + .address_list = normal_i2c, +}; + +static int __init asxvolt16_fan_init(void) +{ + return i2c_add_driver(&asxvolt16_fan_driver); +} + +static void __exit asxvolt16_fan_exit(void) +{ + i2c_del_driver(&asxvolt16_fan_driver); +} + +module_init(asxvolt16_fan_init); +module_exit(asxvolt16_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("asxvolt16_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-leds.c new file mode 100755 index 00000000..da47c54d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-leds.c @@ -0,0 +1,378 @@ +/* + * A LED driver for the accton_asxvolt16_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 "asxvolt16_led" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int asxvolt16_cpld_read(unsigned short cpld_addr, u8 reg); +extern int asxvolt16_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct accton_asxvolt16_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 accton_asxvolt16_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x62) + +#define LED_TYPE_DIAG_REG_MASK (0x2) +#define LED_MODE_DIAG_AMBER_VALUE (0x2) +#define LED_MODE_DIAG_GREEN_VALUE (0x0) + +#define LED_TYPE_LOC_REG_MASK (0x1) +#define LED_MODE_LOC_AMBER_VALUE (0x0) +#define LED_MODE_LOC_OFF_VALUE (0x1) + +static const u8 led_reg[] = { + 0x39, /* LOC/DIAG 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_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_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} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int accton_asxvolt16_led_read_value(u8 reg) +{ + return asxvolt16_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int accton_asxvolt16_led_write_value(u8 reg, u8 value) +{ + return asxvolt16_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void accton_asxvolt16_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_asxvolt16_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_asxvolt16_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_asxvolt16_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_asxvolt16_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_asxvolt16_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_asxvolt16_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asxvolt16_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_asxvolt16_led_diag_get(struct led_classdev *cdev) +{ + accton_asxvolt16_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_asxvolt16_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + /* LOC led is read-only */ +} + +static enum led_brightness accton_asxvolt16_led_loc_get(struct led_classdev *cdev) +{ + //accton_asxvolt16_led_update(); + //return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); + return LED_MODE_OFF; +} + +static void accton_asxvolt16_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_asxvolt16_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_asxvolt16_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_asxvolt16_led::diag", + .default_trigger = "unused", + .brightness_set = accton_asxvolt16_led_diag_set, + .brightness_get = accton_asxvolt16_led_diag_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_LOC] = { + .name = "accton_asxvolt16_led::loc", + .default_trigger = "unused", + .brightness_set = accton_asxvolt16_led_loc_set, + .brightness_get = accton_asxvolt16_led_loc_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_FAN] = { + .name = "accton_asxvolt16_led::fan", + .default_trigger = "unused", + .brightness_set = accton_asxvolt16_led_auto_set, + .brightness_get = accton_asxvolt16_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_asxvolt16_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_asxvolt16_led_auto_set, + .brightness_get = accton_asxvolt16_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_asxvolt16_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_asxvolt16_led_auto_set, + .brightness_get = accton_asxvolt16_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + + +static int accton_asxvolt16_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_asxvolt16_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_asxvolt16_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_asxvolt16_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_asxvolt16_leds[i]); + } + } + + return ret; +} + +static int accton_asxvolt16_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_asxvolt16_leds); i++) { + led_classdev_unregister(&accton_asxvolt16_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_asxvolt16_led_driver = { + .probe = accton_asxvolt16_led_probe, + .remove = accton_asxvolt16_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_asxvolt16_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_asxvolt16_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_asxvolt16_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&accton_asxvolt16_led_driver); +exit: + return ret; +} + +static void __exit accton_asxvolt16_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_asxvolt16_led_driver); + kfree(ledctl); +} + +late_initcall(accton_asxvolt16_led_init); +module_exit(accton_asxvolt16_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_asxvolt16_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-psu.c new file mode 100755 index 00000000..91fa50ce --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-psu.c @@ -0,0 +1,245 @@ +/* + * An hwmon driver for accton asxvolt16 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 0x8 + +#define MODEL_NAME_LEN 8 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x2e + +#define IS_POWER_GOOD(id, value) (!(value & BIT(7-id))) +#define IS_PRESENT(id, value) (!(value & BIT(1-id))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +extern int asxvolt16_cpld_read(unsigned short cpld_addr, u8 reg); +static struct asxvolt16_psu_data *asxvolt16_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 asxvolt16_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 asxvolt16_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 *asxvolt16_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 asxvolt16_psu_data *data = asxvolt16_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 const struct attribute_group asxvolt16_psu_group = { + .attrs = asxvolt16_psu_attributes, +}; + +static int asxvolt16_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct asxvolt16_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct asxvolt16_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, &asxvolt16_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, &asxvolt16_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int asxvolt16_psu_remove(struct i2c_client *client) +{ + struct asxvolt16_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &asxvolt16_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + asxvolt16_psu1, + asxvolt16_psu2 +}; + +static const struct i2c_device_id asxvolt16_psu_id[] = { + { "asxvolt16_psu1", asxvolt16_psu1 }, + { "asxvolt16_psu2", asxvolt16_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, asxvolt16_psu_id); + +static struct i2c_driver asxvolt16_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "asxvolt16_psu", + }, + .probe = asxvolt16_psu_probe, + .remove = asxvolt16_psu_remove, + .id_table = asxvolt16_psu_id, + .address_list = normal_i2c, +}; + +static struct asxvolt16_psu_data *asxvolt16_psu_update_device(struct device *dev, u8 update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct asxvolt16_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 asxvolt16 update\n"); + + /* Read psu status */ + status = asxvolt16_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 asxvolt16_psu_init(void) +{ + return i2c_add_driver(&asxvolt16_psu_driver); +} + +static void __exit asxvolt16_psu_exit(void) +{ + i2c_del_driver(&asxvolt16_psu_driver); +} + +module_init(asxvolt16_psu_init); +module_exit(asxvolt16_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("asxvolt16_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-sfp.c new file mode 100755 index 00000000..3130d160 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/modules/builds/x86-64-accton-asxvolt16-sfp.c @@ -0,0 +1,1783 @@ +/* + * SFP driver for accton asxvolt16 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 "asxvolt16_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 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 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* 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 + +#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 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); +extern int asxvolt16_cpld_read(unsigned short cpld_addr, u8 reg); +extern int asxvolt16_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_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, 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_los, S_IRUGO, sfp_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 +}; + +/* XFP attributes for sysfs */ +static struct attribute *xfp_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_tx_disable.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +asxvolt16_sfp1, asxvolt16_sfp2, asxvolt16_sfp3, asxvolt16_sfp4, +asxvolt16_sfp5, asxvolt16_sfp6, asxvolt16_sfp7, asxvolt16_sfp8, +asxvolt16_sfp9, asxvolt16_sfp10, asxvolt16_sfp11, asxvolt16_sfp12, +asxvolt16_sfp13, asxvolt16_sfp14, asxvolt16_sfp15, asxvolt16_sfp16, +asxvolt16_sfp17, asxvolt16_sfp18, asxvolt16_sfp19, asxvolt16_sfp20 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(asxvolt16_sfp1), +I2C_DEV_ID(asxvolt16_sfp2), +I2C_DEV_ID(asxvolt16_sfp3), +I2C_DEV_ID(asxvolt16_sfp4), +I2C_DEV_ID(asxvolt16_sfp5), +I2C_DEV_ID(asxvolt16_sfp6), +I2C_DEV_ID(asxvolt16_sfp7), +I2C_DEV_ID(asxvolt16_sfp8), +I2C_DEV_ID(asxvolt16_sfp9), +I2C_DEV_ID(asxvolt16_sfp10), +I2C_DEV_ID(asxvolt16_sfp11), +I2C_DEV_ID(asxvolt16_sfp12), +I2C_DEV_ID(asxvolt16_sfp13), +I2C_DEV_ID(asxvolt16_sfp14), +I2C_DEV_ID(asxvolt16_sfp15), +I2C_DEV_ID(asxvolt16_sfp16), +I2C_DEV_ID(asxvolt16_sfp17), +I2C_DEV_ID(asxvolt16_sfp18), +I2C_DEV_ID(asxvolt16_sfp19), +I2C_DEV_ID(asxvolt16_sfp20), +{ /* 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 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 xfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable */ + 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 */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct xfp_data *xfp; + 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[] = {0x05, 0x07, 0x25}; + int reg_values[3] = {0}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~20 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = asxvolt16_cpld_read(0x62, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x62) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); + //data->present |= (u64)status << (i*8); + reg_values[i] = status; + } + + data->present |= (reg_values[1] & 0x40) >> 6; /* port 0 */ + data->present |= (reg_values[1] & 0x80) >> 6; /* port 1 */ + data->present |= (reg_values[0] & 0x10) >> 2; /* port 2 */ + data->present |= (reg_values[0] & 0x20) >> 2; /* port 3 */ + data->present |= (reg_values[0] & 0x04) << 2; /* port 4 */ + data->present |= (reg_values[0] & 0x08) << 2; /* port 5 */ + data->present |= (reg_values[0] & 0x01) << 6; /* port 6 */ + data->present |= (reg_values[0] & 0x02) << 6; /* port 7 */ + + data->present |= (reg_values[0] & 0x40) << 2; /* port 8 */ + data->present |= (reg_values[0] & 0x80) << 2; /* port 9 */ + data->present |= (reg_values[1] & 0x01) << 10; /* port 10 */ + data->present |= (reg_values[1] & 0x02) << 10; /* port 11 */ + data->present |= (reg_values[1] & 0x04) << 10; /* port 12 */ + data->present |= (reg_values[1] & 0x08) << 10; /* port 13 */ + data->present |= (reg_values[1] & 0x10) << 10; /* port 14 */ + data->present |= (reg_values[1] & 0x20) << 10; /* port 15 */ + + data->present |= (reg_values[2] & 0xF) << 16; /* port 16 ~ 19 */ + + data->present &= 0xFFFFF; + 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 j = 0; + int status = -1; + + if (time_before(jiffies, data->xfp->last_updated + HZ + HZ / 2) && data->xfp->valid) { + return data; + } + + DEBUG_PRINT("Starting asxvolt16 sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->xfp->valid = 0; + memset(data->xfp->status, 0, sizeof(data->xfp->status)); + + /* Read status of port 1~16(XFP port) */ + for (j = 0; j < 4; j++) { + u8 reg = 0x11 + j*2; + + status = asxvolt16_cpld_read(0x62, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x62) reg(0x%x) err %d\n", reg, status); + goto exit; + } + + data->xfp->status[j/2] |= (u64)status << ((j%2)*8); + } + + data->xfp->valid = 1; + data->xfp->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); + 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); + + cpld_reg = (data->port <= asxvolt16_sfp8) ? 0x15 : 0x17; + cpld_bit = 1 << (data->port % 8); + + /* Read current status */ + cpld_val = asxvolt16_cpld_read(0x62, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->xfp->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->xfp->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + asxvolt16_cpld_write(0x62, 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)) ? 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[3] = {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 -> 20 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + 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; +} + +/* 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 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 (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); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + default: + return 0; + } + + val = !!(data->xfp->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; + } + +#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 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 xfp_group = { + .attrs = xfp_attributes, +}; + +static int xfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct xfp_data **data) +{ + int status; + struct xfp_data *xfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + xfp = kzalloc(sizeof(struct xfp_data), GFP_KERNEL); + if (!xfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &xfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &xfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &xfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = xfp; + dev_info(&client->dev, "xfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &xfp_group); +exit_free: + kfree(xfp); +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; + } + + 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 >= asxvolt16_sfp1 && dev_id->driver_data <= asxvolt16_sfp16) { + data->driver_type = DRIVER_TYPE_XFP; + ret = xfp_probe(client, dev_id, &data->xfp); + } + else { /* asxvolt16_sfp17 ~ asxvolt16_sfp20 */ + 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 xfp_remove(struct i2c_client *client, struct xfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &xfp_group); + kfree(data); + return 0; +} + +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); + + switch (data->driver_type) { + case DRIVER_TYPE_XFP: + ret = xfp_remove(client, data->xfp); + break; + case DRIVER_TYPE_QSFP: + ret = qsfp_remove(client, data->qsfp); + break; + } + +#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 asxvolt16_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/PKG.yml new file mode 100755 index 00000000..19442f27 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-asxvolt16 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/lib/Makefile new file mode 100755 index 00000000..6d342795 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-asxvolt16 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_asxvolt16 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-asxvolt16.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..c734569c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_asxvolt16 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/.module new file mode 100755 index 00000000..359ccbc2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_asxvolt16 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/Makefile new file mode 100755 index 00000000..4ae7bf99 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_asxvolt16 +AUTOMODULE := x86_64_accton_asxvolt16 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/README new file mode 100755 index 00000000..9b99d573 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_asxvolt16 README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..4a9ee806 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_asxvolt16 Autogeneration +# +############################################################################### +x86_64_accton_asxvolt16_AUTO_DEFS := module/auto/x86_64_accton_asxvolt16.yml +x86_64_accton_asxvolt16_AUTO_DIRS := module/inc/x86_64_accton_asxvolt16 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/x86_64_accton_asxvolt16.yml b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/x86_64_accton_asxvolt16.yml new file mode 100755 index 00000000..36b059a4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/auto/x86_64_accton_asxvolt16.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_asxvolt16 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB +- x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_accton_asxvolt16_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_asxvolt16_config + + portingmacro: + x86_64_accton_asxvolt16: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16.x b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16.x new file mode 100755 index 00000000..cd7aa68b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_config.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_config.h new file mode 100755 index 00000000..2b7a4627 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_asxvolt16 Configuration Header + * + * @addtogroup x86_64_accton_asxvolt16-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_asxvolt16_CONFIG_H__ +#define __x86_64_accton_asxvolt16_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_accton_asxvolt16_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING +#define x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT +#define x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB +#define x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI +#define x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_asxvolt16_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_asxvolt16_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_asxvolt16_config_settings table. */ +extern x86_64_accton_asxvolt16_config_settings_t x86_64_accton_asxvolt16_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_asxvolt16_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_asxvolt16_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_asxvolt16_porting.h" + +#endif /* __x86_64_accton_asxvolt16_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_dox.h new file mode 100755 index 00000000..ae43964d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_asxvolt16 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_asxvolt16_DOX_H__ +#define __x86_64_accton_asxvolt16_DOX_H__ + +/** + * @defgroup x86_64_accton_asxvolt16 x86_64_accton_asxvolt16 - x86_64_accton_asxvolt16 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_asxvolt16-x86_64_accton_asxvolt16 Public Interface + * @defgroup x86_64_accton_asxvolt16-config Compile Time Configuration + * @defgroup x86_64_accton_asxvolt16-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_accton_asxvolt16_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_porting.h new file mode 100755 index 00000000..5f4d6f85 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/inc/x86_64_accton_asxvolt16/x86_64_accton_asxvolt16_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_asxvolt16 Porting Macros. + * + * @addtogroup x86_64_accton_asxvolt16-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_asxvolt16_PORTING_H__ +#define __x86_64_accton_asxvolt16_PORTING_H__ + + +/* */ +#if x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_accton_asxvolt16_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_accton_asxvolt16_MALLOC GLOBAL_MALLOC + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_MALLOC malloc + #else + #error The macro x86_64_accton_asxvolt16_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_FREE + #if defined(GLOBAL_FREE) + #define x86_64_accton_asxvolt16_FREE GLOBAL_FREE + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_FREE free + #else + #error The macro x86_64_accton_asxvolt16_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_accton_asxvolt16_MEMSET GLOBAL_MEMSET + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_MEMSET memset + #else + #error The macro x86_64_accton_asxvolt16_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_accton_asxvolt16_MEMCPY GLOBAL_MEMCPY + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_MEMCPY memcpy + #else + #error The macro x86_64_accton_asxvolt16_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_accton_asxvolt16_STRNCPY GLOBAL_STRNCPY + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_STRNCPY strncpy + #else + #error The macro x86_64_accton_asxvolt16_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_accton_asxvolt16_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_VSNPRINTF vsnprintf + #else + #error The macro x86_64_accton_asxvolt16_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_accton_asxvolt16_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_SNPRINTF snprintf + #else + #error The macro x86_64_accton_asxvolt16_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asxvolt16_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_accton_asxvolt16_STRLEN GLOBAL_STRLEN + #elif x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asxvolt16_STRLEN strlen + #else + #error The macro x86_64_accton_asxvolt16_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_accton_asxvolt16_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..0055b437 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_asxvolt16_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_asxvolt16_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_asxvolt16_DEPENDMODULE_ENTRIES := init:x86_64_accton_asxvolt16 ucli:x86_64_accton_asxvolt16 + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..36abc70f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_asxvolt16_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/debug.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/debug.c new file mode 100755 index 00000000..16485e36 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_accton_asxvolt16_int.h" + +#if x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_accton_asxvolt16_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..c3a77bc9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/fani.c @@ -0,0 +1,356 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_PREFIX_PATH "/sys/bus/i2c/devices/" + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define MAX_FAN_SPEED 25500 +#define MAX_PSU_FAN_SPEED 25500 + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +#define PSU_FAN_INFO(pid, fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5), + CHASSIS_FAN_INFO(6), + PSU_FAN_INFO(1, 1), + PSU_FAN_INFO(2, 1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + char path[64] = {0}; + + /* get fan present status + */ + ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get fan fault status (turn on when any one fails) + */ + ret = onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + if (value > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + + /* get fan direction (both : the same) + */ + ret = onlp_file_read_int(&value, "%s""fan%d_direction", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + info->status |= value ? ONLP_FAN_STATUS_F2B : ONLP_FAN_STATUS_B2F; + + + /* get front fan speed + */ + ret = onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get rear fan speed + */ + ret = onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + /* take the min value from front/rear fan speed + */ + if (info->rpm > value) { + info->rpm = value; + } + + /* get speed percentage from rpm + */ + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +static uint32_t +_onlp_get_fan_direction_on_psu(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) { + continue; + } + + if (PSU_TYPE_AC_F2B == psu_type) { + return ONLP_FAN_STATUS_F2B; + } + else { + return ONLP_FAN_STATUS_B2F; + } + } + + return 0; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int val = 0; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= _onlp_get_fan_direction_on_psu(); + + /* get fan fault status + */ + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_fault", &val) == ONLP_STATUS_OK) { + info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + } + + /* get fan speed + */ + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int fid; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) + { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + switch (fid) + { + case FAN_1_ON_PSU_1: + return psu_ym2651y_pmbus_info_set(PSU1_ID, "psu_fan1_duty_cycle_percentage", p); + case FAN_1_ON_PSU_2: + return psu_ym2651y_pmbus_info_set(PSU2_ID, "psu_fan1_duty_cycle_percentage", p); + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + path = FAN_NODE(fan_duty_cycle_percentage); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_integer(path, p) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..503e04e0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,247 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define LED_FORMAT "/sys/class/leds/accton_asxvolt16_led::%s/brightness" + +/* LED related data + */ +enum led_light_mode { /*must be the same with the definition @ kernel driver */ + 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 +}; + +enum onlp_led_id +{ + LED_LOC = 1, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN, +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} +}; + +static char *leds[] = /* must map with onlp_led_id */ +{ + NULL, + "loc", + "diag", + "psu1", + "psu2", + "fan" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 5 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int lid, value; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + + /* Get LED mode */ + if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) { + DEBUG_PRINT("Unable to read status from file (%s)", leds[lid]); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(lid, value); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int lid; + char path[64] = {0}; + + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + if (lid != LED_DIAG) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + sprintf(path, LED_FORMAT, leds[lid]); + + if (onlp_file_write_integer(path, onlp_to_driver_led_mode(lid , mode)) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..59451bc3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_asxvolt16 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..e4784251 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,223 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" + +int _onlp_file_write(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_WRONLY, S_IWUSR)) == -1) { + return -1; + } + + if ((len = write(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_write_integer(char *filename, int value) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return _onlp_file_write(filename, buf, (int)strlen(buf), 0); +} + +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + printf("%s(%d)\r\n", __FUNCTION__, __LINE__); + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 8 +#define I2C_PSU_FAN_DIR_LEN 3 +#define PSU_SERIAL_NUMBER_LEN 18 +#define PSU_NODE_MAX_PATH_LEN 64 + +int get_psu_serial_number(int id, char *serial, int serial_len) +{ + char *node = NULL; + char sn[PSU_SERIAL_NUMBER_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_mfr_serial) : PSU2_AC_PMBUS_NODE(psu_mfr_serial); + + if (onlp_file_read_string(node, sn, sizeof(sn), 0) != 0) { + return ONLP_STATUS_E_INVALID; + } + sn[PSU_SERIAL_NUMBER_LEN] = 0; + + if (serial) { + strncpy(serial, sn, sizeof(sn)); + } + + return ONLP_STATUS_OK; +} + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + char fan_dir[I2C_PSU_FAN_DIR_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_mfr_model) : PSU2_AC_PMBUS_NODE(psu_mfr_model); + + if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(model_name, "YM-2651Y", strlen("YM-2651Y")) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (modelname) { + strncpy(modelname, model_name, sizeof(model_name)-1); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F; + } + + return PSU_TYPE_UNKNOWN; +} + +int psu_ym2651y_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + ret = onlp_file_read_int(value, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + } + else { + ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int psu_ym2651y_pmbus_info_set(int id, char *node, int value) +{ + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + switch (id) { + case PSU1_ID: + sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + break; + case PSU2_ID: + sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + }; + + if (onlp_file_write_integer(path, value) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..1b039106 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,95 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_accton_asxvolt16_log.h" + +#define CHASSIS_FAN_COUNT 6 +#define CHASSIS_THERMAL_COUNT 5 +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_LED_COUNT 5 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-005b/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/17-0058/" + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/18-0053/" +#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/17-0050/" + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +#define FAN_BOARD_PATH "/sys/bus/i2c/devices/9-0066/" +#define FAN_NODE(node) FAN_BOARD_PATH#node + +#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F +} psu_type_t; + +int onlp_file_write_integer(char *filename, int value); +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_ym2651y_pmbus_info_get(int id, char *node, int *value); +int psu_ym2651y_pmbus_info_set(int id, char *node, int value); + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +int get_psu_serial_number(int id, char *serial, int serial_len); + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..21e0cde4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/psui.c @@ -0,0 +1,187 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + ret = onlp_file_read_int(value, "%s%s", PSU1_AC_HWMON_PREFIX, node); + } + else if (PSU2_ID == id) { + ret = onlp_file_read_int(value, "%s%s", PSU2_AC_HWMON_PREFIX, node); + } + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_ym2651y_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + get_psu_serial_number(index, info->serial, sizeof(info->serial)); + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + return ONLP_STATUS_OK; + } + + + /* Get PSU type + */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + + switch (psu_type) { + case PSU_TYPE_AC_F2B: + case PSU_TYPE_AC_B2F: + ret = psu_ym2651y_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..0c7dec72 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,260 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2016 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_asxvolt16_log.h" + +#define NUM_OF_PORT 20 +#define MAX_SFP_PATH 64 +static char sfp_node_path[MAX_SFP_PATH] = {0}; + +static const int sfp_bus_index[] = { +47, 48, 37, 38, 35, 36, 33, 34, +39, 40, 41, 42, 43, 44, 45, 46, +49, 50, 51, 52 +}; + +#define FRONT_PORT_BUS_INDEX(port) (sfp_bus_index[port]) + +static char* +sfp_get_port_path_addr(int port, int addr, char *node_name) +{ + sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", + FRONT_PORT_BUS_INDEX(port), addr, node_name); + return sfp_node_path; +} + +static char* +sfp_get_port_path(int port, char *node_name) +{ + return sfp_get_port_path_addr(port, 50, node_name); +} + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 54} + */ + int p; + + for(p = 0; p < NUM_OF_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + char *path = sfp_get_port_path(port, "sfp_is_present"); + + if (onlp_file_read_int(&present, path) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t bytes[3]; + char* path; + FILE* fp; + + AIM_BITMAP_CLR_ALL(dst); + + path = sfp_get_port_path(0, "sfp_is_present_all"); + fp = fopen(path, "r"); + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + return ONLP_STATUS_E_INTERNAL; + } + int count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); + fclose(fp); + if(count != AIM_ARRAYSIZE(bytes)) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant QSFP ports */ + bytes[2] &= 0xF; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + AIM_BITMAP_CLR_ALL(dst); + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + char* path = sfp_get_port_path(port, "sfp_eeprom"); + + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + memset(data, 0, 256); + + if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + char* path = sfp_get_port_path(port, "sfp_tx_disable"); + + if (onlp_file_write_integer(path, value) != 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + char* path = NULL; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_FAULT: + { + path = sfp_get_port_path(port, "sfp_tx_fault"); + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + path = sfp_get_port_path(port, "sfp_tx_disable"); + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..4d59747a --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,283 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_asxvolt16_int.h" +#include "x86_64_accton_asxvolt16_log.h" + +#define CPLD_VERSION_FORMAT "/sys/bus/i2c/devices/%s/version" +#define NUM_OF_CPLD 2 + +static char* cpld_path[NUM_OF_CPLD] = +{ + "11-0060", + "12-0062" +}; + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-asxvolt16-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 5 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 6 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD] = {0}; + + for (i=0; i < AIM_ARRAYSIZE(cpld_path); i++) { + v[i] = 0; + + if(onlp_file_read_int(v+i, CPLD_VERSION_FORMAT , cpld_path[i]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + } + + pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +#define FAN_DUTY_MAX (100) +#define FAN_DUTY_MIN (32) + +static int +sysi_fanctrl_fan_fault_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], + onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], + int *adjusted) +{ + int i; + *adjusted = 0; + + /* Bring fan speed to FAN_DUTY_MAX if any fan is not operational */ + for (i = 0; i < CHASSIS_FAN_COUNT; i++) { + if (!(fi[i].status & ONLP_FAN_STATUS_FAILED)) { + continue; + } + + *adjusted = 1; + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + } + + return ONLP_STATUS_OK; +} + +static int +sysi_fanctrl_fan_absent_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], + onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], + int *adjusted) +{ + int i; + *adjusted = 0; + + /* Bring fan speed to FAN_DUTY_MAX if fan is not present */ + for (i = 0; i < CHASSIS_FAN_COUNT; i++) { + if (fi[i].status & ONLP_FAN_STATUS_PRESENT) { + continue; + } + + *adjusted = 1; + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + } + + return ONLP_STATUS_OK; +} + +static int +sysi_fanctrl_overall_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], + onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], + int *adjusted) +{ + int i, num_of_sensor = 0, temp_avg = 0, fanduty; + + for (i = (THERMAL_CPU_CORE); i <= (THERMAL_CPU_CORE); i++) { + num_of_sensor++; + temp_avg += ti[i-1].mcelsius; + } + + temp_avg /= num_of_sensor; + *adjusted = 1; + + if (onlp_file_read_int(&fanduty, FAN_NODE(fan_duty_cycle_percentage)) < 0) { + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + } + + if (temp_avg > 55000) { + if (fanduty == FAN_DUTY_MAX) { + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + } + else if (temp_avg > 50000) { + if (fanduty == 63) { + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), 63); + } + else if (temp_avg > 30000) { + if (fanduty == 50) { + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), 50); + } + + if (fanduty == FAN_DUTY_MIN) { + return ONLP_STATUS_OK; + } + + return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MIN); +} + +typedef int (*fan_control_policy)(onlp_fan_info_t fi[CHASSIS_FAN_COUNT], + onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT], + int *adjusted); + +fan_control_policy fan_control_policies[] = { +sysi_fanctrl_fan_fault_policy, +sysi_fanctrl_fan_absent_policy, +sysi_fanctrl_overall_thermal_sensor_policy, +}; + +int +onlp_sysi_platform_manage_fans(void) +{ + int i, rc; + onlp_fan_info_t fi[CHASSIS_FAN_COUNT]; + onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT]; + + memset(fi, 0, sizeof(fi)); + memset(ti, 0, sizeof(ti)); + + /* Get fan status + */ + for (i = 0; i < CHASSIS_FAN_COUNT; i++) { + rc = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i+1), &fi[i]); + + if (rc != ONLP_STATUS_OK) { + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i+1); + return ONLP_STATUS_E_INTERNAL; + } + } + + /* Get thermal sensor status + */ + for (i = 0; i < THERMAL_CPU_CORE; i++) { + rc = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+1), &ti[i]); + + if (rc != ONLP_STATUS_OK) { + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX); + AIM_LOG_ERROR("Unable to get thermal(%d) status\r\n", i+1); + return ONLP_STATUS_E_INTERNAL; + } + } + + /* Apply thermal policy according the policy list, + * If fan duty is adjusted by one of the policies, skip the others + */ + for (i = 0; i < AIM_ARRAYSIZE(fan_control_policies); i++) { + int adjusted = 0; + + rc = fan_control_policies[i](fi, ti, &adjusted); + if (!adjusted) { + continue; + } + + return rc; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..898842e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,128 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[] = /* must map with onlp_thermal_id */ +{ + NULL, + NULL, /* CPU_CORE files */ + "/sys/bus/i2c/devices/10-0049*temp1_input", + "/sys/bus/i2c/devices/10-004a*temp1_input", + "/sys/bus/i2c/devices/10-004b*temp1_input", + "/sys/bus/i2c/devices/10-004e*temp1_input", + "/sys/bus/i2c/devices/18-005b/psu_temp1_input", + "/sys/bus/i2c/devices/17-0058/psu_temp1_input", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0*temp2_input", + "/sys/devices/platform/coretemp.0*temp3_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-49", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2-4a", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3-4b", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4-4e", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if(tid == THERMAL_CPU_CORE) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_config.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_config.c new file mode 100755 index 00000000..feebfba5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(_x) __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(_x) +x86_64_accton_asxvolt16_config_settings_t x86_64_accton_asxvolt16_config_settings[] = +{ +#ifdef x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_INCLUDE_LOGGING(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_PORTING_STDLIB(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_asxvolt16_config_STRINGIFY_NAME(x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE(x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_accton_asxvolt16_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_asxvolt16_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_asxvolt16_config_STRINGIFY_VALUE +#undef __x86_64_accton_asxvolt16_config_STRINGIFY_NAME + +const char* +x86_64_accton_asxvolt16_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_asxvolt16_config_settings[i].name; i++) { + if(strcmp(x86_64_accton_asxvolt16_config_settings[i].name, setting)) { + return x86_64_accton_asxvolt16_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_asxvolt16_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_asxvolt16_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_asxvolt16_config_settings[i].name, x86_64_accton_asxvolt16_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_enums.c new file mode 100755 index 00000000..8330dfda --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_int.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_int.h new file mode 100755 index 00000000..ce6032d4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_asxvolt16 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_asxvolt16_INT_H__ +#define __x86_64_accton_asxvolt16_INT_H__ + +#include + + +#endif /* __x86_64_accton_asxvolt16_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.c new file mode 100755 index 00000000..b903d52c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_asxvolt16_log.h" +/* + * x86_64_accton_asxvolt16 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_accton_asxvolt16_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_accton_asxvolt16_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_accton_asxvolt16_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.h b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.h new file mode 100755 index 00000000..a28f5cc0 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_asxvolt16_LOG_H__ +#define __x86_64_accton_asxvolt16_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_asxvolt16 +#include + +#endif /* __x86_64_accton_asxvolt16_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_module.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_module.c new file mode 100755 index 00000000..4c1bddf9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_asxvolt16_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_asxvolt16_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_asxvolt16_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_ucli.c new file mode 100755 index 00000000..b28a55d7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/onlp/builds/src/module/src/x86_64_accton_asxvolt16_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_asxvolt16_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_asxvolt16_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_asxvolt16) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_asxvolt16_ucli_module__ = + { + "x86_64_accton_asxvolt16_ucli", + NULL, + x86_64_accton_asxvolt16_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_asxvolt16_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_asxvolt16_ucli_module__); + n = ucli_node_create("x86_64_accton_asxvolt16", NULL, &x86_64_accton_asxvolt16_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_asxvolt16")); + return n; +} + +#else +void* +x86_64_accton_asxvolt16_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/PKG.yml new file mode 100755 index 00000000..48b7b786 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-asxvolt16 REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/lib/x86-64-accton-asxvolt16-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/lib/x86-64-accton-asxvolt16-r0.yml new file mode 100755 index 00000000..b0587642 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/lib/x86-64-accton-asxvolt16-r0.yml @@ -0,0 +1,33 @@ +--- + +###################################################################### +# +# platform-config for ASXvOLT16 +# +###################################################################### + +x86-64-accton-asxvolt16-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS0,115200n8 + tg3.short_preamble=1 + tg3.bcm5718s_reset=1 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/python/x86_64_accton_asxvolt16_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/python/x86_64_accton_asxvolt16_r0/__init__.py new file mode 100755 index 00000000..e31302bf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asxvolt16/platform-config/r0/src/python/x86_64_accton_asxvolt16_r0/__init__.py @@ -0,0 +1,77 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_asxvolt16_r0(OnlPlatformAccton, + OnlPlatformPortConfig_20x100): + PLATFORM='x86-64-accton-asxvolt16-r0' + MODEL="ASXvOLT16" + SYS_OBJECT_ID=".816.1" + + def baseconfig(self): + self.insmod('ym2651y') + for m in [ 'cpld', 'fan', 'psu', 'leds', 'sfp' ]: + self.insmod("x86-64-accton-asxvolt16-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + self.new_i2c_devices([ + # initialize root multiplexer (PCA9548) + ('pca9548', 0x77, 0), + + # initiate leaf multiplexer (PCA9548) + ('pca9548', 0x76, 1), + ('pca9548', 0x74, 2), + ('pca9548', 0x72, 2), + ('pca9548', 0x75, 25), + ('pca9548', 0x75, 26), + ('pca9548', 0x75, 27), + + # initiate chassis fan + ('asxvolt16_fan', 0x66, 9), + + # inititate LM75 + ('lm75', 0x49, 10), + ('lm75', 0x4a, 10), + ('lm75', 0x4b, 10), + ('lm75', 0x4e, 10), + + #initiate CPLD and FPGA + ('asxvolt16_fpga', 0x60, 11), + ('asxvolt16_cpld', 0x62, 12), + + # initiate PSU-1 + ('asxvolt16_psu1', 0x53, 18), + ('ym2651', 0x5b, 18), + + # initiate PSU-2 + ('asxvolt16_psu2', 0x50, 17), + ('ym2651', 0x58, 17), + + # initiate XFP/QSFP + ('asxvolt16_sfp7', 0x50, 33), + ('asxvolt16_sfp8', 0x50, 34), + ('asxvolt16_sfp5', 0x50, 35), + ('asxvolt16_sfp6', 0x50, 36), + ('asxvolt16_sfp3', 0x50, 37), + ('asxvolt16_sfp4', 0x50, 38), + ('asxvolt16_sfp9', 0x50, 39), + ('asxvolt16_sfp10', 0x50, 40), + + ('asxvolt16_sfp11', 0x50, 41), + ('asxvolt16_sfp12', 0x50, 42), + ('asxvolt16_sfp13', 0x50, 43), + ('asxvolt16_sfp14', 0x50, 44), + ('asxvolt16_sfp15', 0x50, 45), + ('asxvolt16_sfp16', 0x50, 46), + ('asxvolt16_sfp1', 0x50, 47), + ('asxvolt16_sfp2', 0x50, 48), + + ('asxvolt16_sfp17', 0x50, 49), + ('asxvolt16_sfp18', 0x50, 50), + ('asxvolt16_sfp19', 0x50, 51), + ('asxvolt16_sfp20', 0x50, 52), + + # initiate IDPROM + ('24c02', 0x56, 0), + ]) + + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100-32x/platform-config/r0/src/python/x86_64_accton_wedge100_32x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-wedge100-32x/platform-config/r0/src/python/x86_64_accton_wedge100_32x_r0/__init__.py index 7bf82abd..9cd765f4 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100-32x/platform-config/r0/src/python/x86_64_accton_wedge100_32x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100-32x/platform-config/r0/src/python/x86_64_accton_wedge100_32x_r0/__init__.py @@ -8,6 +8,8 @@ class OnlPlatform_x86_64_accton_wedge100_32x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".100.32.1" def baseconfig(self): + self.insmod('optoe') + ########### initialize I2C bus 0 ########### self.new_i2c_devices([ # initialize multiplexer (PCA9548) @@ -19,5 +21,71 @@ class OnlPlatform_x86_64_accton_wedge100_32x_r0(OnlPlatformAccton, ('24c64', 0x50, 39), ]) - + + # Initialize QSFP devices + self.new_i2c_device('optoe1', 0x50, 1) + self.new_i2c_device('optoe1', 0x50, 2) + self.new_i2c_device('optoe1', 0x50, 3) + self.new_i2c_device('optoe1', 0x50, 4) + self.new_i2c_device('optoe1', 0x50, 5) + self.new_i2c_device('optoe1', 0x50, 6) + self.new_i2c_device('optoe1', 0x50, 7) + self.new_i2c_device('optoe1', 0x50, 8) + self.new_i2c_device('optoe1', 0x50, 9) + self.new_i2c_device('optoe1', 0x50, 10) + self.new_i2c_device('optoe1', 0x50, 11) + self.new_i2c_device('optoe1', 0x50, 12) + self.new_i2c_device('optoe1', 0x50, 13) + self.new_i2c_device('optoe1', 0x50, 14) + self.new_i2c_device('optoe1', 0x50, 15) + self.new_i2c_device('optoe1', 0x50, 16) + self.new_i2c_device('optoe1', 0x50, 17) + self.new_i2c_device('optoe1', 0x50, 18) + self.new_i2c_device('optoe1', 0x50, 19) + self.new_i2c_device('optoe1', 0x50, 20) + self.new_i2c_device('optoe1', 0x50, 21) + self.new_i2c_device('optoe1', 0x50, 22) + self.new_i2c_device('optoe1', 0x50, 23) + self.new_i2c_device('optoe1', 0x50, 24) + self.new_i2c_device('optoe1', 0x50, 25) + self.new_i2c_device('optoe1', 0x50, 26) + self.new_i2c_device('optoe1', 0x50, 27) + self.new_i2c_device('optoe1', 0x50, 28) + self.new_i2c_device('optoe1', 0x50, 29) + self.new_i2c_device('optoe1', 0x50, 30) + self.new_i2c_device('optoe1', 0x50, 31) + self.new_i2c_device('optoe1', 0x50, 32) + subprocess.call('echo port1 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port2 > /sys/bus/i2c/devices/1-0050/port_name', shell=True) + subprocess.call('echo port3 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port4 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port5 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port6 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port7 > /sys/bus/i2c/devices/8-0050/port_name', shell=True) + subprocess.call('echo port8 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + subprocess.call('echo port9 > /sys/bus/i2c/devices/10-0050/port_name', shell=True) + subprocess.call('echo port10 > /sys/bus/i2c/devices/9-0050/port_name', shell=True) + subprocess.call('echo port11 > /sys/bus/i2c/devices/12-0050/port_name', shell=True) + subprocess.call('echo port12 > /sys/bus/i2c/devices/11-0050/port_name', shell=True) + subprocess.call('echo port13 > /sys/bus/i2c/devices/14-0050/port_name', shell=True) + subprocess.call('echo port14 > /sys/bus/i2c/devices/13-0050/port_name', shell=True) + subprocess.call('echo port15 > /sys/bus/i2c/devices/16-0050/port_name', shell=True) + subprocess.call('echo port16 > /sys/bus/i2c/devices/15-0050/port_name', shell=True) + subprocess.call('echo port17 > /sys/bus/i2c/devices/18-0050/port_name', shell=True) + subprocess.call('echo port18 > /sys/bus/i2c/devices/17-0050/port_name', shell=True) + subprocess.call('echo port19 > /sys/bus/i2c/devices/20-0050/port_name', shell=True) + subprocess.call('echo port20 > /sys/bus/i2c/devices/19-0050/port_name', shell=True) + subprocess.call('echo port21 > /sys/bus/i2c/devices/22-0050/port_name', shell=True) + subprocess.call('echo port22 > /sys/bus/i2c/devices/21-0050/port_name', shell=True) + subprocess.call('echo port23 > /sys/bus/i2c/devices/24-0050/port_name', shell=True) + subprocess.call('echo port24 > /sys/bus/i2c/devices/23-0050/port_name', shell=True) + subprocess.call('echo port25 > /sys/bus/i2c/devices/26-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/25-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/28-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/27-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/30-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/29-0050/port_name', shell=True) + subprocess.call('echo port31 > /sys/bus/i2c/devices/32-0050/port_name', shell=True) + subprocess.call('echo port32 > /sys/bus/i2c/devices/31-0050/port_name', shell=True) + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.c index 1d374e75..3319a00f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.c @@ -31,9 +31,9 @@ #define TTY_DEVICE "/dev/ttyACM0" #define TTY_PROMPT "@bmc:" -#define TTY_I2C_TIMEOUT 800000 +#define TTY_I2C_TIMEOUT 55000 #define TTY_BMC_LOGIN_TIMEOUT 1000000 -#define TTY_RETRY 10 +#define TTY_RETRY 3 #define MAXIMUM_TTY_BUFFER_LENGTH 1024 #define MAXIMUM_TTY_STRING_LENGTH (MAXIMUM_TTY_BUFFER_LENGTH - 1) @@ -86,6 +86,7 @@ static int tty_exec_buf(unsigned long udelay, const char *str) write(tty_fd, tty_buf, strlen(tty_buf)+1); usleep(udelay); + memset(tty_buf, 0, MAXIMUM_TTY_BUFFER_LENGTH); read(tty_fd, tty_buf, MAXIMUM_TTY_BUFFER_LENGTH); return (strstr(tty_buf, str) != NULL) ? 0 : -1; } @@ -118,26 +119,51 @@ static int tty_login(void) return -1; } +int bmc_tty_init(void) +{ + int i; + if (tty_fd >= 0){ + return 0; + } + + for (i = 1; i <= TTY_RETRY; i++) { + if (tty_open() != 0) { + AIM_LOG_ERROR("ERROR: Cannot open TTY device\n"); + continue; + } + if (tty_login() != 0) { + AIM_LOG_ERROR("ERROR: Cannot login TTY device\n"); + tty_close(); + continue; + } + + return 0; + } + + AIM_LOG_ERROR("Unable to init bmc tty\r\n"); + return -1; +} + +int bmc_tty_deinit(void) +{ + if( tty_fd != -1 ){ + tty_close(); + } + else{ + AIM_LOG_ERROR("ERROR: TTY not open\n"); + } + return 0; +} + int bmc_send_command(char *cmd) { int i, ret = 0; for (i = 1; i <= TTY_RETRY; i++) { - if (tty_open() != 0) { - printf("ERROR: Cannot open TTY device\n"); - continue; - } - if (tty_login() != 0) { - //printf("ERROR: Cannot login TTY device\n"); - tty_close(); - continue; - } - - snprintf(tty_buf, MAXIMUM_TTY_BUFFER_LENGTH, "%s", cmd); - ret = tty_exec_buf(TTY_I2C_TIMEOUT * i, TTY_PROMPT); - tty_close(); + snprintf(tty_buf, MAXIMUM_TTY_BUFFER_LENGTH, "%s", cmd); + ret = tty_exec_buf(TTY_I2C_TIMEOUT, TTY_PROMPT); if (ret != 0) { - printf("ERROR: bmc_send_command timed out\n"); +// AIM_LOG_ERROR("ERROR: bmc_send_command(%s) timed out\n", cmd); continue; } @@ -148,6 +174,63 @@ int bmc_send_command(char *cmd) return -1; } +int chk_numeric_char(char *data, int base) +{ + int len, i, orig = 0; + if( *data == '\0' ){ + return 0; + } + len = (int) strlen(data); + if( base == 10 ){ + for( i=0; i '9' ){ + return 0; + } + } + return 1; + } + else if( base == 16 ){ + if( !memcmp(data, "0x", 2) ){ + if( len <= 2 ){ + return 0; + } + orig = 2; + } + else if( !memcmp(data, "0X", 2) ){ + if( len <= 2 ){ + return 0; + } + orig = 2; + } + for( i=orig; i orig) && ( *(data+i) == 0xd ) ){ + break; + } + if( (i > orig) && ( *(data+i) == 0xa ) ){ + break; + } + if( !( ( (*(data+i) >= '0') && (*(data+i) <= '9') ) || + ( (*(data+i) >= 'A') && (*(data+i) <= 'F') ) || + ( (*(data+i) >= 'a') && (*(data+i) <= 'f') ) + ) + ){ + return 0; + } + } + return 1; + } + return 0; +} + int bmc_command_read_int(int* value, char *cmd, int base) { @@ -166,6 +249,9 @@ bmc_command_read_int(int* value, char *cmd, int base) for (i = 1; i <= TTY_RETRY; i++) { current_str = strstr(prev_str + len, cmd); if(current_str == NULL) { + if( !chk_numeric_char(prev_str + len, base) ){ + return -1; + } *value = strtoul(prev_str + len, NULL, base); break; }else { diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.h index ee600282..e77b420f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/platform_lib.h @@ -64,6 +64,9 @@ int bmc_i2c_writeb(uint8_t bus, uint8_t devaddr, uint8_t addr, uint8_t value); int bmc_i2c_readw(uint8_t bus, uint8_t devaddr, uint8_t addr); int bmc_i2c_readraw(uint8_t bus, uint8_t devaddr, uint8_t addr, char* data, int data_size); +int bmc_tty_init(void); +int bmc_tty_deinit(void); + #endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/psui.c index 4d321457..7b964eb6 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/psui.c @@ -24,6 +24,7 @@ * ***********************************************************/ #include +#include #include #include #include "platform_lib.h" @@ -121,6 +122,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) if (bmc_i2c_writeb(7, 0x70, 0, value) < 0) { return ONLP_STATUS_E_INTERNAL; } + usleep(1200); /* Read vin */ addr = (pid == PSU1_ID) ? 0x59 : 0x5a; @@ -164,7 +166,10 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) } /* Get model name */ - return bmc_i2c_readraw(7, addr, 0x9a, info->model, sizeof(info->model)); + bmc_i2c_readraw(7, addr, 0x9a, info->model, sizeof(info->model)); + + /* Get serial number */ + return bmc_i2c_readraw(7, addr, 0x9e, info->serial, sizeof(info->serial)); } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sfpi.c index 449a86f3..52a7ea63 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sfpi.c @@ -32,6 +32,8 @@ #define BIT(i) (1 << (i)) #define NUM_OF_SFP_PORT 32 +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" + static const int sfp_bus_index[] = { 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 17, 16, @@ -156,44 +158,55 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } -static int -sfpi_eeprom_read(int port, uint8_t devaddr, uint8_t data[256]) -{ - int i; - - /* - * Read the SFP eeprom into data[] - * - * Return MISSING if SFP is missing. - * Return OK if eeprom is read - */ - memset(data, 0, 256); - - for (i = 0; i < 128; i++) { - int bus = sfp_bus_index[port]; - int val = onlp_i2c_readw(bus, devaddr, i*2, ONLP_I2C_F_FORCE); - - if (val < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - data[i*2] = val & 0xff; - data[(i*2)+1] = (val >> 8) & 0xff; - } - - return ONLP_STATUS_OK; -} - int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - return sfpi_eeprom_read(port, 0x50, data); + int size = 0; + if(port <0 || port >= NUM_OF_SFP_PORT) + return ONLP_STATUS_E_INTERNAL; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, sfp_bus_index[port]) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size(%d) is different!\r\n", port, size); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - return sfpi_eeprom_read(port, 0x51, data); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, sfp_bus_index[port]); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d, %d)", port, ret); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sysi.c index 8d19ba0f..c7c6d39f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/onlp/builds/src/module/src/sysi.c @@ -1,114 +1,115 @@ -/************************************************************ - * - * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * - ************************************************************ - * - * - * - ***********************************************************/ -#include -#include - -#include -#include -#include -#include -#include -#include -#include "platform_lib.h" - -#include "x86_64_accton_wedge100bf_32x_int.h" -#include "x86_64_accton_wedge100bf_32x_log.h" - -const char* -onlp_sysi_platform_get(void) -{ - return "x86-64-accton-wedge100bf-32x-r0"; -} - -int -onlp_sysi_onie_data_get(uint8_t** data, int* size) -{ - uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { - *data = rdata; - return ONLP_STATUS_OK; - } - } - - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; -} - -int -onlp_sysi_oids_get(onlp_oid_t* table, int max) -{ - int i; - onlp_oid_t* e = table; - memset(table, 0, max*sizeof(onlp_oid_t)); - - /* 8 Thermal sensors on the chassis */ - for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { - *e++ = ONLP_THERMAL_ID_CREATE(i); - } - - /* 2 LEDs on the chassis */ - for (i = 1; i <= CHASSIS_LED_COUNT; i++) { - *e++ = ONLP_LED_ID_CREATE(i); - } - - /* 2 PSUs on the chassis */ - for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { - *e++ = ONLP_PSU_ID_CREATE(i); - } - - /* 5 Fans on the chassis */ - for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { - *e++ = ONLP_FAN_ID_CREATE(i); - } - - return 0; -} - -int -onlp_sysi_platform_info_get(onlp_platform_info_t* pi) -{ - return ONLP_STATUS_OK; -} - -void -onlp_sysi_platform_info_free(onlp_platform_info_t* pi) -{ -} - -int -onlp_sysi_platform_manage_fans(void) -{ - return ONLP_STATUS_OK; -} - -int -onlp_sysi_platform_manage_leds(void) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_wedge100bf_32x_int.h" +#include "x86_64_accton_wedge100bf_32x_log.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-wedge100bf-32x-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 8 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 2 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 5 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + bmc_tty_init(); + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ +} + +int +onlp_sysi_platform_manage_fans(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/platform-config/r0/src/python/x86_64_accton_wedge100bf_32x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/platform-config/r0/src/python/x86_64_accton_wedge100bf_32x_r0/__init__.py index 374dcd50..0d2ae6c2 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/platform-config/r0/src/python/x86_64_accton_wedge100bf_32x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-32x/platform-config/r0/src/python/x86_64_accton_wedge100bf_32x_r0/__init__.py @@ -8,6 +8,8 @@ class OnlPlatform_x86_64_accton_wedge100bf_32x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".100.32.2" def baseconfig(self): + self.insmod('optoe') + ########### initialize I2C bus 1 ########### self.new_i2c_devices([ # initialize multiplexer (PCA9548) @@ -19,5 +21,71 @@ class OnlPlatform_x86_64_accton_wedge100bf_32x_r0(OnlPlatformAccton, ('24c64', 0x50, 40), ]) - + + # Initialize QSFP devices + self.new_i2c_device('optoe1', 0x50, 2) + self.new_i2c_device('optoe1', 0x50, 3) + self.new_i2c_device('optoe1', 0x50, 4) + self.new_i2c_device('optoe1', 0x50, 5) + self.new_i2c_device('optoe1', 0x50, 6) + self.new_i2c_device('optoe1', 0x50, 7) + self.new_i2c_device('optoe1', 0x50, 8) + self.new_i2c_device('optoe1', 0x50, 9) + self.new_i2c_device('optoe1', 0x50, 10) + self.new_i2c_device('optoe1', 0x50, 11) + self.new_i2c_device('optoe1', 0x50, 12) + self.new_i2c_device('optoe1', 0x50, 13) + self.new_i2c_device('optoe1', 0x50, 14) + self.new_i2c_device('optoe1', 0x50, 15) + self.new_i2c_device('optoe1', 0x50, 16) + self.new_i2c_device('optoe1', 0x50, 17) + self.new_i2c_device('optoe1', 0x50, 18) + self.new_i2c_device('optoe1', 0x50, 19) + self.new_i2c_device('optoe1', 0x50, 20) + self.new_i2c_device('optoe1', 0x50, 21) + self.new_i2c_device('optoe1', 0x50, 22) + self.new_i2c_device('optoe1', 0x50, 23) + self.new_i2c_device('optoe1', 0x50, 24) + self.new_i2c_device('optoe1', 0x50, 25) + self.new_i2c_device('optoe1', 0x50, 26) + self.new_i2c_device('optoe1', 0x50, 27) + self.new_i2c_device('optoe1', 0x50, 28) + self.new_i2c_device('optoe1', 0x50, 29) + self.new_i2c_device('optoe1', 0x50, 30) + self.new_i2c_device('optoe1', 0x50, 31) + self.new_i2c_device('optoe1', 0x50, 32) + self.new_i2c_device('optoe1', 0x50, 33) + subprocess.call('echo port1 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port2 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port3 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port4 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port5 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + subprocess.call('echo port6 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port7 > /sys/bus/i2c/devices/9-0050/port_name', shell=True) + subprocess.call('echo port8 > /sys/bus/i2c/devices/8-0050/port_name', shell=True) + subprocess.call('echo port9 > /sys/bus/i2c/devices/11-0050/port_name', shell=True) + subprocess.call('echo port10 > /sys/bus/i2c/devices/10-0050/port_name', shell=True) + subprocess.call('echo port11 > /sys/bus/i2c/devices/13-0050/port_name', shell=True) + subprocess.call('echo port12 > /sys/bus/i2c/devices/12-0050/port_name', shell=True) + subprocess.call('echo port13 > /sys/bus/i2c/devices/15-0050/port_name', shell=True) + subprocess.call('echo port14 > /sys/bus/i2c/devices/14-0050/port_name', shell=True) + subprocess.call('echo port15 > /sys/bus/i2c/devices/17-0050/port_name', shell=True) + subprocess.call('echo port16 > /sys/bus/i2c/devices/16-0050/port_name', shell=True) + subprocess.call('echo port17 > /sys/bus/i2c/devices/19-0050/port_name', shell=True) + subprocess.call('echo port18 > /sys/bus/i2c/devices/18-0050/port_name', shell=True) + subprocess.call('echo port19 > /sys/bus/i2c/devices/21-0050/port_name', shell=True) + subprocess.call('echo port20 > /sys/bus/i2c/devices/20-0050/port_name', shell=True) + subprocess.call('echo port21 > /sys/bus/i2c/devices/23-0050/port_name', shell=True) + subprocess.call('echo port22 > /sys/bus/i2c/devices/22-0050/port_name', shell=True) + subprocess.call('echo port23 > /sys/bus/i2c/devices/25-0050/port_name', shell=True) + subprocess.call('echo port24 > /sys/bus/i2c/devices/24-0050/port_name', shell=True) + subprocess.call('echo port25 > /sys/bus/i2c/devices/27-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/26-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/29-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/28-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/31-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/30-0050/port_name', shell=True) + subprocess.call('echo port31 > /sys/bus/i2c/devices/33-0050/port_name', shell=True) + subprocess.call('echo port32 > /sys/bus/i2c/devices/32-0050/port_name', shell=True) + return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/fani.c index 3775723f..9eca1780 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/fani.c @@ -1,222 +1,238 @@ -/************************************************************ - * - * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * - ************************************************************ - * - * Fan Platform Implementation Defaults. - * - ***********************************************************/ -#include -#include -#include "platform_lib.h" - -#define VALIDATE(_id) \ - do { \ - if(!ONLP_OID_IS_FAN(_id)) { \ - return ONLP_STATUS_E_INVALID; \ - } \ - } while(0) - -#define MAX_FAN_SPEED 15400 -#define BIT(i) (1 << (i)) - -enum fan_id { - FAN_1_ON_FAN_BOARD = 1, - FAN_2_ON_FAN_BOARD, - FAN_3_ON_FAN_BOARD, - FAN_4_ON_FAN_BOARD, - FAN_5_ON_FAN_BOARD, -}; - -#define FAN_BOARD_PATH "/sys/bus/i2c/devices/8-0033/" - -#define CHASSIS_FAN_INFO(fid) \ - { \ - { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ - 0x0,\ - ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ - 0,\ - 0,\ - ONLP_FAN_MODE_INVALID,\ - } - -/* Static fan information */ -onlp_fan_info_t finfo[] = { - { }, /* Not used */ - CHASSIS_FAN_INFO(1), - CHASSIS_FAN_INFO(2), - CHASSIS_FAN_INFO(3), - CHASSIS_FAN_INFO(4), - CHASSIS_FAN_INFO(5) -}; - -/* - * This function will be called prior to all of onlp_fani_* functions. - */ -int -onlp_fani_init(void) -{ - return ONLP_STATUS_OK; -} - -int -onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) -{ - int value = 0, fid; - char path[64] = {0}; - VALIDATE(id); - - fid = ONLP_OID_ID_GET(id); - *info = finfo[fid]; - - /* get fan present status - */ - sprintf(path, "%s""fantray_present", FAN_BOARD_PATH); - - if (bmc_file_read_int(&value, path, 16) < 0) { - AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); - return ONLP_STATUS_E_INTERNAL; - } - - if (value & BIT(fid-1)) { - return ONLP_STATUS_OK; - } - info->status |= ONLP_FAN_STATUS_PRESENT; - - - /* get front fan rpm - */ - sprintf(path, "%s""fan%d_input", FAN_BOARD_PATH, fid*2 - 1); - - if (bmc_file_read_int(&value, path, 10) < 0) { - AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); - return ONLP_STATUS_E_INTERNAL; - } - info->rpm = value; - - /* get rear fan rpm - */ - sprintf(path, "%s""fan%d_input", FAN_BOARD_PATH, fid*2); - - if (bmc_file_read_int(&value, path, 10) < 0) { - AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); - return ONLP_STATUS_E_INTERNAL; - } - - /* take the min value from front/rear fan speed - */ - if (info->rpm > value) { - info->rpm = value; - } - - - /* set fan status based on rpm - */ - if (!info->rpm) { - info->status |= ONLP_FAN_STATUS_FAILED; - return ONLP_STATUS_OK; - } - - - /* get speed percentage from rpm - */ - info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; - - /* set fan direction - */ - info->status |= ONLP_FAN_STATUS_F2B; - - return ONLP_STATUS_OK; -} - -/* - * This function sets the speed of the given fan in RPM. - * - * This function will only be called if the fan supprots the RPM_SET - * capability. - * - * It is optional if you have no fans at all with this feature. - */ -int -onlp_fani_rpm_set(onlp_oid_t id, int rpm) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - -/* - * This function sets the fan speed of the given OID as a percentage. - * - * This will only be called if the OID has the PERCENTAGE_SET - * capability. - * - * It is optional if you have no fans at all with this feature. - */ -int -onlp_fani_percentage_set(onlp_oid_t id, int p) -{ - char cmd[32] = {0}; - - sprintf(cmd, "set_fan_speed.sh %d", p); - - if (bmc_send_command(cmd) < 0) { - AIM_LOG_ERROR("Unable to send command to bmc(%s)\r\n", cmd); - return ONLP_STATUS_E_INTERNAL; - } - - return ONLP_STATUS_OK; -} - -/* - * This function sets the fan speed of the given OID as per - * the predefined ONLP fan speed modes: off, slow, normal, fast, max. - * - * Interpretation of these modes is up to the platform. - * - */ -int -onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - -/* - * This function sets the fan direction of the given OID. - * - * This function is only relevant if the fan OID supports both direction - * capabilities. - * - * This function is optional unless the functionality is available. - */ -int -onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - -/* - * Generic fan ioctl. Optional. - */ -int -onlp_fani_ioctl(onlp_oid_t id, va_list vargs) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - - +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define MAX_FAN_SPEED 15400 +#define BIT(i) (1 << (i)) + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_7_ON_FAN_BOARD, + FAN_8_ON_FAN_BOARD, + FAN_9_ON_FAN_BOARD, + FAN_10_ON_FAN_BOARD, +}; + +#define FAN_BOARD_PATH "/sys/bus/i2c/devices/8-0033/" + +#define FAN_BOARD_PATH_2 "/sys/bus/i2c/devices/9-0033/" + +#define FETCH_FAN_PATH(x) (x <= 5) ? FAN_BOARD_PATH : FAN_BOARD_PATH_2 + +#define FETCH_FAN_ID(x) ((x <= 5) ? x : (x-5) ) + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5), + CHASSIS_FAN_INFO(6), + CHASSIS_FAN_INFO(7), + CHASSIS_FAN_INFO(8), + CHASSIS_FAN_INFO(9), + CHASSIS_FAN_INFO(10) +}; + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int value = 0, fid; + char path[64] = {0}; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + /* get fan present status + */ + sprintf(path, "%s""fantray_present", FETCH_FAN_PATH(fid)); + + if (bmc_file_read_int(&value, path, 16) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + if (value & BIT(fid-1)) { + return ONLP_STATUS_OK; + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get front fan rpm + */ + sprintf(path, "%s""fan%d_input", FETCH_FAN_PATH(fid), FETCH_FAN_ID(fid)*2 - 1); + + if (bmc_file_read_int(&value, path, 10) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get rear fan rpm + */ + sprintf(path, "%s""fan%d_input", FETCH_FAN_PATH(fid), FETCH_FAN_ID(fid)*2); + + if (bmc_file_read_int(&value, path, 10) < 0) { + AIM_LOG_ERROR("Unable to read status from file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + /* take the min value from front/rear fan speed + */ + if (info->rpm > value) { + info->rpm = value; + } + + + /* set fan status based on rpm + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + + /* get speed percentage from rpm + */ + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + /* set fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + return ONLP_STATUS_OK; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + char cmd[32] = {0}; + + sprintf(cmd, "set_fan_speed.sh %d", p); + + if (bmc_send_command(cmd) < 0) { + AIM_LOG_ERROR("Unable to send command to bmc(%s)\r\n", cmd); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.c index 1d374e75..3319a00f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.c @@ -31,9 +31,9 @@ #define TTY_DEVICE "/dev/ttyACM0" #define TTY_PROMPT "@bmc:" -#define TTY_I2C_TIMEOUT 800000 +#define TTY_I2C_TIMEOUT 55000 #define TTY_BMC_LOGIN_TIMEOUT 1000000 -#define TTY_RETRY 10 +#define TTY_RETRY 3 #define MAXIMUM_TTY_BUFFER_LENGTH 1024 #define MAXIMUM_TTY_STRING_LENGTH (MAXIMUM_TTY_BUFFER_LENGTH - 1) @@ -86,6 +86,7 @@ static int tty_exec_buf(unsigned long udelay, const char *str) write(tty_fd, tty_buf, strlen(tty_buf)+1); usleep(udelay); + memset(tty_buf, 0, MAXIMUM_TTY_BUFFER_LENGTH); read(tty_fd, tty_buf, MAXIMUM_TTY_BUFFER_LENGTH); return (strstr(tty_buf, str) != NULL) ? 0 : -1; } @@ -118,26 +119,51 @@ static int tty_login(void) return -1; } +int bmc_tty_init(void) +{ + int i; + if (tty_fd >= 0){ + return 0; + } + + for (i = 1; i <= TTY_RETRY; i++) { + if (tty_open() != 0) { + AIM_LOG_ERROR("ERROR: Cannot open TTY device\n"); + continue; + } + if (tty_login() != 0) { + AIM_LOG_ERROR("ERROR: Cannot login TTY device\n"); + tty_close(); + continue; + } + + return 0; + } + + AIM_LOG_ERROR("Unable to init bmc tty\r\n"); + return -1; +} + +int bmc_tty_deinit(void) +{ + if( tty_fd != -1 ){ + tty_close(); + } + else{ + AIM_LOG_ERROR("ERROR: TTY not open\n"); + } + return 0; +} + int bmc_send_command(char *cmd) { int i, ret = 0; for (i = 1; i <= TTY_RETRY; i++) { - if (tty_open() != 0) { - printf("ERROR: Cannot open TTY device\n"); - continue; - } - if (tty_login() != 0) { - //printf("ERROR: Cannot login TTY device\n"); - tty_close(); - continue; - } - - snprintf(tty_buf, MAXIMUM_TTY_BUFFER_LENGTH, "%s", cmd); - ret = tty_exec_buf(TTY_I2C_TIMEOUT * i, TTY_PROMPT); - tty_close(); + snprintf(tty_buf, MAXIMUM_TTY_BUFFER_LENGTH, "%s", cmd); + ret = tty_exec_buf(TTY_I2C_TIMEOUT, TTY_PROMPT); if (ret != 0) { - printf("ERROR: bmc_send_command timed out\n"); +// AIM_LOG_ERROR("ERROR: bmc_send_command(%s) timed out\n", cmd); continue; } @@ -148,6 +174,63 @@ int bmc_send_command(char *cmd) return -1; } +int chk_numeric_char(char *data, int base) +{ + int len, i, orig = 0; + if( *data == '\0' ){ + return 0; + } + len = (int) strlen(data); + if( base == 10 ){ + for( i=0; i '9' ){ + return 0; + } + } + return 1; + } + else if( base == 16 ){ + if( !memcmp(data, "0x", 2) ){ + if( len <= 2 ){ + return 0; + } + orig = 2; + } + else if( !memcmp(data, "0X", 2) ){ + if( len <= 2 ){ + return 0; + } + orig = 2; + } + for( i=orig; i orig) && ( *(data+i) == 0xd ) ){ + break; + } + if( (i > orig) && ( *(data+i) == 0xa ) ){ + break; + } + if( !( ( (*(data+i) >= '0') && (*(data+i) <= '9') ) || + ( (*(data+i) >= 'A') && (*(data+i) <= 'F') ) || + ( (*(data+i) >= 'a') && (*(data+i) <= 'f') ) + ) + ){ + return 0; + } + } + return 1; + } + return 0; +} + int bmc_command_read_int(int* value, char *cmd, int base) { @@ -166,6 +249,9 @@ bmc_command_read_int(int* value, char *cmd, int base) for (i = 1; i <= TTY_RETRY; i++) { current_str = strstr(prev_str + len, cmd); if(current_str == NULL) { + if( !chk_numeric_char(prev_str + len, base) ){ + return -1; + } *value = strtoul(prev_str + len, NULL, base); break; }else { diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.h index 790978a2..44cc4d33 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/platform_lib.h @@ -64,6 +64,9 @@ int bmc_i2c_writeb(uint8_t bus, uint8_t devaddr, uint8_t addr, uint8_t value); int bmc_i2c_readw(uint8_t bus, uint8_t devaddr, uint8_t addr); int bmc_i2c_readraw(uint8_t bus, uint8_t devaddr, uint8_t addr, char* data, int data_size); +int bmc_tty_init(void); +int bmc_tty_deinit(void); + #endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/psui.c index 4d321457..7b964eb6 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/psui.c @@ -24,6 +24,7 @@ * ***********************************************************/ #include +#include #include #include #include "platform_lib.h" @@ -121,6 +122,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) if (bmc_i2c_writeb(7, 0x70, 0, value) < 0) { return ONLP_STATUS_E_INTERNAL; } + usleep(1200); /* Read vin */ addr = (pid == PSU1_ID) ? 0x59 : 0x5a; @@ -164,7 +166,10 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) } /* Get model name */ - return bmc_i2c_readraw(7, addr, 0x9a, info->model, sizeof(info->model)); + bmc_i2c_readraw(7, addr, 0x9a, info->model, sizeof(info->model)); + + /* Get serial number */ + return bmc_i2c_readraw(7, addr, 0x9e, info->serial, sizeof(info->serial)); } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sfpi.c index eceb8881..58261d91 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sfpi.c @@ -32,15 +32,17 @@ #define BIT(i) (1 << (i)) #define NUM_OF_SFP_PORT 64 +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" + static const int sfp_bus_index[] = { - 4, 3, 6, 5, 8, 7, 10, 9, - 12, 11, 14, 13, 16, 15, 18, 17, - 20, 19, 22, 21, 24, 23, 26, 25, - 28, 27, 30, 29, 32, 31, 34, 33, 44, 43, 46, 45, 48, 47, 50, 49, 52, 51, 54, 53, 56, 55, 58, 57, 60, 59, 62, 61, 64, 63, 66, 65, 68, 67, 70, 69, 72, 71, 74, 73, + 4, 3, 6, 5, 8, 7, 10, 9, + 12, 11, 14, 13, 16, 15, 18, 17, + 20, 19, 22, 21, 24, 23, 26, 25, + 28, 27, 30, 29, 32, 31, 34, 33, }; /************************************************************ @@ -103,13 +105,13 @@ onlp_sfpi_is_present(int port) int offset; if(port < 16) { - bus = 37; - }else if(port >=16 && port < 32){ - bus = 38; - }else if(port >=32 && port < 48){ bus = 77; - }else if(port >=48 && port <= 63){ + }else if(port >=16 && port < 32){ bus = 78; + }else if(port >=32 && port < 48){ + bus = 37; + }else if(port >=48 && port <= 63){ + bus = 38; } if ((port < 8) || (port >= 16 && port <= 23) || (port >= 32 && port <= 39) \ @@ -144,19 +146,19 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { case 0: case 1: - bus = 37; + bus = 77; break; case 2: case 3: - bus = 38; + bus = 78; break; case 4: case 5: - bus = 77; + bus = 37; break; case 6: case 7: - bus = 78; + bus = 38; break; default: break; @@ -193,44 +195,55 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } -static int -sfpi_eeprom_read(int port, uint8_t devaddr, uint8_t data[256]) -{ - int i; - - /* - * Read the SFP eeprom into data[] - * - * Return MISSING if SFP is missing. - * Return OK if eeprom is read - */ - memset(data, 0, 256); - - for (i = 0; i < 128; i++) { - int bus = sfp_bus_index[port]; - int val = onlp_i2c_readw(bus, devaddr, i*2, ONLP_I2C_F_FORCE); - - if (val < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - data[i*2] = val & 0xff; - data[(i*2)+1] = (val >> 8) & 0xff; - } - - return ONLP_STATUS_OK; -} - int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - return sfpi_eeprom_read(port, 0x50, data); + int size = 0; + if(port <0 || port >= NUM_OF_SFP_PORT) + return ONLP_STATUS_E_INTERNAL; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, sfp_bus_index[port]) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size(%d) is different!\r\n", port, size); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - return sfpi_eeprom_read(port, 0x51, data); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, sfp_bus_index[port]); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d, %d)", port, ret); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sysi.c index 653d45cc..13997b2f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/onlp/builds/src/module/src/sysi.c @@ -1,114 +1,115 @@ -/************************************************************ - * - * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * - ************************************************************ - * - * - * - ***********************************************************/ -#include -#include - -#include -#include -#include -#include -#include -#include -#include "platform_lib.h" - -#include "x86_64_accton_wedge100bf_65x_int.h" -#include "x86_64_accton_wedge100bf_65x_log.h" - -const char* -onlp_sysi_platform_get(void) -{ - return "x86-64-accton-wedge100bf-65x-r0"; -} - -int -onlp_sysi_onie_data_get(uint8_t** data, int* size) -{ - uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { - *data = rdata; - return ONLP_STATUS_OK; - } - } - - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; -} - -int -onlp_sysi_oids_get(onlp_oid_t* table, int max) -{ - int i; - onlp_oid_t* e = table; - memset(table, 0, max*sizeof(onlp_oid_t)); - - /* 8 Thermal sensors on the chassis */ - for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { - *e++ = ONLP_THERMAL_ID_CREATE(i); - } - - /* 2 LEDs on the chassis */ - for (i = 1; i <= CHASSIS_LED_COUNT; i++) { - *e++ = ONLP_LED_ID_CREATE(i); - } - - /* 2 PSUs on the chassis */ - for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { - *e++ = ONLP_PSU_ID_CREATE(i); - } - - /* 5 Fans on the chassis */ - for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { - *e++ = ONLP_FAN_ID_CREATE(i); - } - - return 0; -} - -int -onlp_sysi_platform_info_get(onlp_platform_info_t* pi) -{ - return ONLP_STATUS_OK; -} - -void -onlp_sysi_platform_info_free(onlp_platform_info_t* pi) -{ -} - -int -onlp_sysi_platform_manage_fans(void) -{ - return ONLP_STATUS_OK; -} - -int -onlp_sysi_platform_manage_leds(void) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#include "x86_64_accton_wedge100bf_65x_int.h" +#include "x86_64_accton_wedge100bf_65x_log.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-wedge100bf-65x-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 8 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 2 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 5 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + bmc_tty_init(); + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ +} + +int +onlp_sysi_platform_manage_fans(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/platform-config/r0/src/python/x86_64_accton_wedge100bf_65x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/platform-config/r0/src/python/x86_64_accton_wedge100bf_65x_r0/__init__.py index a8ceb80b..2cc1610d 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/platform-config/r0/src/python/x86_64_accton_wedge100bf_65x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-wedge100bf-65x/platform-config/r0/src/python/x86_64_accton_wedge100bf_65x_r0/__init__.py @@ -8,6 +8,8 @@ class OnlPlatform_x86_64_accton_wedge100bf_65x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".100.65.1" def baseconfig(self): + self.insmod('optoe') + ########### initialize I2C bus 1 & bus 2 ########### self.new_i2c_devices([ # initialize multiplexer (PCA9548) @@ -27,5 +29,135 @@ class OnlPlatform_x86_64_accton_wedge100bf_65x_r0(OnlPlatformAccton, ('24c64', 0x50, 41), ]) + + # Initialize QSFP devices + self.new_i2c_device('optoe1', 0x50, 3) + self.new_i2c_device('optoe1', 0x50, 4) + self.new_i2c_device('optoe1', 0x50, 5) + self.new_i2c_device('optoe1', 0x50, 6) + self.new_i2c_device('optoe1', 0x50, 7) + self.new_i2c_device('optoe1', 0x50, 8) + self.new_i2c_device('optoe1', 0x50, 9) + self.new_i2c_device('optoe1', 0x50, 10) + self.new_i2c_device('optoe1', 0x50, 11) + self.new_i2c_device('optoe1', 0x50, 12) + self.new_i2c_device('optoe1', 0x50, 13) + self.new_i2c_device('optoe1', 0x50, 14) + self.new_i2c_device('optoe1', 0x50, 15) + self.new_i2c_device('optoe1', 0x50, 16) + self.new_i2c_device('optoe1', 0x50, 17) + self.new_i2c_device('optoe1', 0x50, 18) + self.new_i2c_device('optoe1', 0x50, 19) + self.new_i2c_device('optoe1', 0x50, 20) + self.new_i2c_device('optoe1', 0x50, 21) + self.new_i2c_device('optoe1', 0x50, 22) + self.new_i2c_device('optoe1', 0x50, 23) + self.new_i2c_device('optoe1', 0x50, 24) + self.new_i2c_device('optoe1', 0x50, 25) + self.new_i2c_device('optoe1', 0x50, 26) + self.new_i2c_device('optoe1', 0x50, 27) + self.new_i2c_device('optoe1', 0x50, 28) + self.new_i2c_device('optoe1', 0x50, 29) + self.new_i2c_device('optoe1', 0x50, 30) + self.new_i2c_device('optoe1', 0x50, 31) + self.new_i2c_device('optoe1', 0x50, 32) + self.new_i2c_device('optoe1', 0x50, 33) + self.new_i2c_device('optoe1', 0x50, 34) + self.new_i2c_device('optoe1', 0x50, 43) + self.new_i2c_device('optoe1', 0x50, 44) + self.new_i2c_device('optoe1', 0x50, 45) + self.new_i2c_device('optoe1', 0x50, 46) + self.new_i2c_device('optoe1', 0x50, 47) + self.new_i2c_device('optoe1', 0x50, 48) + self.new_i2c_device('optoe1', 0x50, 49) + self.new_i2c_device('optoe1', 0x50, 50) + self.new_i2c_device('optoe1', 0x50, 51) + self.new_i2c_device('optoe1', 0x50, 52) + self.new_i2c_device('optoe1', 0x50, 53) + self.new_i2c_device('optoe1', 0x50, 54) + self.new_i2c_device('optoe1', 0x50, 55) + self.new_i2c_device('optoe1', 0x50, 56) + self.new_i2c_device('optoe1', 0x50, 57) + self.new_i2c_device('optoe1', 0x50, 58) + self.new_i2c_device('optoe1', 0x50, 59) + self.new_i2c_device('optoe1', 0x50, 60) + self.new_i2c_device('optoe1', 0x50, 61) + self.new_i2c_device('optoe1', 0x50, 62) + self.new_i2c_device('optoe1', 0x50, 63) + self.new_i2c_device('optoe1', 0x50, 64) + self.new_i2c_device('optoe1', 0x50, 65) + self.new_i2c_device('optoe1', 0x50, 66) + self.new_i2c_device('optoe1', 0x50, 67) + self.new_i2c_device('optoe1', 0x50, 68) + self.new_i2c_device('optoe1', 0x50, 69) + self.new_i2c_device('optoe1', 0x50, 70) + self.new_i2c_device('optoe1', 0x50, 71) + self.new_i2c_device('optoe1', 0x50, 72) + self.new_i2c_device('optoe1', 0x50, 73) + self.new_i2c_device('optoe1', 0x50, 74) + subprocess.call('echo port1 > /sys/bus/i2c/devices/44-0050/port_name', shell=True) + subprocess.call('echo port2 > /sys/bus/i2c/devices/43-0050/port_name', shell=True) + subprocess.call('echo port3 > /sys/bus/i2c/devices/46-0050/port_name', shell=True) + subprocess.call('echo port4 > /sys/bus/i2c/devices/45-0050/port_name', shell=True) + subprocess.call('echo port5 > /sys/bus/i2c/devices/48-0050/port_name', shell=True) + subprocess.call('echo port6 > /sys/bus/i2c/devices/47-0050/port_name', shell=True) + subprocess.call('echo port7 > /sys/bus/i2c/devices/50-0050/port_name', shell=True) + subprocess.call('echo port8 > /sys/bus/i2c/devices/49-0050/port_name', shell=True) + subprocess.call('echo port9 > /sys/bus/i2c/devices/52-0050/port_name', shell=True) + subprocess.call('echo port10 > /sys/bus/i2c/devices/51-0050/port_name', shell=True) + subprocess.call('echo port11 > /sys/bus/i2c/devices/54-0050/port_name', shell=True) + subprocess.call('echo port12 > /sys/bus/i2c/devices/53-0050/port_name', shell=True) + subprocess.call('echo port13 > /sys/bus/i2c/devices/56-0050/port_name', shell=True) + subprocess.call('echo port14 > /sys/bus/i2c/devices/55-0050/port_name', shell=True) + subprocess.call('echo port15 > /sys/bus/i2c/devices/58-0050/port_name', shell=True) + subprocess.call('echo port16 > /sys/bus/i2c/devices/57-0050/port_name', shell=True) + subprocess.call('echo port17 > /sys/bus/i2c/devices/60-0050/port_name', shell=True) + subprocess.call('echo port18 > /sys/bus/i2c/devices/59-0050/port_name', shell=True) + subprocess.call('echo port19 > /sys/bus/i2c/devices/62-0050/port_name', shell=True) + subprocess.call('echo port20 > /sys/bus/i2c/devices/61-0050/port_name', shell=True) + subprocess.call('echo port21 > /sys/bus/i2c/devices/64-0050/port_name', shell=True) + subprocess.call('echo port22 > /sys/bus/i2c/devices/63-0050/port_name', shell=True) + subprocess.call('echo port23 > /sys/bus/i2c/devices/66-0050/port_name', shell=True) + subprocess.call('echo port24 > /sys/bus/i2c/devices/65-0050/port_name', shell=True) + subprocess.call('echo port25 > /sys/bus/i2c/devices/68-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/67-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/70-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/69-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/72-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/71-0050/port_name', shell=True) + subprocess.call('echo port31 > /sys/bus/i2c/devices/74-0050/port_name', shell=True) + subprocess.call('echo port32 > /sys/bus/i2c/devices/73-0050/port_name', shell=True) + subprocess.call('echo port33 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port34 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port35 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port36 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port37 > /sys/bus/i2c/devices/8-0050/port_name', shell=True) + subprocess.call('echo port38 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + subprocess.call('echo port39 > /sys/bus/i2c/devices/10-0050/port_name', shell=True) + subprocess.call('echo port40 > /sys/bus/i2c/devices/9-0050/port_name', shell=True) + subprocess.call('echo port41 > /sys/bus/i2c/devices/12-0050/port_name', shell=True) + subprocess.call('echo port42 > /sys/bus/i2c/devices/11-0050/port_name', shell=True) + subprocess.call('echo port43 > /sys/bus/i2c/devices/14-0050/port_name', shell=True) + subprocess.call('echo port44 > /sys/bus/i2c/devices/13-0050/port_name', shell=True) + subprocess.call('echo port45 > /sys/bus/i2c/devices/16-0050/port_name', shell=True) + subprocess.call('echo port46 > /sys/bus/i2c/devices/15-0050/port_name', shell=True) + subprocess.call('echo port47 > /sys/bus/i2c/devices/18-0050/port_name', shell=True) + subprocess.call('echo port48 > /sys/bus/i2c/devices/17-0050/port_name', shell=True) + subprocess.call('echo port49 > /sys/bus/i2c/devices/20-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/19-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/22-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/21-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/24-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/23-0050/port_name', shell=True) + subprocess.call('echo port55 > /sys/bus/i2c/devices/26-0050/port_name', shell=True) + subprocess.call('echo port56 > /sys/bus/i2c/devices/25-0050/port_name', shell=True) + subprocess.call('echo port57 > /sys/bus/i2c/devices/28-0050/port_name', shell=True) + subprocess.call('echo port58 > /sys/bus/i2c/devices/27-0050/port_name', shell=True) + subprocess.call('echo port59 > /sys/bus/i2c/devices/30-0050/port_name', shell=True) + subprocess.call('echo port60 > /sys/bus/i2c/devices/29-0050/port_name', shell=True) + subprocess.call('echo port61 > /sys/bus/i2c/devices/32-0050/port_name', shell=True) + subprocess.call('echo port62 > /sys/bus/i2c/devices/31-0050/port_name', shell=True) + subprocess.call('echo port63 > /sys/bus/i2c/devices/34-0050/port_name', shell=True) + subprocess.call('echo port64 > /sys/bus/i2c/devices/33-0050/port_name', shell=True) return True diff --git a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/PKG.yml b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/PKG.yml index d8c6ed4a..fb67b75a 100755 --- a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/PKG.yml +++ b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c-poe REVISION=r0 +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c-poe REVISION=r0 DISTS=jessie diff --git a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/src/lib/arm-delta-ag6248c-poe-r0.yml b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/src/lib/arm-delta-ag6248c-poe-r0.yml index ac3ed810..4d30ed20 100755 --- a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/src/lib/arm-delta-ag6248c-poe-r0.yml +++ b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c-poe/platform-config/r0/src/lib/arm-delta-ag6248c-poe-r0.yml @@ -14,7 +14,7 @@ arm-delta-ag6248c-poe-r0: =: delta_ag6248c.dtb <<: *arm-iproc-kernel-package itb: - <<: *arm-itb + <<: *armel-itb loader: device: /dev/mtdblock4 diff --git a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/PKG.yml b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/PKG.yml index 16ff5c28..2c2717a8 100644 --- a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/PKG.yml +++ b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c REVISION=r0 +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c REVISION=r0 DISTS=jessie diff --git a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/src/lib/arm-delta-ag6248c-r0.yml b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/src/lib/arm-delta-ag6248c-r0.yml index ba1cbec5..d84dd9c4 100644 --- a/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/src/lib/arm-delta-ag6248c-r0.yml +++ b/packages/platforms/delta/armel/arm-delta-ag6248c/arm-delta-ag6248c/platform-config/r0/src/lib/arm-delta-ag6248c-r0.yml @@ -14,7 +14,7 @@ arm-delta-ag6248c-r0: =: delta_ag6248c.dtb <<: *arm-iproc-kernel-package itb: - <<: *arm-itb + <<: *armel-itb loader: device: /dev/mtdblock4 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag5648/modules/builds/dni_ag5648_sfp.c b/packages/platforms/delta/x86-64/x86-64-delta-ag5648/modules/builds/dni_ag5648_sfp.c index 198084f1..f3f06153 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag5648/modules/builds/dni_ag5648_sfp.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag5648/modules/builds/dni_ag5648_sfp.c @@ -308,8 +308,9 @@ static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, u8 cpld_addr_t = 0x00; int values[8] = {'\0'}; int bit_t = 0x00; - - switch (attr->index) + int offset = 0; + + switch (attr->index) { case SFP_IS_PRESENT: port_t = sfp_port_data; @@ -343,8 +344,9 @@ static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, { /* SFP Port 37-44 */ cpld_addr_t = MASTER_CPLD; reg_t = SFP_PRESENCE_6; - } - else if (port_t > 44 && port_t < 49) + offset = 4; + } + else if (port_t > 44 && port_t < 49) { /* SFP Port 45-48 */ cpld_addr_t = MASTER_CPLD; reg_t = SFP_PRESENCE_7; @@ -364,7 +366,7 @@ static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, cpld_addr_t, reg_t), 0); /* SWPLD QSFP module respond */ - bit_t = 1 << ((port_t - 1) % 8); + bit_t = 1 << ((port_t - offset - 1) % 8); values[0] = values[0] & bit_t; values[0] = values[0] / bit_t; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag5648/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag5648/onlp/builds/src/module/src/sfpi.c index 7234d966..beefbfcf 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag5648/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag5648/onlp/builds/src/module/src/sfpi.c @@ -2,7 +2,7 @@ * * * Copyright 2014 Big Switch Networks, Inc. - * Copyright (C) 2017 Delta Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the * "License"); you may not use this file except in compliance @@ -34,9 +34,9 @@ #include "platform_lib.h" /******************* Utility Function *****************************************/ -int +int ag5648_get_respond_val(int port) -{ +{ int respond_default = 0xff; int value = 0x00; if(port > NUM_OF_SFP && port <= (NUM_OF_SFP + NUM_OF_QSFP)) @@ -48,9 +48,9 @@ ag5648_get_respond_val(int port) { return respond_default; } - + } -int +int ag5648_get_respond_reg(int port) { return QSFP_RESPOND_REG; @@ -62,14 +62,14 @@ ag5648_get_respond_reg(int port) * ***********************************************************/ -int +int onlp_sfpi_init(void) { /* Called at initialization time */ return ONLP_STATUS_OK; } -int +int onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) { /*Ports {1, 54}*/ @@ -81,38 +81,37 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) } return ONLP_STATUS_OK; } - -int + +int onlp_sfpi_is_present(int port) { - char port_data[2]; + char port_data[3]; int present, present_bit; - + /* Select QSFP port */ - sprintf(port_data, "%d", port ); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); /* Read SFP/QSFP MODULE is present or not */ present_bit = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH); /* From sfp_is_present value, - * return 0 = The module is preset + * return 0 = The module is present * return 1 = The module is NOT present */ if(present_bit == 0) { present = 1; } else if (present_bit == 1) { present = 0; - AIM_LOG_ERROR("Unble to present status from port(%d)\r\n", port); } else { /* Port range over 1-54, return -1 */ - AIM_LOG_ERROR("Error to present status from port(%d)\r\n", port); + AIM_LOG_ERROR("Error to read present status from port(%d)\r\n", port); present = -1; } return present; } -int +int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { char present_all_data[24] = {0}; @@ -135,7 +134,7 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) bytes+6, bytes+7 ); - + if(count != AIM_ARRAYSIZE(bytes)) { /* Likely a CPLD read timeout. */ AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); @@ -160,7 +159,7 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) } } - /* Populate bitmap */ + /* Populate bitmap */ for(i = 0; i < NUM_OF_PORT; i++) { AIM_BITMAP_MOD(dst, i+1, !(presence_all & 1)); presence_all >>= 1; @@ -168,14 +167,14 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } -int +int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char port_data[2]; + char port_data[3]; int sfp_respond_reg; int sfp_respond_val; - + /* Get respond register if port have it */ sfp_respond_reg = ag5648_get_respond_reg(port); @@ -183,9 +182,9 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) sfp_respond_val = ag5648_get_respond_val(port); dni_lock_cpld_write_attribute(MASTER_CPLD_PATH, sfp_respond_reg, sfp_respond_val); - + /* Select port */ - sprintf(port_data, "%d", port ); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); memset(data, 0 ,256); @@ -200,7 +199,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) return ONLP_STATUS_OK; } -int onlp_sfpi_port_map(int port, int* rport) +int onlp_sfpi_port_map(int port, int* rport) { *rport = port; return ONLP_STATUS_OK; @@ -208,15 +207,15 @@ int onlp_sfpi_port_map(int port, int* rport) int -onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int value_t; - char port_data[2]; + char port_data[3]; /* Select QSFP port */ - sprintf(port_data, "%d", port ); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); - switch (control) { + switch (control) { case ONLP_SFP_CONTROL_RESET_STATE: *value = dni_i2c_lock_read_attribute(NULL, SFP_RESET_PATH); /* From sfp_reset value, @@ -225,11 +224,11 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) */ if (*value == 0) { - *value = 1; + *value = 1; } - else if (*value == 1) + else if (*value == 1) { - *value = 0; + *value = 0; } value_t = ONLP_STATUS_OK; break; @@ -260,13 +259,13 @@ int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int value_t; - char port_data[2]; - sprintf(port_data, "%d", port); + char port_data[3]; + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); switch (control) { case ONLP_SFP_CONTROL_RESET_STATE: - sprintf(port_data, "%d", value); + snprintf(port_data, sizeof(port_data), "%d", value); dni_i2c_lock_write_attribute(NULL, port_data, SFP_RESET_PATH); value_t = ONLP_STATUS_OK; break; @@ -277,7 +276,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) value_t = ONLP_STATUS_E_UNSUPPORTED; break; case ONLP_SFP_CONTROL_LP_MODE: - sprintf(port_data, "%d", value); + snprintf(port_data, sizeof(port_data), "%d", value); dni_i2c_lock_write_attribute(NULL, port_data, SFP_LP_MODE_PATH); value_t = ONLP_STATUS_OK; break; @@ -291,7 +290,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) { - char port_data[2]; + char port_data[3]; int sfp_respond_reg, sfp_respond_val; dev_info_t dev_info; @@ -303,7 +302,7 @@ onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) dni_lock_cpld_write_attribute(MASTER_CPLD_PATH, sfp_respond_reg, sfp_respond_val); /* Select port */ - sprintf(port_data, "%d", port); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); dev_info.bus = I2C_BUS_4; @@ -318,7 +317,7 @@ onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) int onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) { - char port_data[2]; + char port_data[3]; int sfp_respond_reg, sfp_respond_val; dev_info_t dev_info; @@ -330,7 +329,7 @@ onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) dni_lock_cpld_write_attribute(MASTER_CPLD_PATH, sfp_respond_reg, sfp_respond_val); /* Select port */ - sprintf(port_data, "%d", port); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); dev_info.bus = I2C_BUS_4; @@ -346,7 +345,7 @@ onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) int onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) { - char port_data[2]; + char port_data[3]; int sfp_respond_reg, sfp_respond_val; dev_info_t dev_info; @@ -358,7 +357,7 @@ onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) dni_lock_cpld_write_attribute(MASTER_CPLD_PATH, sfp_respond_reg, sfp_respond_val); /* Select port */ - sprintf(port_data, "%d", port); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); dev_info.bus = I2C_BUS_4; @@ -373,7 +372,7 @@ onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) { - char port_data[2]; + char port_data[3]; int sfp_respond_reg, sfp_respond_val; dev_info_t dev_info; @@ -385,7 +384,7 @@ onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) dni_lock_cpld_write_attribute(MASTER_CPLD_PATH, sfp_respond_reg, sfp_respond_val); /* Select port */ - sprintf(port_data, "%d", port); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); dev_info.bus = I2C_BUS_4; @@ -401,9 +400,9 @@ onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) int onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) { - char port_data[2] ; + char port_data[3] ; /* Select QSFP port */ - sprintf(port_data, "%d", port ); + snprintf(port_data, sizeof(port_data), "%d", port); dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); switch (control) { case ONLP_SFP_CONTROL_RESET_STATE: diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag7648/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag7648/onlp/builds/src/module/src/sfpi.c index a1b2debd..135be9e7 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag7648/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag7648/onlp/builds/src/module/src/sfpi.c @@ -70,75 +70,75 @@ struct portCtrl{ int rxLosRegBit; int txDisableReg; int txDisableRegBit; - + }; #define CPLD_NAME1 "SYSCPLD" #define CPLD_NAME2 "MASTERCPLD" #define CPLD_NAME3 "SLAVECPLD" -static struct portCtrl gPortCtrl[] = +static struct portCtrl gPortCtrl[] = { {1, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 0, SFP_PLUS_1_8_RX_LOS_REG, 0, SFP_PLUS_1_8_TX_DISABLE_REG, 0}, {2, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 1, SFP_PLUS_1_8_RX_LOS_REG, 1, SFP_PLUS_1_8_TX_DISABLE_REG, 1}, - {3, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 2, SFP_PLUS_1_8_RX_LOS_REG, 1, SFP_PLUS_1_8_TX_DISABLE_REG, 2}, - {4, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 3, SFP_PLUS_1_8_RX_LOS_REG, 2, SFP_PLUS_1_8_TX_DISABLE_REG, 3}, - {5, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 4, SFP_PLUS_1_8_RX_LOS_REG, 3, SFP_PLUS_1_8_TX_DISABLE_REG, 4}, - {6, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 5, SFP_PLUS_1_8_RX_LOS_REG, 4, SFP_PLUS_1_8_TX_DISABLE_REG, 5}, - {7, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 6, SFP_PLUS_1_8_RX_LOS_REG, 5, SFP_PLUS_1_8_TX_DISABLE_REG, 6}, - {8, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 7, SFP_PLUS_1_8_RX_LOS_REG, 6, SFP_PLUS_1_8_TX_DISABLE_REG, 7}, + {3, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 2, SFP_PLUS_1_8_RX_LOS_REG, 2, SFP_PLUS_1_8_TX_DISABLE_REG, 2}, + {4, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 3, SFP_PLUS_1_8_RX_LOS_REG, 3, SFP_PLUS_1_8_TX_DISABLE_REG, 3}, + {5, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 4, SFP_PLUS_1_8_RX_LOS_REG, 4, SFP_PLUS_1_8_TX_DISABLE_REG, 4}, + {6, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 5, SFP_PLUS_1_8_RX_LOS_REG, 5, SFP_PLUS_1_8_TX_DISABLE_REG, 5}, + {7, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 6, SFP_PLUS_1_8_RX_LOS_REG, 6, SFP_PLUS_1_8_TX_DISABLE_REG, 6}, + {8, CPLD_NAME3, SFP_PLUS_1_8_PRESENT_REG, 7, SFP_PLUS_1_8_RX_LOS_REG, 7, SFP_PLUS_1_8_TX_DISABLE_REG, 7}, {9, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 0, SFP_PLUS_9_16_RX_LOS_REG, 0, SFP_PLUS_9_16_TX_DISABLE_REG, 0}, {10, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 1, SFP_PLUS_9_16_RX_LOS_REG, 1, SFP_PLUS_9_16_TX_DISABLE_REG, 1}, - {11, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 2, SFP_PLUS_9_16_RX_LOS_REG, 1, SFP_PLUS_9_16_TX_DISABLE_REG, 2}, - {12, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 3, SFP_PLUS_9_16_RX_LOS_REG, 2, SFP_PLUS_9_16_TX_DISABLE_REG, 3}, - {13, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 4, SFP_PLUS_9_16_RX_LOS_REG, 3, SFP_PLUS_9_16_TX_DISABLE_REG, 4}, - {14, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 5, SFP_PLUS_9_16_RX_LOS_REG, 4, SFP_PLUS_9_16_TX_DISABLE_REG, 5}, - {15, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 6, SFP_PLUS_9_16_RX_LOS_REG, 5, SFP_PLUS_9_16_TX_DISABLE_REG, 6}, - {16, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 7, SFP_PLUS_9_16_RX_LOS_REG, 6, SFP_PLUS_9_16_TX_DISABLE_REG, 7}, + {11, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 2, SFP_PLUS_9_16_RX_LOS_REG, 2, SFP_PLUS_9_16_TX_DISABLE_REG, 2}, + {12, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 3, SFP_PLUS_9_16_RX_LOS_REG, 3, SFP_PLUS_9_16_TX_DISABLE_REG, 3}, + {13, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 4, SFP_PLUS_9_16_RX_LOS_REG, 4, SFP_PLUS_9_16_TX_DISABLE_REG, 4}, + {14, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 5, SFP_PLUS_9_16_RX_LOS_REG, 5, SFP_PLUS_9_16_TX_DISABLE_REG, 5}, + {15, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 6, SFP_PLUS_9_16_RX_LOS_REG, 6, SFP_PLUS_9_16_TX_DISABLE_REG, 6}, + {16, CPLD_NAME3, SFP_PLUS_9_16_PRESENT_REG, 7, SFP_PLUS_9_16_RX_LOS_REG, 7, SFP_PLUS_9_16_TX_DISABLE_REG, 7}, {17, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 0, SFP_PLUS_17_24_RX_LOS_REG, 0, SFP_PLUS_17_24_TX_DISABLE_REG, 0}, {18, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 1, SFP_PLUS_17_24_RX_LOS_REG, 1, SFP_PLUS_17_24_TX_DISABLE_REG, 1}, - {19, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 2, SFP_PLUS_17_24_RX_LOS_REG, 1, SFP_PLUS_17_24_TX_DISABLE_REG, 2}, - {20, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 3, SFP_PLUS_17_24_RX_LOS_REG, 2, SFP_PLUS_17_24_TX_DISABLE_REG, 3}, - {21, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 4, SFP_PLUS_17_24_RX_LOS_REG, 3, SFP_PLUS_17_24_TX_DISABLE_REG, 4}, - {22, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 5, SFP_PLUS_17_24_RX_LOS_REG, 4, SFP_PLUS_17_24_TX_DISABLE_REG, 5}, - {23, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 6, SFP_PLUS_17_24_RX_LOS_REG, 5, SFP_PLUS_17_24_TX_DISABLE_REG, 6}, - {24, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 7, SFP_PLUS_17_24_RX_LOS_REG, 6, SFP_PLUS_17_24_TX_DISABLE_REG, 7}, + {19, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 2, SFP_PLUS_17_24_RX_LOS_REG, 2, SFP_PLUS_17_24_TX_DISABLE_REG, 2}, + {20, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 3, SFP_PLUS_17_24_RX_LOS_REG, 3, SFP_PLUS_17_24_TX_DISABLE_REG, 3}, + {21, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 4, SFP_PLUS_17_24_RX_LOS_REG, 4, SFP_PLUS_17_24_TX_DISABLE_REG, 4}, + {22, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 5, SFP_PLUS_17_24_RX_LOS_REG, 5, SFP_PLUS_17_24_TX_DISABLE_REG, 5}, + {23, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 6, SFP_PLUS_17_24_RX_LOS_REG, 6, SFP_PLUS_17_24_TX_DISABLE_REG, 6}, + {24, CPLD_NAME3, SFP_PLUS_17_24_PRESENT_REG, 7, SFP_PLUS_17_24_RX_LOS_REG, 7, SFP_PLUS_17_24_TX_DISABLE_REG, 7}, {25, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 0, SFP_PLUS_25_32_RX_LOS_REG, 0, SFP_PLUS_25_32_TX_DISABLE_REG, 0}, {26, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 1, SFP_PLUS_25_32_RX_LOS_REG, 1, SFP_PLUS_25_32_TX_DISABLE_REG, 1}, - {27, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 2, SFP_PLUS_25_32_RX_LOS_REG, 1, SFP_PLUS_25_32_TX_DISABLE_REG, 2}, - {28, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 3, SFP_PLUS_25_32_RX_LOS_REG, 2, SFP_PLUS_25_32_TX_DISABLE_REG, 3}, - {29, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 4, SFP_PLUS_25_32_RX_LOS_REG, 3, SFP_PLUS_25_32_TX_DISABLE_REG, 4}, - {30, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 5, SFP_PLUS_25_32_RX_LOS_REG, 4, SFP_PLUS_25_32_TX_DISABLE_REG, 5}, - {31, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 6, SFP_PLUS_25_32_RX_LOS_REG, 5, SFP_PLUS_25_32_TX_DISABLE_REG, 6}, - {32, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 7, SFP_PLUS_25_32_RX_LOS_REG, 6, SFP_PLUS_25_32_TX_DISABLE_REG, 7}, + {27, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 2, SFP_PLUS_25_32_RX_LOS_REG, 2, SFP_PLUS_25_32_TX_DISABLE_REG, 2}, + {28, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 3, SFP_PLUS_25_32_RX_LOS_REG, 3, SFP_PLUS_25_32_TX_DISABLE_REG, 3}, + {29, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 4, SFP_PLUS_25_32_RX_LOS_REG, 4, SFP_PLUS_25_32_TX_DISABLE_REG, 4}, + {30, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 5, SFP_PLUS_25_32_RX_LOS_REG, 5, SFP_PLUS_25_32_TX_DISABLE_REG, 5}, + {31, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 6, SFP_PLUS_25_32_RX_LOS_REG, 6, SFP_PLUS_25_32_TX_DISABLE_REG, 6}, + {32, CPLD_NAME3, SFP_PLUS_25_32_PRESENT_REG, 7, SFP_PLUS_25_32_RX_LOS_REG, 7, SFP_PLUS_25_32_TX_DISABLE_REG, 7}, {33, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 0, SFP_PLUS_33_40_RX_LOS_REG, 0, SFP_PLUS_33_40_TX_DISABLE_REG, 0}, {34, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 1, SFP_PLUS_33_40_RX_LOS_REG, 1, SFP_PLUS_33_40_TX_DISABLE_REG, 1}, - {35, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 2, SFP_PLUS_33_40_RX_LOS_REG, 1, SFP_PLUS_33_40_TX_DISABLE_REG, 2}, - {36, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 3, SFP_PLUS_33_40_RX_LOS_REG, 2, SFP_PLUS_33_40_TX_DISABLE_REG, 3}, - {37, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 4, SFP_PLUS_33_40_RX_LOS_REG, 3, SFP_PLUS_33_40_TX_DISABLE_REG, 4}, - {38, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 5, SFP_PLUS_33_40_RX_LOS_REG, 4, SFP_PLUS_33_40_TX_DISABLE_REG, 5}, - {39, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 6, SFP_PLUS_33_40_RX_LOS_REG, 5, SFP_PLUS_33_40_TX_DISABLE_REG, 6}, - {40, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 7, SFP_PLUS_33_40_RX_LOS_REG, 6, SFP_PLUS_33_40_TX_DISABLE_REG, 7}, + {35, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 2, SFP_PLUS_33_40_RX_LOS_REG, 2, SFP_PLUS_33_40_TX_DISABLE_REG, 2}, + {36, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 3, SFP_PLUS_33_40_RX_LOS_REG, 3, SFP_PLUS_33_40_TX_DISABLE_REG, 3}, + {37, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 4, SFP_PLUS_33_40_RX_LOS_REG, 4, SFP_PLUS_33_40_TX_DISABLE_REG, 4}, + {38, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 5, SFP_PLUS_33_40_RX_LOS_REG, 5, SFP_PLUS_33_40_TX_DISABLE_REG, 5}, + {39, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 6, SFP_PLUS_33_40_RX_LOS_REG, 6, SFP_PLUS_33_40_TX_DISABLE_REG, 6}, + {40, CPLD_NAME3, SFP_PLUS_33_40_PRESENT_REG, 7, SFP_PLUS_33_40_RX_LOS_REG, 7, SFP_PLUS_33_40_TX_DISABLE_REG, 7}, {41, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 0, SFP_PLUS_41_48_RX_LOS_REG, 0, SFP_PLUS_41_48_TX_DISABLE_REG, 0}, {42, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 1, SFP_PLUS_41_48_RX_LOS_REG, 1, SFP_PLUS_41_48_TX_DISABLE_REG, 1}, - {43, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 2, SFP_PLUS_41_48_RX_LOS_REG, 1, SFP_PLUS_41_48_TX_DISABLE_REG, 2}, - {44, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 3, SFP_PLUS_41_48_RX_LOS_REG, 2, SFP_PLUS_41_48_TX_DISABLE_REG, 3}, - {45, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 4, SFP_PLUS_41_48_RX_LOS_REG, 3, SFP_PLUS_41_48_TX_DISABLE_REG, 4}, - {46, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 5, SFP_PLUS_41_48_RX_LOS_REG, 4, SFP_PLUS_41_48_TX_DISABLE_REG, 5}, - {47, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 6, SFP_PLUS_41_48_RX_LOS_REG, 5, SFP_PLUS_41_48_TX_DISABLE_REG, 6}, - {48, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 7, SFP_PLUS_41_48_RX_LOS_REG, 6, SFP_PLUS_41_48_TX_DISABLE_REG, 7}, + {43, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 2, SFP_PLUS_41_48_RX_LOS_REG, 2, SFP_PLUS_41_48_TX_DISABLE_REG, 2}, + {44, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 3, SFP_PLUS_41_48_RX_LOS_REG, 3, SFP_PLUS_41_48_TX_DISABLE_REG, 3}, + {45, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 4, SFP_PLUS_41_48_RX_LOS_REG, 4, SFP_PLUS_41_48_TX_DISABLE_REG, 4}, + {46, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 5, SFP_PLUS_41_48_RX_LOS_REG, 5, SFP_PLUS_41_48_TX_DISABLE_REG, 5}, + {47, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 6, SFP_PLUS_41_48_RX_LOS_REG, 6, SFP_PLUS_41_48_TX_DISABLE_REG, 6}, + {48, CPLD_NAME3, SFP_PLUS_41_48_PRESENT_REG, 7, SFP_PLUS_41_48_RX_LOS_REG, 7, SFP_PLUS_41_48_TX_DISABLE_REG, 7}, {49, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 0, INVALID_REG, 0, INVALID_REG_BIT, 0}, {50, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 1, INVALID_REG, 1, INVALID_REG_BIT, 1}, - {51, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 2, INVALID_REG, 1, INVALID_REG_BIT, 2}, - {52, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 3, INVALID_REG, 2, INVALID_REG_BIT, 3}, - {53, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 4, INVALID_REG, 3, INVALID_REG_BIT, 4}, - {54, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 5, INVALID_REG, 4, INVALID_REG_BIT, 5}, + {51, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 2, INVALID_REG, 2, INVALID_REG_BIT, 2}, + {52, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 3, INVALID_REG, 3, INVALID_REG_BIT, 3}, + {53, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 4, INVALID_REG, 4, INVALID_REG_BIT, 4}, + {54, CPLD_NAME2, QSFP_49_54_PRESENT_REG, 5, INVALID_REG, 5, INVALID_REG_BIT, 5}, {0xFFFF, "", INVALID_REG, 0, INVALID_REG, 0, INVALID_REG_BIT, 0}, @@ -190,7 +190,7 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present,r_data; - + if((port >= SFP_PLUS_MIN_PORT) && (port <= QSFP_MAX_PORT)){ r_data=i2c_devname_read_byte(gPortCtrl[port - 1].cpldName, gPortCtrl[port - 1].presentReg); } @@ -198,7 +198,7 @@ onlp_sfpi_is_present(int port) AIM_LOG_ERROR("The port %d is invalid \r\n", port); return ONLP_STATUS_E_UNSUPPORTED; } - + if(r_data<0){ AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; @@ -218,17 +218,17 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) uint64_t presence_all=0; AIM_BITMAP_CLR_ALL(dst); - + if(platform_id == PLATFORM_ID_DELTA_AG7648_R0) - { + { port = 1; - + } else{ AIM_LOG_ERROR("The platform id %d is invalid \r\n", platform_id); return ONLP_STATUS_E_UNSUPPORTED; } - + /*read 8 ports present status once*/ for (i = port; i <= QSFP_MAX_PORT;) { @@ -262,13 +262,13 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { int status; int port,i = 0; - uint64_t rx_los_all; - - + uint64_t rx_los_all; + + if(platform_id == PLATFORM_ID_DELTA_AG7648_R0) - { + { port = 1; - + } else{ AIM_LOG_ERROR("The platform id %d is invalid \r\n", platform_id); @@ -308,10 +308,10 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) * Return MISSING if SFP is missing. * Return OK if eeprom is read */ - + int i;//,r_data,re_cnt; char sfp_name[32]; - + //int i,re_cnt;uint8_t r_data; memset(data, 0, 256); memset(sfp_name, 0x0, sizeof(sfp_name)); @@ -346,7 +346,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - + return onlp_sfpi_eeprom_read( port, data); } @@ -356,32 +356,32 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) /*value is 1 if the tx disable value is 0 if the tx enable */ - + int rc,r_data,dis_value,present; - + if (port < SFP_PLUS_MIN_PORT || port > QSFP_MAX_PORT) { AIM_LOG_ERROR("port %d is not invalid\r\n", port); return ONLP_STATUS_E_INVALID; } present=onlp_sfpi_is_present(port); - + if(present <= 0){ AIM_LOG_INFO("The port %d is not present and can not set tx disable\r\n",port); return ONLP_STATUS_E_UNSUPPORTED; } - r_data = i2c_devname_read_byte(gPortCtrl[port - 1].cpldName, gPortCtrl[port - 1].txDisableReg); + r_data = i2c_devname_read_byte(gPortCtrl[port - 1].cpldName, gPortCtrl[port - 1].txDisableReg); if(r_data<0){ AIM_LOG_INFO("Unable to read sfp tx disable reg value\r\n"); return ONLP_STATUS_E_INTERNAL; } - + r_data &= ~(0x1 << gPortCtrl[port - 1].txDisableReg); dis_value = value << gPortCtrl[port - 1].txDisableReg; dis_value |= r_data; - + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: @@ -406,7 +406,7 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int r_data,present; - + if (port < SFP_PLUS_MIN_PORT || port > QSFP_MAX_PORT) { AIM_LOG_ERROR("port %d is not invalid\r\n", port); @@ -414,7 +414,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) } present=onlp_sfpi_is_present(port); - + if(present <= 0){ AIM_LOG_INFO("The port %d is not present\r\n",port); return ONLP_STATUS_E_UNSUPPORTED; @@ -425,7 +425,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_RX_LOS: { r_data=i2c_devname_read_byte(gPortCtrl[port - 1].cpldName, gPortCtrl[port - 1].rxLosReg); - + if (r_data<0) { AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; @@ -451,8 +451,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) default: return ONLP_STATUS_E_UNSUPPORTED; } - - + + return ONLP_STATUS_OK; } diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/fani.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/fani.c index b4801ac1..80123c55 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/fani.c @@ -105,7 +105,7 @@ dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info) { int rpm = 0; char fullpath[100] = {0}; - uint8_t present_bit=0x00, bit=0x00; + uint8_t present_bit=0x00; mux_info_t mux_info; mux_info.offset = SWPLD_PSU_FAN_I2C_MUX_REG; @@ -117,7 +117,7 @@ dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info) dev_info.addr = FAN_IO_CTL; dev_info.offset = 0x00; dev_info.flags = DEFAULT_FLAG; - + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); rpm = dni_i2c_lock_read_attribute(&mux_info, fullpath); info->rpm = rpm; @@ -128,42 +128,42 @@ dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info) /* get speed percentage from rpm */ info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; - + mux_info.channel = 0x07; present_bit = dni_i2c_lock_read(&mux_info, &dev_info); switch(local_id) { case FAN_1_ON_FAN_BOARD: case FAN_6_ON_FAN_BOARD: - if((present_bit & (bit+1)) == 0) + if((present_bit & 1) == 0) info->status |= ONLP_FAN_STATUS_PRESENT; else info->status |= ONLP_FAN_STATUS_FAILED; break; case FAN_2_ON_FAN_BOARD: case FAN_7_ON_FAN_BOARD: - if((present_bit & ((bit+1)<<1)) == 0) + if((present_bit & (1<<1)) == 0) info->status |= ONLP_FAN_STATUS_PRESENT; else info->status |= ONLP_FAN_STATUS_FAILED; break; case FAN_3_ON_FAN_BOARD: case FAN_8_ON_FAN_BOARD: - if((present_bit & ((bit+1)<<2)) == 0) + if((present_bit & (1<<2)) == 0) info->status |= ONLP_FAN_STATUS_PRESENT; else info->status |= ONLP_FAN_STATUS_FAILED; break; case FAN_4_ON_FAN_BOARD: case FAN_9_ON_FAN_BOARD: - if((present_bit & ((bit+1)<<3)) == 0) + if((present_bit & (1<<3)) == 0) info->status |= ONLP_FAN_STATUS_PRESENT; else info->status |= ONLP_FAN_STATUS_FAILED; break; case FAN_5_ON_FAN_BOARD: case FAN_10_ON_FAN_BOARD: - if((present_bit & ((bit+1)<<4)) == 0) + if((present_bit & (1<<4)) == 0) info->status |= ONLP_FAN_STATUS_PRESENT; else info->status |= ONLP_FAN_STATUS_FAILED; @@ -179,7 +179,7 @@ dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) int r_data = 0; uint8_t channel = 0x00; char fullpath[80] = {0}; - char channel_data[2] = {'\0'}; + char channel_data[3] = {'\0'}; mux_info_t mux_info; dev_info_t dev_info; @@ -235,7 +235,7 @@ dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) /* get speed percentage from rpm */ info->percentage = ((info->rpm) * 100) / MAX_PSU_FAN_SPEED; - + return ONLP_STATUS_OK; } @@ -245,6 +245,7 @@ dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) int onlp_fani_init(void) { + lockinit(); return ONLP_STATUS_OK; } @@ -338,11 +339,11 @@ onlp_fani_rpm_set(onlp_oid_t id, int rpm) */ int onlp_fani_percentage_set(onlp_oid_t id, int p) -{ +{ int local_id; char data[10] = {0}; char fullpath[70] = {0}; - char channel_data[2] = {'\0'}; + char channel_data[3] = {'\0'}; VALIDATE(id); local_id = ONLP_OID_ID_GET(id); @@ -375,11 +376,11 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) } sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].ctrl_speed); - + /* Write percentage to psu_fan1_duty_cycle_percentage */ sprintf(data, "%d", p); dni_i2c_lock_write_attribute(NULL, data, fullpath); - + return ONLP_STATUS_OK; } diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/ledi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/ledi.c index 4163b7de..71dbc86f 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/ledi.c @@ -99,6 +99,7 @@ static onlp_led_info_t linfo[] = int onlp_ledi_init(void) { + lockinit(); return ONLP_STATUS_OK; } @@ -311,15 +312,15 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) if(mode == ONLP_LED_MODE_GREEN) { front_panel_led_value |= 0x01; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_ORANGE) { front_panel_led_value |= 0x02; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); break; case LED_FRONT_PWR1: /* Clean bit 7,6 */ @@ -329,18 +330,18 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) { /* Green */ front_panel_led_value |= 0x40; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_ORANGE_BLINKING) { /* BLINKING ORANGE */ front_panel_led_value |= 0x80; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_OFF) { front_panel_led_value &= ~0xC0; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else return ONLP_STATUS_E_UNSUPPORTED; @@ -353,18 +354,18 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) { /* Green */ front_panel_led_value |= 0x10; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_ORANGE_BLINKING) { /* BLINKING ORANGE */ front_panel_led_value |= 0x20; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_OFF) { front_panel_led_value &= ~0x30; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else return ONLP_STATUS_E_UNSUPPORTED; @@ -376,20 +377,20 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) if(mode == ONLP_LED_MODE_GREEN_BLINKING) { front_panel_led_value |= 0x08; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if (mode == ONLP_LED_MODE_GREEN) { front_panel_led_value |= 0x04; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else if (mode == ONLP_LED_MODE_RED) { front_panel_led_value |= 0x0c; - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(LED_REG, front_panel_led_value); + dni_swpld_write_attribute(LED_REG, front_panel_led_value,BUS_LOCK); break; case LED_REAR_FAN_TRAY_1: @@ -397,75 +398,75 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) if(mode == ONLP_LED_MODE_GREEN) {/* Green light */ fan_tray_led_reg_value |= 0x40; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_RED) {/* Red light */ fan_tray_led_reg_value |= 0x80; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); break; case LED_REAR_FAN_TRAY_2: fan_tray_led_reg_value &= ~0x30; if(mode == ONLP_LED_MODE_GREEN) {/* Green light */ fan_tray_led_reg_value |= 0x10; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_RED) {/* Red light */ fan_tray_led_reg_value |= 0x20; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); break; case LED_REAR_FAN_TRAY_3: fan_tray_led_reg_value &= ~0x0c; if(mode == ONLP_LED_MODE_GREEN) {/* Green light */ fan_tray_led_reg_value |= 0x04; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_RED) {/* Red light */ fan_tray_led_reg_value |= 0x08; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); break; case LED_REAR_FAN_TRAY_4: fan_tray_led_reg_value &= ~0x03; if(mode == ONLP_LED_MODE_GREEN) {/* Green light */ fan_tray_led_reg_value |= 0x01; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_RED) {/* Red light */ fan_tray_led_reg_value |= 0x02; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); break; case LED_REAR_FAN_TRAY_5: fan_tray_led_reg_2_value &= ~0xC0; if(mode == ONLP_LED_MODE_GREEN) {/* Green light */ fan_tray_led_reg_2_value |= 0x40; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG_2, fan_tray_led_reg_2_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG_2, fan_tray_led_reg_2_value,BUS_LOCK); } else if(mode == ONLP_LED_MODE_RED) {/* Red light */ fan_tray_led_reg_2_value |= 0x80; - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG_2, fan_tray_led_reg_2_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG_2, fan_tray_led_reg_2_value,BUS_LOCK); } else - dni_lock_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value); + dni_swpld_write_attribute(FAN_TRAY_LED_REG, fan_tray_led_reg_value,BUS_LOCK); break; } return ONLP_STATUS_OK; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.c index 743806ad..e439bbdb 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.c @@ -33,8 +33,30 @@ #include #include "platform_lib.h" #include -#include -#include + +static onlp_shlock_t* dni_lock = NULL; + +#define DNI_BUS_LOCK() \ + do{ \ + onlp_shlock_take(dni_lock); \ + }while(0) + +#define DNI_BUS_UNLOCK() \ + do{ \ + onlp_shlock_give(dni_lock);\ + }while(0) + +#define DNILOCK_MAGIC 0xE3A0B4E6 + +void lockinit() +{ + static int sem_inited =0; + if(!sem_inited) + { + onlp_shlock_create(DNILOCK_MAGIC, &dni_lock, "bus-lock"); + sem_inited =1; + } +} int dni_fan_speed_good() { @@ -65,31 +87,39 @@ int dni_fan_speed_good() int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len) { - int fd; + int fd,rv=0; int len; + DNI_BUS_LOCK(); if ((buffer == NULL) || (buf_size < 0)) { - return -1; + rv=-1; + goto ERROR; } if ((fd = open(filename, O_RDONLY)) == -1) { - return -1; + rv=-1; + goto ERROR; } if ((len = read(fd, buffer, buf_size)) < 0) { close(fd); - return -1; + rv= -1; + goto ERROR; } if ((close(fd) == -1)) { - return -1; + rv= -1; + goto ERROR; } if ((len > buf_size) || (data_len != 0 && len != data_len)) { - return -1; + rv= -1; + goto ERROR; } - return 0; +ERROR: + DNI_BUS_UNLOCK(); + return rv; } int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len) @@ -113,83 +143,72 @@ int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, in int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info) { int r_data=0; - pthread_mutex_lock(&mutex); + DNI_BUS_LOCK(); if(mux_info != NULL) - dni_lock_swpld_write_attribute(mux_info->offset, mux_info->channel); + dni_swpld_write_attribute(mux_info->offset, mux_info->channel,BUS_LOCKED); if(dev_info->size == 1) r_data = onlp_i2c_readb(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); else r_data = onlp_i2c_readw(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); - pthread_mutex_unlock(&mutex); + DNI_BUS_UNLOCK(); return r_data; } int dni_i2c_lock_write( mux_info_t * mux_info, dev_info_t * dev_info) { - pthread_mutex_lock(&mutex); + DNI_BUS_LOCK(); if(mux_info != NULL) - dni_lock_swpld_write_attribute(mux_info->offset, mux_info->channel); + dni_swpld_write_attribute(mux_info->offset, mux_info->channel,BUS_LOCKED); /* Write size */ if(dev_info->size == 1) onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); else onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); - pthread_mutex_unlock(&mutex); + DNI_BUS_UNLOCK(); return 0; } int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) { - int fd, len, nbytes = 10; + int fd, len, nbytes = 10,rv = -1; char r_data[10] = {0}; - pthread_mutex_lock(&mutex); + DNI_BUS_LOCK(); if(mux_info != NULL) - dni_lock_swpld_write_attribute(mux_info->offset, mux_info->channel); - if ((fd = open(fullpath, O_RDONLY)) == -1) + dni_swpld_write_attribute(mux_info->offset, mux_info->channel,BUS_LOCKED); + if ((fd = open(fullpath, O_RDONLY)) >= 0) { - goto ERROR; - } - if ((len = read(fd, r_data, nbytes)) <= 0) - { - goto ERROR; + if ((len = read(fd, r_data, nbytes)) > 0) + { + rv=atoi(r_data); + } } close(fd); - pthread_mutex_unlock(&mutex); - return atoi(r_data); -ERROR: - close(fd); - pthread_mutex_unlock(&mutex); - return -1; + DNI_BUS_UNLOCK(); + return rv; } int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath) { - int fd, len, nbytes = 10; - pthread_mutex_lock(&mutex); + int fd, nbytes = 10, rv = -1; + DNI_BUS_LOCK(); if(mux_info!=NULL) - dni_lock_swpld_write_attribute(mux_info->offset, mux_info->channel); + dni_swpld_write_attribute(mux_info->offset, mux_info->channel,BUS_LOCKED); /* Create output file descriptor */ - fd = open(fullpath, O_WRONLY, 0644); - if (fd == -1) + if((fd = open(fullpath, O_WRONLY, 0644)) >= 0) { - goto ERROR; - } - len = write (fd, data, (ssize_t) nbytes); - if (len != nbytes) - { - goto ERROR; + if(write(fd, data, (ssize_t) nbytes) > 0) + { + fsync(fd); + rv = 0; + } } close(fd); - pthread_mutex_unlock(&mutex); - return 0; -ERROR: - close(fd); - pthread_mutex_unlock(&mutex); - return -1; + DNI_BUS_UNLOCK(); + return rv; } @@ -197,81 +216,63 @@ ERROR: Use this function to select address & read the data. */ int dni_lock_swpld_read_attribute(int addr) { - int fd, len, nbytes = 10,data = 0; + int fd , fd1, nbytes = 10,data = 0, rv=-1; char r_data[10] = {0}; char address[10] = {0}; sprintf(address, "%02x", addr); - pthread_mutex_lock(&mutex1); + DNI_BUS_LOCK(); /* Create output file descriptor */ - fd = open(SWPLD_ADDR_PATH, O_WRONLY, 0644); - if (fd == -1) + if((fd = open(SWPLD_ADDR_PATH, O_WRONLY, 0644)) >=0) { - goto ERROR; + if(write (fd, address, 2) >0) + { + fsync(fd); + if ((fd1 = open(SWPLD_DATA_PATH, O_RDONLY,0644)) >= 0) + { + if ((read(fd1, r_data, nbytes)) > 0) + { + sscanf( r_data, "%x", &data); + rv=data; + } + } + close(fd1); + } } - len = write (fd, address, 2); - if(len <= 0) - { - goto ERROR; - } - close(fd); - if ((fd = open(SWPLD_DATA_PATH, O_RDONLY,0644)) == -1) - { - goto ERROR; - } - if ((len = read(fd, r_data, nbytes)) <= 0) - { - goto ERROR; - } - sscanf( r_data, "%x", & data); close(fd); - pthread_mutex_unlock(&mutex1); - return data; -ERROR: - close(fd); - pthread_mutex_unlock(&mutex1); - return -1; - + DNI_BUS_UNLOCK(); + return rv; } /* SWPLD modulize in AG9032v1 platform at bus 6 on address 0x31. Use this function to select address the & write the data. */ -int dni_lock_swpld_write_attribute(int addr, int data) +int dni_swpld_write_attribute(int addr, int data,int bus_lock) { - int fd, len; + int fd,fd1,rv = -1; char address[10] = {0}; sprintf(address, "%02x", addr); - pthread_mutex_lock(&mutex1); + if(bus_lock == BUS_LOCK) + DNI_BUS_LOCK(); /* Create output file descriptor */ - fd = open(SWPLD_ADDR_PATH, O_WRONLY, 0644); - if (fd == -1) + if((fd= open(SWPLD_ADDR_PATH, O_WRONLY, 0644)) >= 0) { - goto ERROR; - } - len = write(fd, address, 2); - if(len <= 0) - { - goto ERROR; + if( write(fd, address, 2) > 0) + { + fsync(fd); + if((fd1 = open(SWPLD_DATA_PATH, O_WRONLY, 0644)) >= 0) + { + sprintf(address, "%02x", data); + if( write (fd1, address, 2) >0 ) + { + rv=0; + fsync(fd1); + } + } + close(fd1); + } } close(fd); - fd = open(SWPLD_DATA_PATH, O_WRONLY, 0644); - if (fd == -1) - { - goto ERROR; - } - sprintf(address, "%02x", data); - len = write (fd, address, 2); - if(len <= 0) - { - goto ERROR; - } - close(fd); - pthread_mutex_unlock(&mutex1); - return 0; - -ERROR: - close(fd); - pthread_mutex_unlock(&mutex1); - return -1; - + if(bus_lock == BUS_LOCK) + DNI_BUS_UNLOCK(); + return rv; } diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.h index ff9f57a4..adcd9ee8 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/platform_lib.h @@ -27,6 +27,9 @@ #define __PLATFORM_LIB_H__ #include "x86_64_delta_ag9032v1_log.h" +#include +#include + /* CPLD numbrt & peripherals */ #define NUM_OF_THERMAL_ON_BOARDS 6 @@ -85,9 +88,10 @@ #define PSU_STATUS_PRESENT (1) #define PSU_NODE_MAX_PATH_LEN (64) #define FAN_SPEED_NORMALLY (5) -#define SPEED_25_PERCENTAGE (25) -#define SPEED_50_PERCENTAGE (50) -#define SPEED_75_PERCENTAGE (75) +#define SPEED_30_PERCENTAGE (30) +#define SPEED_40_PERCENTAGE (40) +#define SPEED_60_PERCENTAGE (60) +#define SPEED_80_PERCENTAGE (80) #define SPEED_100_PERCENTAGE (100) #define FAN_ZERO_TACH (960) @@ -136,6 +140,8 @@ #define SFP_RESET_3 (0x3E) #define SFP_RESET_4 (0x3F) +#define BUS_LOCK 1 +#define BUS_LOCKED 0 int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len); int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len); @@ -160,26 +166,24 @@ typedef struct mux_info_s }mux_info_t; -pthread_mutex_t mutex; -pthread_mutex_t mutex1; int dni_i2c_lock_read(mux_info_t * mux_info, dev_info_t * dev_info); int dni_i2c_lock_write(mux_info_t * mux_info, dev_info_t * dev_info); int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath); int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath); int dni_lock_swpld_read_attribute(int addr); -int dni_lock_swpld_write_attribute(int addr, int addr1); +int dni_swpld_write_attribute(int addr, int data,int bus_lock); int dni_fan_speed_good(); - +void lockinit(); typedef enum { THERMAL_RESERVED = 0, THERMAL_CPU_CORE, - THERMAL_1_ON_CPU_BOARD, - THERMAL_2_ON_FAN_BOARD, - THERMAL_3_ON_SW_BOARD, - THERMAL_4_ON_SW_BOARD, - THERMAL_5_ON_SW_BOARD, + THERMAL_1_ON_CPU_BOARD, //U57 + THERMAL_2_ON_FAN_BOARD, //U334 + THERMAL_3_ON_SW_BOARD, //U38 + THERMAL_4_ON_SW_BOARD, //U40 + THERMAL_5_ON_SW_BOARD, //U240 THERMAL_1_ON_PSU1, THERMAL_1_ON_PSU2, } onlp_thermal_id; @@ -215,5 +219,23 @@ typedef enum LED_REAR_FAN_TRAY_5 }onlp_led_id; +typedef enum +{ + LEVEL_1=0, //worse zone + LEVEL_2, + LEVEL_3, + LEVEL_4, + LEVEL_5, + LEVEL_6 // good and save zone +}thermal_level_t; + +typedef struct thermal_fan_s +{ + int temp_H[6]; //high tmp LV1_LV6 + int temp_L[6]; //low tmp LV1_LV6 + int current_lv; +}thermal_fan_t; + + #endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/psui.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/psui.c index 56fb5eda..fb0843e5 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/psui.c @@ -65,6 +65,7 @@ dni_psu_pmbus_info_get(int id, char *node, int *value) int onlp_psui_init(void) { + lockinit(); return ONLP_STATUS_OK; } @@ -215,4 +216,4 @@ int onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) { return ONLP_STATUS_E_UNSUPPORTED; -} \ No newline at end of file +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sfpi.c index 7eee58d7..b607a947 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sfpi.c @@ -38,7 +38,7 @@ static inline int ag9032v1_sfp_get_lp_mode_reg(int port) { uint8_t reg_offset = 0x00; if (port < 8) /* port 0-7 */ - reg_offset = SFP_LP_MODE_1; + reg_offset = SFP_LP_MODE_1; else if (port > 7 && port < 16) /* port 8-15 */ reg_offset = SFP_LP_MODE_2; else if (port > 15 && port < 24) /* port 16-23 */ @@ -52,7 +52,7 @@ static inline int ag9032v1_sfp_get_lp_mode_reg(int port) { static inline int ag9032v1_sfp_get_reset_reg(int port) { uint8_t reg_offset = 0x00; if (port < 8) /* port 0-7 */ - reg_offset = SFP_RESET_1; + reg_offset = SFP_RESET_1; else if (port > 7 && port < 16) /* port 8-15 */ reg_offset = SFP_RESET_2; else if (port > 15 && port < 24) /* port 16-23 */ @@ -66,7 +66,7 @@ static inline int ag9032v1_sfp_get_reset_reg(int port) { static inline int ag9032v1_sfp_get_respond_reg(int port) { uint8_t reg_offset = 0x00; if (port < 8) /* port 0-7 */ - reg_offset = SFP_RESPOND_1; + reg_offset = SFP_RESPOND_1; else if (port > 7 && port < 16) /* port 8-15 */ reg_offset = SFP_RESPOND_2; else if (port > 15 && port < 24) /* port 16-23 */ @@ -102,6 +102,7 @@ int onlp_sfpi_init(void) { /* Called at initialization time */ + lockinit(); return ONLP_STATUS_OK; } @@ -124,7 +125,7 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) int onlp_sfpi_is_present(int port) { - char port_data[2] = {'\0'}; + char port_data[3] = {'\0'}; uint8_t present = 0; uint8_t present_bit = 0; @@ -143,9 +144,8 @@ onlp_sfpi_is_present(int port) present = 1; } else if (present_bit == 1) { present = 0; - AIM_LOG_ERROR("Unble to present status from port(%d)\r\n", port); } else { - /* Port range over 0-31, return -1 */ + /* Port range over 0-31, return -1 */ AIM_LOG_ERROR("Error to present status from port(%d)\r\n", port); present = -1; } @@ -162,7 +162,7 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) uint8_t bytes[4]; int count = 0; - /* Read presence bitmap from SWPLD QSFP28 Presence Register + /* Read presence bitmap from SWPLD QSFP28 Presence Register * if only port 0 is present, return 7F FF FF FF * if only port 0 and 1 present, return 3F FF FF FF */ @@ -170,11 +170,11 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) sizeof(present_all_data), 0) < 0) { return -1; } - + /* String split */ r_byte = strtok(present_all_data, " "); while (r_byte != NULL) { - r_array[count++] = r_byte; + r_array[count++] = r_byte; r_byte = strtok(NULL, " "); } @@ -217,7 +217,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { uint8_t sfp_response_reg = 0x00; uint8_t backup_response_data = 0x00; - char port_data[2] = {'\0'}; + char port_data[3] = {'\0'}; /* Get port respond register offset */ sfp_response_reg = ag9032v1_sfp_get_respond_reg(port); @@ -225,7 +225,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) /* Select qsfp port to response mode */ backup_response_data = dni_lock_swpld_read_attribute(sfp_response_reg); backup_response_data &= ~(1 << (7 - (port % 8))); - dni_lock_swpld_write_attribute(sfp_response_reg, backup_response_data); + dni_swpld_write_attribute(sfp_response_reg, backup_response_data,BUS_LOCK); /* Select QSFP port */ sprintf(port_data, "%d", port + 1); @@ -234,7 +234,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) memset(data, 0, 256); /* Read qsfp eeprom information into data[] */ - if (dni_i2c_read_attribute_binary(SFP_EEPROM_PATH, + if (dni_i2c_read_attribute_binary(SFP_EEPROM_PATH, (char *)data, 256, 256) != 0) { AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; @@ -272,7 +272,7 @@ int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) /* Select qsfp port to response mode */ backup_response_data = dni_lock_swpld_read_attribute(sfp_response_reg); backup_response_data &= ~(1 << (7 - (port % 8))); - dni_lock_swpld_write_attribute(sfp_response_reg, backup_response_data); + dni_swpld_write_attribute(sfp_response_reg, backup_response_data,BUS_LOCK); channel = port_sel_channel; @@ -311,7 +311,7 @@ int onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) /* Select qsfp port to response mode */ backup_response_data = dni_lock_swpld_read_attribute(sfp_response_reg); backup_response_data &= ~(1 << (7 - (port % 8))); - dni_lock_swpld_write_attribute(sfp_response_reg, backup_response_data); + dni_swpld_write_attribute(sfp_response_reg, backup_response_data,BUS_LOCK); channel = port_sel_channel; @@ -352,7 +352,7 @@ int onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) /* Select qsfp port to response mode */ backup_response_data = dni_lock_swpld_read_attribute(sfp_response_reg); backup_response_data &= ~(1 << (7 - (port % 8))); - dni_lock_swpld_write_attribute(sfp_response_reg, backup_response_data); + dni_swpld_write_attribute(sfp_response_reg, backup_response_data,BUS_LOCK); channel = port_sel_channel; @@ -392,7 +392,7 @@ int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value /* Select qsfp port to response mode */ backup_response_data = dni_lock_swpld_read_attribute(sfp_response_reg); backup_response_data &= ~(1 << (7 - (port % 8))); - dni_lock_swpld_write_attribute(sfp_response_reg, backup_response_data); + dni_swpld_write_attribute(sfp_response_reg, backup_response_data,BUS_LOCK); channel = port_sel_channel; @@ -413,7 +413,7 @@ int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value int onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) { - char port_data[2] = {'\0'}; + char port_data[3] = {'\0'}; /* Select QSFP port */ sprintf(port_data, "%d", port + 1); @@ -424,13 +424,13 @@ onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) *rv = 1; break; case ONLP_SFP_CONTROL_RX_LOS: - *rv = 0; + *rv = 0; break; case ONLP_SFP_CONTROL_TX_DISABLE: *rv = 0; break; case ONLP_SFP_CONTROL_LP_MODE: - *rv = 1; + *rv = 1; break; default: return ONLP_STATUS_OK; @@ -443,7 +443,7 @@ int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { uint8_t value_t = 0; - char port_data[2] = {'\0'}; + char port_data[3] = {'\0'}; /* Select QSFP port */ sprintf(port_data, "%d", port + 1); @@ -478,7 +478,7 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { uint8_t value_t = 0; - char port_data[2] = {'\0'}; + char port_data[3] = {'\0'}; /* Select QSFP port */ sprintf(port_data, "%d", port + 1); @@ -492,10 +492,10 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) * return 1 = The module is NOT in Reset */ if (*value == 0) - *value = 1; + *value = 1; else if (*value == 1) - *value = 0; - + *value = 0; + value_t = ONLP_STATUS_OK; break; case ONLP_SFP_CONTROL_RX_LOS: diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sysi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sysi.c index 9d5d2d7d..e0415c17 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/sysi.c @@ -38,6 +38,17 @@ #include "x86_64_delta_ag9032v1_log.h" #include "platform_lib.h" +// U57 , U334 ,U38,U40 ,U240 +static thermal_fan_t thermal_level[5]={ + { {200,64,60,56,52,45},{65,58,54,50,46,0},9}, + { {200,64,60,56,52,45},{65,58,54,50,46,0},9}, + { {200,79,75,71,67,63},{82,73,69,65,61,0},9}, + { {200,69,65,61,57,53},{71,63,59,55,51,0},9}, + { {200,54,49,44,39,39},{55,46,41,36,0,0},9} +}; + + + const char* onlp_sysi_platform_get(void) { @@ -47,6 +58,7 @@ onlp_sysi_platform_get(void) int onlp_sysi_init(void) { + lockinit(); return ONLP_STATUS_OK; } @@ -120,15 +132,16 @@ onlp_sysi_oids_get(onlp_oid_t* table, int max) { *e++ = ONLP_PSU_ID_CREATE(i); } - return 0; } int onlp_sysi_platform_manage_fans(void) { - int i = 0; + int i=0,j=0; int highest_temp = 0; + int current_temp = 0; + int highest_lv = LEVEL_6; onlp_thermal_info_t thermal[8]; int new_duty_percentage; /* Get current temperature @@ -148,35 +161,51 @@ onlp_sysi_platform_manage_fans(void) { onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), new_duty_percentage); } - AIM_LOG_ERROR("Unable to read thermal status"); return ONLP_STATUS_E_INTERNAL; } - for (i = 0; i < 8; i++) - { - if (thermal[i].mcelsius > highest_temp) - { - highest_temp = thermal[i].mcelsius; + + for(i=0;i<5;i++){ + current_temp=thermal[i+1].mcelsius/1000; + if(thermal_level[i].current_lv == 9){ // initialize the temp level + thermal_level[i].current_lv = LEVEL_4; } + j=thermal_level[i].current_lv; + if(current_temp < thermal_level[i].temp_L[j] && thermal_level[i].current_lv < LEVEL_6 ){ // goto lower level + thermal_level[i].current_lv++; + } + else if(current_temp > thermal_level[i].temp_H[j] && thermal_level[i].current_lv > LEVEL_1 ){ // goto upper level + thermal_level[i].current_lv--; + } + else{ // keep in curent level + // keep in the curent level and + } + if(highest_lv > thermal_level[i].current_lv) + highest_lv = thermal_level[i].current_lv; //update the highest level } + + switch (highest_lv) + { + case LEVEL_1: + case LEVEL_2: + new_duty_percentage = SPEED_100_PERCENTAGE; + break; + case LEVEL_3: + new_duty_percentage = SPEED_80_PERCENTAGE; + break; + case LEVEL_4: + new_duty_percentage = SPEED_60_PERCENTAGE; + break; + case LEVEL_5: + new_duty_percentage = SPEED_40_PERCENTAGE; + break; + case LEVEL_6: + new_duty_percentage = SPEED_30_PERCENTAGE; + break; + default: + new_duty_percentage = SPEED_100_PERCENTAGE; + break; - highest_temp = highest_temp/1000; - - if (highest_temp > 0 && highest_temp <= 30) - { - new_duty_percentage = SPEED_25_PERCENTAGE; - } - else if (highest_temp > 30 && highest_temp <= 40) - { - new_duty_percentage = SPEED_50_PERCENTAGE; - } - else if (highest_temp > 40 && highest_temp <= 50) - { - new_duty_percentage = SPEED_75_PERCENTAGE; - } - else - { - new_duty_percentage = SPEED_100_PERCENTAGE; } /* Set speed on fan 1-10*/ for(i = 1 ; i <= 10; i++) @@ -188,7 +217,7 @@ onlp_sysi_platform_manage_fans(void) */ if(highest_temp >= 0 && highest_temp <= 55) { - new_duty_percentage = SPEED_50_PERCENTAGE; + new_duty_percentage = SPEED_60_PERCENTAGE; } else if(highest_temp > 55) { @@ -210,26 +239,27 @@ onlp_sysi_platform_manage_leds(void) { /* Set front lights: fan, power supply 1, 2 */ - int fantray_present = -1, rpm, rpm1,i=0,count=0, state; + int rpm, rpm1,i=0,count=0, state; + uint8_t present_bit = 0x00; uint8_t power_state; mux_info_t mux_info; + dev_info_t dev_info; + mux_info.offset = SWPLD_PSU_FAN_I2C_MUX_REG; + mux_info.channel = 0x07; mux_info.flags = DEFAULT_FLAG; - dev_info_t dev_info; dev_info.bus = I2C_BUS_3; + dev_info.addr = FAN_IO_CTL; dev_info.offset = 0x00; dev_info.flags = DEFAULT_FLAG; + dev_info.size = 1; - + present_bit = dni_i2c_lock_read(&mux_info, &dev_info); /* Fan tray 1 */ - mux_info.channel = 0x00; - dev_info.addr = FAN_TRAY_1; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - rpm = dni_i2c_lock_read_attribute(NULL, FAN5_FRONT); rpm1 = dni_i2c_lock_read_attribute(NULL, FAN5_REAR); - if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + if((present_bit & (1 << 4)) == 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) {/* Green light */ onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_GREEN); @@ -239,14 +269,11 @@ onlp_sysi_platform_manage_leds(void) onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_RED); } - /* Fan tray 2 */ - mux_info.channel = 0x01; - dev_info.addr = FAN_TRAY_2; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - + + /* Fan tray 2 */ rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); - if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + if((present_bit & (1 << 3)) == 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) {/* Green light */ onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_GREEN); @@ -256,14 +283,11 @@ onlp_sysi_platform_manage_leds(void) onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_RED); } - /* Fan tray 3 */ - mux_info.channel = 0x02; - dev_info.addr = FAN_TRAY_3; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - + + /* Fan tray 3 */ rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); - if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + if((present_bit & (1 << 2)) == 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) {/* Green light */ onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_GREEN); @@ -273,14 +297,11 @@ onlp_sysi_platform_manage_leds(void) onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_RED); } - /* Fan tray 4 */ - mux_info.channel = 0x03; - dev_info.addr = FAN_TRAY_4; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - + + /* Fan tray 4 */ rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); - if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + if((present_bit & (1 << 1)) == 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) {/* Green light */ onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_GREEN); @@ -290,14 +311,11 @@ onlp_sysi_platform_manage_leds(void) onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_RED); } - /* Fan tray 5 */ - mux_info.channel = 0x04; - dev_info.addr = FAN_TRAY_5; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - + + /* Fan tray 5 */ rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); - if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + if((present_bit & 1) == 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) {/* Green light */ onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_5),ONLP_LED_MODE_GREEN); @@ -311,10 +329,12 @@ onlp_sysi_platform_manage_leds(void) /* FRONT FAN LED & SYS */ for(i = 0; i < 5; i++) { - mux_info.channel = i; - dev_info.addr = FAN_TRAY_1 + i; - fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); - if( fantray_present >= 0) + //mux_info.channel = i; + //dev_info.addr = FAN_TRAY_1 + i; + //fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + // if( fantray_present >= 0) + present_bit = dni_i2c_lock_read(&mux_info, &dev_info); + if( (present_bit & (1 << i)) == 0) count++; } /* Set front light of FAN */ @@ -336,7 +356,7 @@ onlp_sysi_platform_manage_leds(void) state = dni_i2c_lock_read(&mux_info, &dev_info); /* Check the state of PSU 1, "state = 1, PSU exists' */ - if(state == 1) + if(state > 0) { power_state = dni_lock_swpld_read_attribute(CTL_REG); /* Set the light of PSU */ @@ -360,7 +380,7 @@ onlp_sysi_platform_manage_leds(void) state = dni_i2c_lock_read(&mux_info, &dev_info); /* Check the state of PSU 2, "state = 1, PSU exists' */ - if(state == 1) + if(state > 0) { power_state = dni_lock_swpld_read_attribute(CTL_REG); /* Set the light of PSU */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/thermali.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/thermali.c index 0e898e72..3d99a974 100644 --- a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v1/onlp/builds/src/module/src/thermali.c @@ -109,6 +109,7 @@ static onlp_thermal_info_t linfo[] = { int onlp_thermali_init(void) { + lockinit(); return ONLP_STATUS_OK; } diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/PKG.yml new file mode 100644 index 00000000..2fb164bf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=delta BASENAME=x86-64-delta-ag9032v2a ARCH=amd64 KERNELS="onl-kernel-4.9-lts-x86-64-all:amd64" diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/Makefile new file mode 100644 index 00000000..2130d15f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.9-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := delta +BASENAME := x86-64-delta-ag9032v2a +ARCH := x86_64 +include $(ONL)/make/kmodule.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/delta_ag9032v2a_platform.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/delta_ag9032v2a_platform.c new file mode 100644 index 00000000..0deb0a9f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/delta_ag9032v2a_platform.c @@ -0,0 +1,2361 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPUPLD_ADDR 0x31 +#define SWPLD1_ADDR 0x6a +#define SWPLD2_ADDR 0x73 +#define SWPLD3_ADDR 0x75 + +#define MUX_VAL_SWPLD 0xFF +#define MUX_VAL_IDEEPROM 0xFC +#define MUX_VAL_PCA9548 0xFD + +#define MUX_VAL_FAN5_EEPROM 0x00 +#define MUX_VAL_FAN4_EEPROM 0x01 +#define MUX_VAL_FAN3_EEPROM 0x02 +#define MUX_VAL_FAN2_EEPROM 0x03 +#define MUX_VAL_FAN1_EEPROM 0x04 +#define MUX_VAL_FAN_CTL 0x05 +#define MUX_VAL_FAN_TMP75 0x06 +#define MUX_VAL_FAN_IO_CTL 0x07 + +#define SWPLD_MUX_DEF 0x00 +#define CPLD_MUX_DEF 0xfd +#define DEF_DEV_NUM 1 + +#define BUS0_DEV_NUM 3 +#define BUS0_BASE_NUM 1 +#define BUS0_MUX_REG 0x14 + +#define BUS1_DEV_NUM 33 +#define BUS1_BASE_NUM 31 +#define BUS1_MUX_REG 0x1f + +#define BUS6_DEV_NUM 8 +#define BUS6_BASE_NUM 21 +#define BUS6_MUX_REG 0x1e + +#define QSFP_PRESENCE_1 0x12 +#define QSFP_PRESENCE_2 0x13 +#define QSFP_PRESENCE_3 0x14 +#define QSFP_PRESENCE_4 0x15 +#define SFP_REG 0x02 + +#define QSFP_LPMODE_1 0x0E +#define QSFP_LPMODE_2 0x0F +#define QSFP_LPMODE_3 0x10 +#define QSFP_LPMODE_4 0x11 + +#define QSFP_RESET_1 0x16 +#define QSFP_RESET_2 0x17 +#define QSFP_RESET_3 0x18 +#define QSFP_RESET_4 0x19 + +#define QSFP_SELECT_REG 0x1F +#define DEFAULT_DISABLE 0x00 +#define QSFP_DEFAULT_DISABLE 0xC0 + +/* Check cpld read results */ +#define VALIDATED_READ(_buf, _rv, _read, _invert) \ + do { \ + _rv = _read; \ + if (_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if (_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) \ + +struct mutex dni_lock; +void device_release(struct device *dev) +{ + return; +} + +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; +} + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, +}; + +#define ag9032v2a_i2c_device_num(NUM){ \ + .name = "delta-ag9032v2a-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9032v2a_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[200]; +}; + +enum cpld_type { + system_cpld, +}; + +enum swpld1_type { + swpld1, +}; + +enum swpld2_type { + swpld2, +}; + +enum swpld3_type { + swpld3, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum cpld_attributes { +//CPLDs address and value + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD1_REG_ADDR, + SWPLD1_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, + //CPLD + CPLD_VER, + CPU_BOARD_VER, + MB_BOARD_VER, + CPU_PWR_OK, + CPLD_PLATFORM_RST, + CPLD_RST, + CPLD_VR_HOT, + CPLD_PWR_RST, + MB_PWR_ENABLE, + MB_PWR_PDD, + MB_RST_DONE, + MB_RST, + SPI_CHIP_SEL, + SMB_CPU_MUX_SEL, + PSU_FAN_INT, + SYS_LED, + SYS_LED_BGR, +//SWPLD1 + PLATFORM_TYPE, + SWPLD1_MB_RST, + AST2520_RST, + BMC56870_RST, + PCIE_RST, +}; + +enum ag9032v2a_sfp_sysfs_attributes +{ + SFP_SELECT_PORT, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_RESET, +}; + +static struct cpld_attribute_data attribute_data[] = { +//CPLDs address and value + [CPLD_REG_ADDR] = { + }, + [CPLD_REG_VALUE] = { + }, + [SWPLD1_REG_ADDR] = { + }, + [SWPLD1_REG_VALUE] = { + }, + [SWPLD2_REG_ADDR] = { + }, + [SWPLD2_REG_VALUE] = { + }, + [SWPLD3_REG_ADDR] = { + }, +//CPLD + [CPU_BOARD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0x0f, + .note = "“0x00â€: EVT1\n“0x01â€: EVT2\n“0x02â€: EVT3\n“0x03â€: EVT4\n“0x10â€: DVT1\n“0x11â€: DVT2\n“0x20â€: PVT" + }, + [CPLD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x03, .mask = 0xff, + .note = "" + }, + [MB_BOARD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x04, .mask = 0x0f, + .note = "“0000â€: proto-A\n“0001â€: proto-B\n“0010â€: P/R" + }, + [CPU_PWR_OK] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x06, .mask = 1 << 2, + .note = "“1†= System Power is OK \n“0†= System Power is not OK" + }, + [CPLD_PLATFORM_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x09, .mask = 1 << 4, + .note = "“1†= Platform Reset \n“0†= Platform Not Reset" + }, + [CPLD_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x09, .mask = 1 << 1, + .note = "“1†= CPU Not Reset \n“0†= CPU Reset." + }, + [CPLD_VR_HOT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 3, + .note = "“1†= Not over temperature\n“0†= Over temperature." + }, + [CPLD_PWR_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 0, + .note = "“0†= Reset\n“1†= Normal operation" + }, + [MB_PWR_ENABLE] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 3, + .note = "“0†= Disable\n“1†= Enable." + }, + [MB_PWR_PDD] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 2, + .note = "“0†= Power rail is failed\n“1†=Power rail is good" + }, + [MB_RST_DONE] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 1, + .note = "“0†= Reset\n“1†= Normal operation" + }, + [MB_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 0, + .note = "“0†= Reset\n“1†= Normal operation" + }, + [SPI_CHIP_SEL] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x13, .mask = 1 << 1, + .note = "“0†= boot from chip2\n“1†= boot from chip1." + }, + [SMB_CPU_MUX_SEL] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x14, .mask = 0x03 , + .note = "“0x0†= to CPU Board ONIE EEPROM\n“0x1†= to MB MUX(0x70)\n“0x2†= to MB SWPLD (option)\n“0x3†= to MB FRONT PANEL PORT" + }, + [PSU_FAN_INT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 1, + .note = "“0†= Interrupt occurs\n“1†= Interrupt doesn’t occur" + }, + [SYS_LED] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x21, .mask = 0x0c, + .note = "‘0x0’: Off \n‘0x1’: Solid Green – Normal operation\n‘0x2’: Blinking Green – Booting Progress\n‘0x3’: Solid Red – System Fail" + }, + [SYS_LED_BGR] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x22, .mask = 0xe0, + .note = "First bit: blue led status\nSecond bit:green led status\nThird bit: red led status" + }, +//SWPLD1 + [PLATFORM_TYPE] = { + .bus = BUS1, .addr = SWPLD1_ADDR, + .reg = 0x01, .mask = 0x0f, + .note = "“0000â€: AG9032V2A (DENVERTON)\n“0001â€: AG9032V2A (BROADWELL-DE)\n“0010~1111â€: RSVP" + }, + [SWPLD1_MB_RST] = { + .bus = BUS1, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 0x80, + .note = "“1†= Normal operation\n“0†= Reset" + }, + [AST2520_RST] = { + .bus = BUS1, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 0x4, + .note = "“1†= Normal operation\n“0†= Reset" + }, + [BMC56870_RST] = { + .bus = BUS1, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 0x2, + .note = "“1†= Normal operation\n“0†= Reset" + }, + [PCIE_RST] = { + .bus = BUS1, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 0x10, + .note = "“1†= Normal operation\n“0†= Reset" + }, +}; +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +struct i2c_client * i2c_client_9548; + +static struct cpld_platform_data ag9032v2a_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = CPUPLD_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld1_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +// pca9548 - add 8 bus +static struct pca954x_platform_mode pca954x_mode[] = +{ + { + .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, + }, + { + .adap_id = 10, + .deselect_on_exit = 1, + }, + { + .adap_id = 11, + .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", 0x71), + .platform_data = &pca954x_data, + }, +}; + +/*---------------- IPMI - start ------------- */ +static LIST_HEAD(cpld_client_list); + +struct cpld_client_node +{ + struct i2c_client *client; + struct list_head list; +}; + + int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + mutex_lock(&dni_lock); + list_for_each(list_node, &cpld_client_list){ + cpld_node = list_entry(list_node, struct cpld_client_node, list); + if ((cpld_node->client->adapter->nr == bus) && (cpld_node->client->addr == cpld_addr) ){ + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + mutex_unlock(&dni_lock); + return ret; +} +EXPORT_SYMBOL(i2c_cpld_read); + int i2c_cpld_write(int bus, 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(&dni_lock); + list_for_each(list_node, &cpld_client_list){ + cpld_node = list_entry(list_node, struct cpld_client_node, list); + if ((cpld_node->client->adapter->nr == bus) && (cpld_node->client->addr == cpld_addr) ){ + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + mutex_unlock(&dni_lock); + return ret; +} +EXPORT_SYMBOL(i2c_cpld_write); +/*---------------- IPMI - stop ------------- */ + +/*---------------- I2C device - start ------------- */ +static struct i2c_device_platform_data ag9032v2a_i2c_device_platform_data[] = { + { + // id eeprom + .parent = 2, + .info = { I2C_BOARD_INFO("eeprom", 0x53) }, + .client = NULL, + }, + { + // PSU 1 + .parent = 4, + .info = { I2C_BOARD_INFO("dni_ag9032v2a_psu", 0x58) }, + .client = NULL, + }, + { + // PSU 2 + .parent = 5, + .info = { I2C_BOARD_INFO("dni_ag9032v2a_psu", 0x58) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + // fan control + .parent = 26, + .info = { I2C_BOARD_INFO("emc2305", 0x2c) }, + .client = NULL, + }, + { + // fan control + .parent = 26, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + // tmp75 + .parent = 27, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + // qsfp 1 (0x50) + .parent = 31, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 2 (0x50) + .parent = 32, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 3 (0x50) + .parent = 33, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 4 (0x50) + .parent = 34, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 5 (0x50) + .parent = 35, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 6 (0x50) + .parent = 36, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 7 (0x50) + .parent = 37, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 8 (0x50) + .parent = 38, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 9 (0x50) + .parent = 39, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 10 (0x50) + .parent = 40, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 11 (0x50) + .parent = 41, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 12 (0x50) + .parent = 42, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 13 (0x50) + .parent = 43, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 14 (0x50) + .parent = 44, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 15 (0x50) + .parent = 45, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 16 (0x50) + .parent = 46, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 17 (0x50) + .parent = 47, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 18 (0x50) + .parent = 48, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 19 (0x50) + .parent = 49, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 20 (0x50) + .parent = 50, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 21 (0x50) + .parent = 51, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 22 (0x50) + .parent = 52, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 23 (0x50) + .parent = 53, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 24 (0x50) + .parent = 54, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 25 (0x50) + .parent = 55, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 26 (0x50) + .parent = 56, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 27 (0x50) + .parent = 57, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 28 (0x50) + .parent = 58, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 29 (0x50) + .parent = 59, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 30 (0x50) + .parent = 60, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 31 (0x50) + .parent = 61, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 32 (0x50) + .parent = 62, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 1 (0x50) + .parent = 63, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct platform_device ag9032v2a_i2c_device[] = { + ag9032v2a_i2c_device_num(0), + ag9032v2a_i2c_device_num(1), + ag9032v2a_i2c_device_num(2), + ag9032v2a_i2c_device_num(3), + ag9032v2a_i2c_device_num(4), + ag9032v2a_i2c_device_num(5), + ag9032v2a_i2c_device_num(6), + ag9032v2a_i2c_device_num(7), + ag9032v2a_i2c_device_num(8), + ag9032v2a_i2c_device_num(9), + ag9032v2a_i2c_device_num(10), + ag9032v2a_i2c_device_num(11), + ag9032v2a_i2c_device_num(12), + ag9032v2a_i2c_device_num(13), + ag9032v2a_i2c_device_num(14), + ag9032v2a_i2c_device_num(15), + ag9032v2a_i2c_device_num(16), + ag9032v2a_i2c_device_num(17), + ag9032v2a_i2c_device_num(18), + ag9032v2a_i2c_device_num(19), + ag9032v2a_i2c_device_num(20), + ag9032v2a_i2c_device_num(21), + ag9032v2a_i2c_device_num(22), + ag9032v2a_i2c_device_num(23), + ag9032v2a_i2c_device_num(24), + ag9032v2a_i2c_device_num(25), + ag9032v2a_i2c_device_num(26), + ag9032v2a_i2c_device_num(27), + ag9032v2a_i2c_device_num(28), + ag9032v2a_i2c_device_num(29), + ag9032v2a_i2c_device_num(30), + ag9032v2a_i2c_device_num(31), + ag9032v2a_i2c_device_num(32), + ag9032v2a_i2c_device_num(33), + ag9032v2a_i2c_device_num(34), + ag9032v2a_i2c_device_num(35), + ag9032v2a_i2c_device_num(36), + ag9032v2a_i2c_device_num(37), + ag9032v2a_i2c_device_num(38), + ag9032v2a_i2c_device_num(39), + ag9032v2a_i2c_device_num(40), + ag9032v2a_i2c_device_num(41), + ag9032v2a_i2c_device_num(42), +}; + +/*---------------- 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-ag9032v2a-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- SFP attribute read/write - start -------- */ +long sfp_port_data = 0; +static struct kobject *kobj_swpld1; +static struct kobject *kobj_swpld2; +static struct kobject *kobj_swpld3; + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf){ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld1); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld2); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + + long port_t = 0; + u8 reg_t = 0x00; + int values[7] = {'\0'}; + int bit_t = 0x00; + + mutex_lock(&dni_lock); + switch (attr->index) { + case SFP_IS_PRESENT: + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* QSFP Port 1-8 */ + reg_t = QSFP_PRESENCE_1; + } else if (port_t > 8 && port_t < 17) { /* QSFP Port 9-16 */ + reg_t = QSFP_PRESENCE_2; + } else if (port_t > 16 && port_t < 25) { /* QSFP Port 17-24 */ + reg_t = QSFP_PRESENCE_3; + } else if (port_t > 24 && port_t < 33) { /* QSFP Port 25-32 */ + reg_t = QSFP_PRESENCE_4; + } else if (port_t > 32 && port_t < 34) { /* SFP Port 1 */ + reg_t = SFP_REG; + } else { + values[0] = 1; /* return 1, module NOT present */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if(port_t > 32 && port_t < 34){ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata2[swpld2].client, reg_t), 0); + values[0] = values[0] & 0x80; + values[0] = values[0] / 0x80; + } + else{ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + /* SWPLD QSFP module respond */ + port_t = 8 - (port_t % 8); + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + } + + /* sfp_is_present value + * return 0 is module present + * return 1 is module NOT present*/ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_IS_PRESENT_ALL: + /* + * Report the SFP ALL PRESENCE status + * This data information form CPLD.*/ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], + i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_1), 0); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], + i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_2), 0); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], + i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_3), 0); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], + i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_4), 0); + /* SFP_PRESENT Ports 1 */ + VALIDATED_READ(buf, values[4], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_REG), 0); + values[4] = (values[4] & 0x80); + + /* sfp_is_present_all value + * return 0 is module present + * return 1 is module NOT present + */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%02X %02X %02X %02X %02X\n",values[0], values[1], values[2],values[3], values[4]); + case SFP_LP_MODE: + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* QSFP Port 1-8 */ + reg_t = QSFP_LPMODE_1; + } else if (port_t > 8 && port_t < 17) { /* QSFP Port 9-16 */ + reg_t = QSFP_LPMODE_2; + } else if (port_t > 16 && port_t < 25) { /* QSFP Port 17-24 */ + reg_t = QSFP_LPMODE_3; + } else if (port_t > 24 && port_t < 33) { /* QSFP Port 25-32 */ + reg_t = QSFP_LPMODE_4; + } else { + values[0] = 0; /* return 0, module is NOT in LP mode */ + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 0 && port_t < 33) { + /* QSFP Port 1-32 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + } else { + /* In ag9032v2a only QSFP support control LP MODE */ + values[0] = 0; + return sprintf(buf, "%d\n", values[0]); + } + + bit_t = 8 - (port_t % 8); + bit_t = 1 << (bit_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_lp_mode value + * return 0 is module NOT in LP mode + * return 1 is module in LP mode + */ + + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_RESET: + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* QSFP Port 1-8 */ + reg_t = QSFP_RESET_1; + } else if (port_t > 8 && port_t < 17) { /* QSFP Port 9-16 */ + reg_t = QSFP_RESET_2; + } else if (port_t > 16 && port_t < 25) { /* QSFP Port 17-24 */ + reg_t = QSFP_RESET_3; + } else if (port_t > 24 && port_t < 33) { /* QSFP Port 25-32 */ + reg_t = QSFP_RESET_4; + } else { + values[0] = 1; /* return 1, module NOT in reset mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 0 && port_t < 33) { + /* QSFP Port 1-32 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + } else { + /* In ag9032v2a only QSFP support control LP MODE */ + values[0] = 0; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + /* SWPLD QSFP module respond */ + bit_t = 8 - (port_t % 8); + bit_t = 1 << (bit_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_reset value + * return 0 is module Reset + * return 1 is module Normal*/ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } +} + +static ssize_t get_port_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + + mutex_lock(&dni_lock); + if (sfp_port_data == DEFAULT_DISABLE) + { + /* Disable QSFP and SFP channel */ + if (i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_SELECT_REG, (u8)QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + } + mutex_unlock(&dni_lock); + + return sprintf(buf, "%ld\n", sfp_port_data); + +} + +static ssize_t set_port_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + + error = kstrtol(buf, 10, &data); + if(error){ + return error; + } + mutex_lock(&dni_lock); + /* Disable QSFP channel */ + if (i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_SELECT_REG, (u8)QSFP_DEFAULT_DISABLE) < 0) { + mutex_unlock(&dni_lock); + return -EIO; + } + + sfp_port_data = data; + mutex_unlock(&dni_lock); + return count; +} + +static ssize_t set_lpmode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + mutex_lock(&dni_lock); + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* QSFP Port 1-8 */ + reg_t = QSFP_LPMODE_1; + } else if (port_t > 8 && port_t < 17) { /* QSFP Port 9-16 */ + reg_t = QSFP_LPMODE_2; + } else if (port_t > 16 && port_t < 25) { /* QSFP Port 17-24 */ + reg_t = QSFP_LPMODE_3; + } else if (port_t > 24 && port_t < 33) { /* QSFP Port 25-32 */ + reg_t = QSFP_LPMODE_4; + } else { + values = 0; /* return 1, module NOT in low power mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values); + } + + values = i2c_smbus_read_byte_data(pdata[swpld1].client, reg_t); + if (values < 0) + { + return -EIO; + + mutex_unlock(&dni_lock); + } + /* Indicate the module is in LP mode or not + * 0 = Disable + * 1 = Enable + */ + if (data == 0) + { + bit_t = 8 - (port_t % 8); + bit_t = ~(1 << (bit_t % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = 8 - (port_t % 8); + bit_t = (1 << (bit_t % 8)); + values = values | bit_t; + } + else + { + mutex_unlock(&dni_lock); + return -EINVAL; + } + if (i2c_smbus_write_byte_data(pdata[swpld1].client, reg_t, (u8)values) < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + + mutex_unlock(&dni_lock); + return count; +} + +static ssize_t set_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + mutex_lock(&dni_lock); + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* QSFP Port 1-8 */ + reg_t = QSFP_RESET_1; + } else if (port_t > 8 && port_t < 17) { /* QSFP Port 9-16 */ + reg_t = QSFP_RESET_2; + } else if (port_t > 16 && port_t < 25) { /* QSFP Port 17-24 */ + reg_t = QSFP_RESET_3; + } else if (port_t > 24 && port_t < 33) { /* QSFP Port 25-32 */ + reg_t = QSFP_RESET_4; + } else { + values = 0; /* return 1, module NOT in low power mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values); + } + + values = i2c_smbus_read_byte_data(pdata[swpld1].client, reg_t); + if (values < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + /* Indicate the module is in LP mode or not + * 0 = Disable + * 1 = Enable + */ + if (data == 0) + { + bit_t = 8 - (port_t % 8); + bit_t = ~(1 << (bit_t % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = 8 - (port_t % 8); + bit_t = (1 << (bit_t % 8)); + values = values | bit_t; + } + else + { + mutex_unlock(&dni_lock); + return -EINVAL; + } + if (i2c_smbus_write_byte_data(pdata[swpld1].client, reg_t, (u8)values) < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + + mutex_unlock(&dni_lock); + return count; +} +/*---------------- SFP attribute read/write - end -------- */ + +/*---------------- CPLD - start ------------- */ +unsigned char cpupld_reg_addr; +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; +/* CPLD -- device */ +static struct platform_device cpld_device = { + .name = "delta-ag9032v2a-cpld", + .id = 0, + .dev = { + .platform_data = ag9032v2a_cpld_platform_data, + .release = device_release + }, + +}; + +static struct platform_device swpld1_device = { + .name = "delta-ag9032v2a-swpld1", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld1_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld2_device = { + .name = "delta-ag9032v2a-swpld2", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld2_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld3_device = { + .name = "delta-ag9032v2a-swpld3", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld3_platform_data, + .release = device_release + }, +}; + +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; + + mutex_lock(&dni_lock); + switch (attr->index) { + case CPLD_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case SWPLD1_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld1_reg_addr); + case SWPLD2_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case CPLD_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, cpupld_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD1_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld1].client, swpld1_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD2_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld2].client, swpld2_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD3_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld3].client, swpld3_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case CPLD_VER: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = (value & mask); + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", value); + case CPU_BOARD_VER ... SYS_LED_BGR: + 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; + case PLATFORM_TYPE ... PCIE_RST: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[swpld1].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = (value & mask); + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xff: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0f: + case 0x03: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%01x%s", value, note); + case 0x0c: + mutex_unlock(&dni_lock); + value = value >> 2; + return sprintf(buf, "0x%01x%s", value, note); + case 0xf0: + mutex_unlock(&dni_lock); + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + case 0xe0: + mutex_unlock(&dni_lock); + value = value >> 5; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + mutex_unlock(&dni_lock); + 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; + } + + mutex_lock(&dni_lock); + switch (attr->index) { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_ADDR: + swpld1_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld1].client, swpld1_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld2].client, swpld2_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld3].client, swpld3_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case CPU_BOARD_VER ... SYS_LED_BGR: + 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; + case PLATFORM_TYPE ... PCIE_RST: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[swpld1].client, reg); + mask_out = value & ~(mask); + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0x03: + case 0x0C: + case 0x0F: + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xE0: + set_data = set_data << 5; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + switch (attr->index) { + case CPU_BOARD_VER ... SYS_LED_BGR: + i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, set_data); + break; + case PLATFORM_TYPE ... PCIE_RST: + i2c_smbus_write_byte_data(pdata[swpld1].client, reg, set_data); + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "cpld not found"); + } + mutex_unlock(&dni_lock); + return count; +} + +//address and value +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(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_VALUE); + +//CPLD +static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPU_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_reg, NULL, CPLD_VER); +static SENSOR_DEVICE_ATTR(mb_board_ver, S_IRUGO, get_cpld_reg, NULL, MB_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpu_pwr_ok, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPU_PWR_OK); +static SENSOR_DEVICE_ATTR(cpld_platform_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_PLATFORM_RST); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_RST); +static SENSOR_DEVICE_ATTR(cpld_vr_hot, S_IRUGO, get_cpld_reg, NULL, CPLD_VR_HOT); +static SENSOR_DEVICE_ATTR(cpld_pwr_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_PWR_RST); +static SENSOR_DEVICE_ATTR(mb_pwr_enable, S_IRUGO, get_cpld_reg, NULL, MB_PWR_ENABLE); +static SENSOR_DEVICE_ATTR(mb_pwr_pdd, S_IRUGO, get_cpld_reg, NULL, MB_PWR_PDD); +static SENSOR_DEVICE_ATTR(mb_rst_done, S_IRUGO, get_cpld_reg, NULL, MB_RST_DONE); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, MB_RST); +static SENSOR_DEVICE_ATTR(spi_chip_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SPI_CHIP_SEL); +static SENSOR_DEVICE_ATTR(smb_cpu_mux_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SMB_CPU_MUX_SEL); +static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_reg, NULL, PSU_FAN_INT); +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO, get_cpld_reg, NULL, SYS_LED); +static SENSOR_DEVICE_ATTR(sys_led_bgr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SYS_LED_BGR); + +//SWPLD1 +static SENSOR_DEVICE_ATTR(platform_type, S_IRUGO, get_cpld_reg, NULL, PLATFORM_TYPE); +static SENSOR_DEVICE_ATTR(swpld1_mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_MB_RST); +static SENSOR_DEVICE_ATTR(ast2520_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, AST2520_RST); +static SENSOR_DEVICE_ATTR(bmc56870_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, BMC56870_RST); +static SENSOR_DEVICE_ATTR(pcie_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, PCIE_RST); + +//QSFP +static SENSOR_DEVICE_ATTR(sfp_select_port, S_IRUGO | S_IWUSR, get_port_data, set_port_data, SFP_SELECT_PORT); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, for_status, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, for_status, set_lpmode_data, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, for_status, set_reset_data, SFP_RESET); + +static struct attribute *cpld_attrs[] = { + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, + &sensor_dev_attr_cpu_board_ver.dev_attr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_mb_board_ver.dev_attr.attr, + &sensor_dev_attr_cpu_pwr_ok.dev_attr.attr, + &sensor_dev_attr_cpld_platform_rst.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_cpld_vr_hot.dev_attr.attr, + &sensor_dev_attr_cpld_pwr_rst.dev_attr.attr, + &sensor_dev_attr_mb_pwr_enable.dev_attr.attr, + &sensor_dev_attr_mb_pwr_pdd.dev_attr.attr, + &sensor_dev_attr_mb_rst_done.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_spi_chip_sel.dev_attr.attr, + &sensor_dev_attr_smb_cpu_mux_sel.dev_attr.attr, + &sensor_dev_attr_psu_fan_int.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_sys_led_bgr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld1_attrs[] = { + //SWPLD1 + &sensor_dev_attr_swpld1_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld1_reg_addr.dev_attr.attr, + &sensor_dev_attr_platform_type.dev_attr.attr, + &sensor_dev_attr_swpld1_mb_rst.dev_attr.attr, + &sensor_dev_attr_ast2520_rst.dev_attr.attr, + &sensor_dev_attr_bmc56870_rst.dev_attr.attr, + &sensor_dev_attr_pcie_rst.dev_attr.attr, + //QSFP + &sensor_dev_attr_sfp_select_port.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_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_attr_grp = { + .attrs = cpld_attrs, +}; + +static struct attribute_group swpld1_attr_grp = { + .attrs = swpld1_attrs, +}; + +static struct attribute_group swpld2_attr_grp = { + .attrs = swpld2_attrs, +}; + +static struct attribute_group swpld3_attr_grp = { + .attrs = swpld3_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(BUS0); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS0); + 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, &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 __init swpld1_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, "SWPLD1 platform data not found\n"); + return -ENODEV; + } + parent = i2c_get_adapter(BUS1); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld1].client = i2c_new_dummy(parent, pdata[swpld1].reg_addr); + if (!pdata[swpld1].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld1].reg_addr); + goto error; + } + + kobj_swpld1 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + return 0; + +error: + kobject_put(kobj_swpld1); + i2c_unregister_device(pdata[swpld1].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __init swpld2_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, "SWPLD2 platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS1); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld2].client = i2c_new_dummy(parent, pdata[swpld2].reg_addr); + if (!pdata[swpld2].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld2].reg_addr); + goto error; + } + + kobj_swpld2 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld2); + i2c_unregister_device(pdata[swpld2].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __init swpld3_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, "SWPLD3 platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS1); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld3].client = i2c_new_dummy(parent, pdata[swpld3].reg_addr); + if (!pdata[swpld3].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld3].reg_addr); + goto error; + } + + kobj_swpld3 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld3); + i2c_unregister_device(pdata[swpld3].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, &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 int __exit swpld1_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, &swpld1_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld1].client) { + if (!parent) { + parent = (pdata[swpld1].client)->adapter; + } + i2c_unregister_device(pdata[swpld1].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld2_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, &swpld2_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld2].client) { + if (!parent) { + parent = (pdata[swpld2].client)->adapter; + } + i2c_unregister_device(pdata[swpld2].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld3_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, &swpld3_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld3].client) { + if (!parent) { + parent = (pdata[swpld3].client)->adapter; + } + i2c_unregister_device(pdata[swpld3].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-ag9032v2a-cpld", + }, +}; + +static struct platform_driver swpld1_driver = { + .probe = swpld1_probe, + .remove = __exit_p(swpld1_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld1", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld3", + }, +}; +/*---------------- CPLD - end ------------- */ +/*---------------- MUX - start ------------- */ + +struct cpld_mux_platform_data { + int parent; + int base_nr; + struct i2c_client *cpld; + int reg_addr; +}; + +struct cpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct cpld_mux_platform_data data; +}; + +extern int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value); +extern int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg); + +static struct cpld_mux_platform_data ag9032v2a_cpld_mux_platform_data[] = { + { + .parent = BUS0, + .base_nr = BUS0_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS0_MUX_REG, + }, +}; + +static struct cpld_mux_platform_data ag9032v2a_swpld_mux_platform_data[] = { + { + .parent = BUS6, + .base_nr = BUS6_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS6_MUX_REG, + }, + { + .parent = BUS1, + .base_nr = BUS1_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS1_MUX_REG, + }, +}; + +static struct platform_device cpld_mux_device[] = +{ + { + .name = "delta-ag9032v2a-cpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v2a_cpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static struct platform_device swpld1_mux_device[] = +{ + { + .name = "delta-ag9032v2a-swpld1-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v2a_swpld_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v2a-swpld1-mux", + .id = 1, + .dev = { + .platform_data = &ag9032v2a_swpld_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 cpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 cpld_mux_val = 0; + int ret = 0; + if ( mux->data.base_nr == BUS0_BASE_NUM ){ + switch (chan) { + case 0: + cpld_mux_val = MUX_VAL_SWPLD; + break; + case 1: + cpld_mux_val = MUX_VAL_IDEEPROM; + break; + case 2: + default: + cpld_mux_val = MUX_VAL_PCA9548; + break; + } + } + else + { + printk(KERN_ERR "CPLD mux select error\n"); + return 0; + } + ret = cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(cpld_mux_val & 0xff)); + return ret; +} + +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val = 0; + int ret =0; + if ( mux->data.base_nr == BUS6_BASE_NUM ){ + switch (chan) { + case 0: + swpld_mux_val = MUX_VAL_FAN5_EEPROM; + break; + case 1: + swpld_mux_val = MUX_VAL_FAN4_EEPROM; + break; + case 2: + swpld_mux_val = MUX_VAL_FAN3_EEPROM; + break; + case 3: + swpld_mux_val = MUX_VAL_FAN2_EEPROM; + break; + case 4: + swpld_mux_val = MUX_VAL_FAN1_EEPROM; + break; + case 5: + swpld_mux_val = MUX_VAL_FAN_CTL; + break; + case 6: + swpld_mux_val = MUX_VAL_FAN_TMP75; + break; + case 7: + swpld_mux_val = MUX_VAL_FAN_IO_CTL; + break; + default: + swpld_mux_val = MUX_VAL_FAN_CTL; + break; + } + } + else if ( mux->data.base_nr == BUS1_BASE_NUM ){ + swpld_mux_val = chan; + } + else + { + printk(KERN_ERR "SWPLD mux select error\n"); + return 0; + } + ret = cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); + return ret; +} + +static int __init cpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD 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 BUS0: + dev_num = BUS0_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, cpld_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; +} + +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_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 BUS6: + dev_num = BUS6_DEV_NUM; + break; + case BUS1: + dev_num = BUS1_DEV_NUM; + break; + default : + dev_num = DEF_DEV_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; +} + +static int __exit cpld_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; +} + +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; +} + +static struct platform_driver cpld_mux_driver = { + .probe = cpld_mux_probe, + .remove = __exit_p(cpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-cpld-mux", + }, +}; + +static struct platform_driver swpld1_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld1-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ + +static int __init delta_ag9032v2a_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_mux_platform_data *cpld_mux_pdata; + struct cpld_platform_data *cpld_pdata; + struct cpld_mux_platform_data *swpld_mux_pdata; + struct cpld_platform_data *swpld_pdata; + int ret,i = 0; + + mutex_init(&dni_lock); + printk("ag9032v2a_platform module initialization\n"); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpld_driver; + } + // 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; + } + + // 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; + } + + // 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 mux prob which call the SWPLD + ret = platform_driver_register(&cpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_cpld_mux_driver; + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&swpld1_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld1 mux driver\n"); + goto error_swpld1_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 CPUPLD + ret = platform_device_register(&cpld_device); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_cpld_device; + } + + // link the CPLD and the Mux + cpld_pdata = ag9032v2a_cpld_platform_data; + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) + { + cpld_mux_pdata = cpld_mux_device[i].dev.platform_data; + cpld_mux_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&cpld_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_cpld_mux; + } + } + + adapter = i2c_get_adapter(BUS3); + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + // register the SWPLD + ret = platform_device_register(&swpld1_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld1 device\n"); + goto error_swpld1_device; + } + + // register the SWPLD + ret = platform_device_register(&swpld2_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld2 device\n"); + goto error_swpld2_device; + } + + // register the SWPLD + ret = platform_device_register(&swpld3_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld3 device\n"); + goto error_swpld3_device; + } + + // link the SWPLD1 and the Mux + swpld_pdata = ag9032v2a_swpld1_platform_data; + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) + { + swpld_mux_pdata = swpld1_mux_device[i].dev.platform_data; + swpld_mux_pdata->cpld = swpld_pdata[swpld1].client; + ret = platform_device_register(&swpld1_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag9032v2a_swpld1_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ag9032v2a_i2c_device); i++) + { + ret = platform_device_register(&ag9032v2a_i2c_device[i]); + if (ret) + { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9032v2a_i2c_device; + } + } + if (ret) + goto error_cpld_mux; + return 0; + +error_ag9032v2a_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v2a_i2c_device[i]); + } + i = ARRAY_SIZE(swpld1_mux_device); +error_ag9032v2a_swpld1_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&swpld1_mux_device[i]); + } + platform_device_unregister(&swpld3_device); +error_swpld3_device: + platform_device_unregister(&swpld2_device); +error_swpld2_device: + platform_device_unregister(&swpld1_device); +error_swpld1_device: + i2c_unregister_device(i2c_client_9548); + i = ARRAY_SIZE(cpld_mux_device); +error_cpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&cpld_mux_device[i]); + } + platform_device_unregister(&cpld_device); +error_cpld_device: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld1_mux_driver); +error_swpld1_mux_driver: + platform_driver_unregister(&cpld_mux_driver); +error_cpld_mux_driver: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_driver_unregister(&swpld1_driver); +error_swpld1_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag9032v2a_platform_exit(void) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(ag9032v2a_i2c_device); i++) { + platform_device_unregister(&ag9032v2a_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) { + platform_device_unregister(&swpld1_mux_device[i]); + } + + 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); + + i2c_unregister_device(i2c_client_9548); + + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) { + platform_device_unregister(&cpld_mux_device[i]); + } + + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld1_mux_driver); + platform_driver_unregister(&cpld_mux_driver); + platform_device_unregister(&cpld_device); + platform_driver_unregister(&cpld_driver); +} + +module_init(delta_ag9032v2a_platform_init); +module_exit(delta_ag9032v2a_platform_exit); + +MODULE_DESCRIPTION("DELTA ag9032v2a Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/dni_ag9032v2a_psu.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/dni_ag9032v2a_psu.c new file mode 100644 index 00000000..5869698c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/dni_ag9032v2a_psu.c @@ -0,0 +1,495 @@ +/* + * An hwmon driver for delta AG9032v1 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * Aries Lin + * + * 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 + +/* 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 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[2]; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_model[14]; + u8 mfr_serial[14]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(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_fault(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); + +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, +}; + +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 \ + *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; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle[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->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 for_fan_fault(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_fault >> 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->v_out; + return (exponent > 0) ? sprintf(buf, "%d\n", \ + mantissa * (1 << exponent)) : \ + sprintf(buf, "%d\n", mantissa / (1 << -exponent) * multiplier); + +} + +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); + + 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_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])}, + {0x90, &(data->fan_speed[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 */ + 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[0] = '\0'; + } + + 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->mfr_serial[0] = '\0'; + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, \ + S_IRUGO | S_IWUSR, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +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 struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.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_ag9032v2a_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag9032v2a_psu", dni_ag9032v2a_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/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/dni_emc2305.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/dni_emc2305.c new file mode 100644 index 00000000..73d9900a --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/modules/builds/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/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/PKG.yml new file mode 100644 index 00000000..79d3b872 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-delta-ag9032v2a ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/Makefile new file mode 100644 index 00000000..b1f2579b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-delta-ag9032v2a +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_delta_ag9032v2a onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-delta-ag9032v2a.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/libonlp-x86-64-delta-ag9032v2a-r0.mk b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/libonlp-x86-64-delta-ag9032v2a-r0.mk new file mode 100644 index 00000000..278d63a8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/lib/libonlp-x86-64-delta-ag9032v2a-r0.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-delta-ag9032v2a-r0 module. +# +# Autogenerated 2016-03-16 22:11:47.698846 +# +############################################################################### +libonlp-x86-64-delta-ag9032v2a-r0_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/onlpdump/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..5bbac151 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_delta_ag9032v2a onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/.module b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/.module new file mode 100644 index 00000000..a40454cc --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_delta_ag9032v2a diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/Makefile new file mode 100644 index 00000000..e92e1be7 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/Makefile @@ -0,0 +1,10 @@ +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.mk + +MODULE := x86_64_delta_ag9032v2a +AUTOMODULE := x86_64_delta_ag9032v2a +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..52d70057 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# x86_64_delta_ag9032v2a Autogeneration +# +############################################################################### + +x86_64_delta_ag9032v2a_AUTO_DEFS := module/auto/x86_64_delta_ag9032v2a.yml +x86_64_delta_ag9032v2a_AUTO_DIRS := module/inc/x86_64_delta_ag9032v2a module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/x86_64_delta_ag9032v2a.yml b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/x86_64_delta_ag9032v2a.yml new file mode 100755 index 00000000..78134b91 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/auto/x86_64_delta_ag9032v2a.yml @@ -0,0 +1,55 @@ +############################################################################### +# +# x86_64_delta_ag9032v2a Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_DELTA_ag9032v2a_CONFIG_PORTING_STDLIB +- X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 +- X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT: + doc: "SFP port numbers." + default: 4 +- X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX: + doc: "Max fan speed." + default: 18000 + +definitions: + cdefs: + X86_64_DELTA_AG9032V2A_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_delta_ag9032v2a_config + + portingmacro: + X86_64_DELTA_ag9032v2a: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a.x b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a.x new file mode 100644 index 00000000..eaa7797e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a.x @@ -0,0 +1,16 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ + + +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_config.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_config.h new file mode 100755 index 00000000..728bb45b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_config.h @@ -0,0 +1,157 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_ag9032v2a Configuration Header + * + * @addtogroup x86_64_delta_ag9032v2a-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_AG9032V2A_CONFIG_H__ +#define __X86_64_DELTA_AG9032V2A_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_DELTA_AG9032V2A_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING +#define X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT +#define X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB +#define X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_DELTA_ag9032v2a_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI +#define X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT + * + * SFP port numbers. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT +#define X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT 4 +#endif + +/** + * X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX + * + * Max fan speed. */ + + +#ifndef X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX +#define X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX 18000 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_delta_ag9032v2a_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_delta_ag9032v2a_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_delta_ag9032v2a_config_settings table. */ +extern x86_64_delta_ag9032v2a_config_settings_t x86_64_delta_ag9032v2a_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_delta_ag9032v2a_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_delta_ag9032v2a_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_delta_ag9032v2a_porting.h" + +#endif /* __x86_64_delta_ag9032v2a_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_dox.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_dox.h new file mode 100644 index 00000000..d7f18bea --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_delta_ag9032v2a Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_ag9032v2a_DOX_H__ +#define _X86_64_DELTA_ag9032v2a_DOX_H__ + +/** + * @defgroup x86_64_delta_ag9032v2a x86_64_delta_ag9032v2a - x86_64_delta_ag9032v2a Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_delta_ag9032v2a-x86_64_delta_ag9032v2a Public Interface + * @defgroup x86_64_delta_ag9032v2a-config Compile Time Configuration + * @defgroup x86_64_delta_ag9032v2a-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_DELTA_ag9032v2a_DOX_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_porting.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_porting.h new file mode 100755 index 00000000..5493d589 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/inc/x86_64_delta_ag9032v2a/x86_64_delta_ag9032v2a_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_ag9032v2 Porting Macros. + * + * @addtogroup x86_64_delta_ag9032v2-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_AG9032V2A_PORTING_H__ +#define __X86_64_DELTA_AG9032V2A_PORTING_H__ + + +/* */ +#if X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_DELTA_AG9032V2A_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_DELTA_AG9032V2A_MALLOC GLOBAL_MALLOC + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_MALLOC malloc + #else + #error The macro X86_64_DELTA_AG9032V2A_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_FREE + #if defined(GLOBAL_FREE) + #define X86_64_DELTA_AG9032V2A_FREE GLOBAL_FREE + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_FREE free + #else + #error The macro X86_64_DELTA_AG9032V2A_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_DELTA_AG9032V2A_MEMSET GLOBAL_MEMSET + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_MEMSET memset + #else + #error The macro X86_64_DELTA_AG9032V2A_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_DELTA_AG9032V2A_MEMCPY GLOBAL_MEMCPY + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_MEMCPY memcpy + #else + #error The macro X86_64_DELTA_AG9032V2A_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_DELTA_AG9032V2A_STRNCPY GLOBAL_STRNCPY + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_STRNCPY strncpy + #else + #error The macro X86_64_DELTA_AG9032V2A_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_DELTA_AG9032V2A_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_VSNPRINTF vsnprintf + #else + #error The macro X86_64_DELTA_AG9032V2A_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_DELTA_AG9032V2A_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_SNPRINTF snprintf + #else + #error The macro X86_64_DELTA_AG9032V2A_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AG9032V2A_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_DELTA_AG9032V2A_STRLEN GLOBAL_STRLEN + #elif X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AG9032V2A_STRLEN strlen + #else + #error The macro X86_64_DELTA_AG9032V2A_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* _X86_64_DELTA_AG9032V2A_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..e5c9fb11 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_delta_ag9032v2a_INCLUDES := -I $(THIS_DIR)inc +x86_64_delta_ag9032v2a_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_delta_ag9032v2a_DEPENDMODULE_ENTRIES := init:x86_64_delta_ag9032v2a ucli:x86_64_delta_ag9032v2a + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..ae7ef8d0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_delta_ag9032v2a_ucli.c + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/fani.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..6db5b6c0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/fani.c @@ -0,0 +1,479 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include + + + +typedef struct fan_path_S +{ + char *status; + char *speed; + char *ctrl_speed; +}fan_path_T; + +static fan_path_T fan_path[] = /* must map with onlp_fan_id */ +{ + { NULL, NULL, NULL }, + { "26-002c/fan1_fault", "26-002c/fan1_input", "26-002c/fan1_input_percentage" }, + { "26-002c/fan2_fault", "26-002c/fan2_input", "26-002c/fan2_input_percentage" }, + { "26-002c/fan3_fault", "26-002c/fan3_input", "26-002c/fan3_input_percentage" }, + { "26-002c/fan4_fault", "26-002c/fan4_input", "26-002c/fan4_input_percentage" }, + { "26-002c/fan5_fault", "26-002c/fan5_input", "26-002c/fan5_input_percentage" }, + { "26-002d/fan1_fault", "26-002d/fan1_input", "26-002d/fan1_input_percentage" }, + { "26-002d/fan2_fault", "26-002d/fan2_input", "26-002d/fan2_input_percentage" }, + { "26-002d/fan3_fault", "26-002d/fan3_input", "26-002d/fan3_input_percentage" }, + { "26-002d/fan4_fault", "26-002d/fan4_input", "26-002d/fan4_input_percentage" }, + { "26-002d/fan5_fault", "26-002d/fan5_input", "26-002d/fan5_input_percentage" }, + { "4-0058/psu_fan1_fault", "4-0058/psu_fan1_speed_rpm", "4-0058/psu_fan1_duty_cycle_percentage" }, + { "5-0058/psu_fan1_fault", "5-0058/psu_fan1_speed_rpm", "5-0058/psu_fan1_duty_cycle_percentage" } +}; + + + +#define MAKE_FAN_INFO_NODE_ON_FAN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_FAN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[] = { + { }, // Not used + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(9), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(10), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info, char *dev_name) +{ + int bit_data = 0; + int rpm = 0; + char fullpath[100] = {0}; + int rv = ONLP_STATUS_OK; + uint8_t present_bit = 0x00; + uint8_t bit = 0x00; + UINT4 multiplier = 1; + UINT4 u4Data = 0; + + if(dni_bmc_check()==BMC_ON) + { + if(dni_bmc_sensor_read(dev_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->rpm = u4Data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + } + + rv = dni_bmc_fanpresent_info_get(&bit_data); + if(rv == ONLP_STATUS_OK && bit_data != 0) + { + present_bit = bit_data; + } + else + { + rv = ONLP_STATUS_E_INVALID; + } + } + else + { + dev_info_t dev_info; + dev_info.bus = I2C_BUS_28; + dev_info.addr = FAN_IO_CTL; + dev_info.offset = 0x00; + dev_info.flags = DEFAULT_FLAG; + + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + rpm = dni_i2c_lock_read_attribute(NULL, fullpath); + info->rpm = rpm; + + /* If rpm is FAN_ZERO_TACH, then the rpm value is zero. */ + if(info->rpm == FAN_ZERO_RPM) + info->rpm = 0; + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100)/MAX_FRONT_FAN_SPEED; + present_bit = dni_i2c_lock_read(NULL, &dev_info); + } + switch(local_id) + { + case FAN_1_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + if((present_bit & (bit+1)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_2_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + if((present_bit & ((bit+1) << 1)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_3_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + if((present_bit & ((bit+1) << 2)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_4_ON_FAN_BOARD: + case FAN_9_ON_FAN_BOARD: + if((present_bit & ((bit+1) << 3)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_5_ON_FAN_BOARD: + case FAN_10_ON_FAN_BOARD: + if((present_bit & ((bit+1) << 4)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + } + return rv; + +} + +static int +dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info, char *dev_name) +{ + int rpm_data = 0; + int r_data = 0; + int bit_data = 0; + int rv = ONLP_STATUS_OK; + int psu_present = 0; + //char module_name[20] = {0}; + UINT4 multiplier = 1; + UINT4 u4Data = 0; + char fullpath[100] = {0}; + if(dni_bmc_check()==BMC_ON) + { + rv = dni_psu_present(&bit_data); + psu_present = bit_data; + rv = dni_bmc_sensor_read(dev_name, &u4Data, multiplier); + rpm_data = (int)u4Data; + + switch(local_id) + { + case FAN_1_ON_PSU1: + if( (psu_present & 0x80) !=0x80) + { + info->rpm = rpm_data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_FAILED; + rv = ONLP_STATUS_E_INVALID; + } + break; + case FAN_1_ON_PSU2: + if( (psu_present & 0x08) !=0x08) + { + info->rpm = rpm_data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_FAILED; + rv = ONLP_STATUS_E_INVALID; + } + break; + } + } + else + { + dev_info_t dev_info; + dev_info.addr = PSU_EEPROM; + dev_info.offset = 0x00; /* In EEPROM address 0x00 */ + dev_info.flags = DEFAULT_FLAG; + switch(local_id) + { + case FAN_1_ON_PSU1: + dev_info.bus = I2C_BUS_4; + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].status); + break; + case FAN_1_ON_PSU2: + dev_info.bus = I2C_BUS_5; + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].status); + break; + default: + break; + } + if(dni_i2c_lock_read(NULL, &dev_info) >= 0) { + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].status); + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + + if (r_data == 1) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + /* Read PSU FAN speed from psu_fan1_speed_rpm */ + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + info->rpm = r_data; + + /* Calculate psu fan duty cycle based on rpm */ + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + return rv; + +} +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[ONLP_OID_ID_GET(id)]; + + switch(local_id) + { + case FAN_1_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_5_1"); + break; + case FAN_2_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_4_1"); + break; + case FAN_3_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_3_1"); + break; + case FAN_4_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_1"); + break; + case FAN_5_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_1"); + break; + case FAN_6_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_5_2"); + break; + case FAN_7_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_4_2"); + break; + case FAN_8_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_3_2"); + break; + case FAN_9_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_2"); + break; + case FAN_10_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_2"); + break; + case FAN_1_ON_PSU1: + rv = dni_fani_info_get_fan_on_psu(local_id, info, "PSU1_Fan"); + break; + case FAN_1_ON_PSU2: + rv = dni_fani_info_get_fan_on_psu(local_id, info, "PSU2_Fan"); + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + + return rv; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + int local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + if(dni_bmc_check() != BMC_ON) + { + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + switch (local_id) + { + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + case FAN_9_ON_FAN_BOARD: + case FAN_10_ON_FAN_BOARD: + sprintf(fullpath, "%s%s",PREFIX_PATH, fan_path[local_id].speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + sprintf(data, "%d", rpm); + + dni_i2c_lock_write_attribute(NULL, data, fullpath); + } + return ONLP_STATUS_OK; + +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + + if(dni_bmc_check() != BMC_ON) + { + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* Select PSU member */ + switch (local_id) { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + case FAN_9_ON_FAN_BOARD: + case FAN_10_ON_FAN_BOARD: + break; + default: + return ONLP_STATUS_E_INVALID; + } + + sprintf(fullpath, "%s%s",PREFIX_PATH, fan_path[local_id].ctrl_speed); + + /* Write percentage to psu_fan1_duty_cycle_percentage */ + sprintf(data, "%d", p); + dni_i2c_lock_write_attribute(NULL, data, fullpath); + } + return ONLP_STATUS_OK; + +} + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/ledi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..8bcbb04a --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,606 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* + * Get the information for the given LED OID. + */ + +static onlp_led_info_t linfo[] = +{ + { }, // Not used + { + { ONLP_LED_ID_CREATE(LED_FRONT_FAN), "FRONT LED (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_SYS), "FRONT LED (SYS LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_PWR1), "FRONT LED (PWR1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_PWR2), "FRONT LED (PWR2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1), "FAN TRAY 1 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2), "FAN TRAY 2 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3), "FAN TRAY 3 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4), "FAN TRAY 4 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_5), "FAN TRAY 5 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_GREEN, + }, +}; + + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int r_data = 0; + int bit_data = 0; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[ONLP_OID_ID_GET(id)]; + + if(dni_bmc_check() == BMC_ON){ + switch(local_id) + { + case LED_FRONT_FAN: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, SYS_LED1_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x03) == 0x03 || (r_data & 0x03) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_SYS: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, SYS_LED1_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_GREEN_BLINKING; + else if((r_data & 0x0c) == 0x0c) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x0c) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR1: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, SYS_LED1_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0xc0) == 0xc0 || (r_data & 0xc0) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR2: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, SYS_LED1_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x30) == 0x30 || (r_data & 0x30) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_REAR_FAN_TRAY_1: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, SYS_LED3_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_1) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_2: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_2) == ONLP_STATUS_OK){ + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_3: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_3) == ONLP_STATUS_OK){ + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_4: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + + if(dni_fan_present(LED_REAR_FAN_TRAY_4) == ONLP_STATUS_OK){ + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_5: + if( dni_bmc_data_get(I2C_BUS_3, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + + if(dni_fan_present(LED_REAR_FAN_TRAY_5) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + } + + } + else{ + switch(local_id) + { + case LED_FRONT_FAN: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x03) == 0x03 || (r_data & 0x03) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_SYS: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_GREEN_BLINKING; + else if((r_data & 0x0c) == 0x0c) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x0c) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR1: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0xc0) == 0xc0 || (r_data & 0xc0) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR2: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + else if ((r_data & 0x30) == 0x30 || (r_data & 0x30) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_REAR_FAN_TRAY_1: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED3_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_1) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_2: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_2) == ONLP_STATUS_OK){ + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_3: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_3) == ONLP_STATUS_OK){ + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_4: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_4) == ONLP_STATUS_OK){ + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_5: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_5) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + } + } + + + /* Set the on/off status */ + if (info->mode == ONLP_LED_MODE_OFF) + info->status |= ONLP_LED_STATUS_FAILED; + else + info->status |=ONLP_LED_STATUS_PRESENT; + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + if (!on_or_off) + { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + VALIDATE(id); + int local_id = ONLP_OID_ID_GET(id); + uint8_t front_panel_led_value = 0; + uint8_t fan_tray_led_reg_value = 0; + + if(dni_bmc_check() == BMC_ON){ + return ONLP_STATUS_OK; + } + else + { + switch(local_id) + { + case LED_FRONT_FAN: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + front_panel_led_value &= ~0x03; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x01; + } + else if(mode == ONLP_LED_MODE_RED){ + front_panel_led_value |= 0x02; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH,SYS_LED1_REGISTER,front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_FRONT_SYS: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + front_panel_led_value &= ~0x0c; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x04; + } + else if(mode == ONLP_LED_MODE_RED){ + front_panel_led_value |= 0x08; + } + else if(mode == ONLP_LED_MODE_GREEN_BLINKING){ + front_panel_led_value |= 0x0c; + } + else{ + front_panel_led_value = front_panel_led_value; + } + if(dni_lock_cpld_write_attribute(SWPLD1_PATH,SYS_LED1_REGISTER,front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_FRONT_PWR1: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + front_panel_led_value &= ~0xc0; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x40; + } + else if(mode == ONLP_LED_MODE_RED){ + front_panel_led_value |= 0x80; + } + else{ + front_panel_led_value = front_panel_led_value; + } + if(dni_lock_cpld_write_attribute(SWPLD1_PATH,SYS_LED1_REGISTER,front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_FRONT_PWR2: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH,SYS_LED1_REGISTER); + front_panel_led_value &= ~0x30; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x10; + } + else if(mode == ONLP_LED_MODE_RED){ + front_panel_led_value |= 0x20; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH,SYS_LED1_REGISTER,front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_REAR_FAN_TRAY_1: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED3_REGISTER); + fan_tray_led_reg_value &= ~0xc0; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x40; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x80; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, SYS_LED3_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_REAR_FAN_TRAY_2: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x03; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x01; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x02; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_REAR_FAN_TRAY_3: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x0c; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x04; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x08; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_REAR_FAN_TRAY_4: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x30; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x10; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x20; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + case LED_REAR_FAN_TRAY_5: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0xc0; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x40; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x80; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + } + } + return ONLP_STATUS_OK; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..c4ec26c8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_delta_ag9032v2a +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..c02dabbe --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,518 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include + +static onlp_shlock_t* dni_lock = NULL; + +#define DNI_BUS_LOCK() \ + do{ \ + onlp_shlock_take(dni_lock); \ + }while(0) + +#define DNI_BUS_UNLOCK() \ + do{ \ + onlp_shlock_give(dni_lock); \ + }while(0) + +#define DNILOCK_MAGIC 0xA6D2B4E8 + +void lockinit() +{ + static int sem_inited = 0; + if(!sem_inited) + { + onlp_shlock_create(DNILOCK_MAGIC, &dni_lock, "bus-lock"); + sem_inited = 1; + } +} + +int dni_bmc_sensor_read(char *device_name, UINT4 *num, UINT4 multiplier) +{ + FILE *fpRead; + char Buf[ 10 ]={0}; + char ipmi_command[120] = {0}; + int lenth=10; + float num_f; + + sprintf(ipmi_command, "ipmitool sdr get %s |grep 'Sensor Reading'| awk -F':' '{print $2}'| awk -F' ' '{ print $1}'", device_name); + fpRead = popen(ipmi_command, "r"); + + if(fpRead == NULL){ + pclose(fpRead); + return ONLP_STATUS_E_GENERIC; + } + fgets(Buf, lenth , fpRead); + num_f = atof( Buf ); + *num = num_f * multiplier; + pclose(fpRead); + return ONLP_STATUS_OK; +} +int +dni_bmc_check() +{ + char cmd[30] = {0}; + char str_data[100] = {0}; + FILE *fptr = NULL; + int rv = 0; + sprintf(cmd, "ipmitool raw 0x38 0x1a 0x00"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + rv = strtol(str_data, NULL, 16); + if(rv == 1) + rv = BMC_OFF; + else + rv = BMC_ON; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int +dni_bmc_data_get(int bus, int addr, int reg, int len, int *r_data) +{ + int rv = ONLP_STATUS_OK; + char cmd[50] = {0}; + char rdata[10] = {0}; + FILE *fptr = NULL; + + sprintf(cmd, "ipmitool raw 0x38 0x2 %d 0x%x 0x%x %d", bus ,addr, reg, len); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(rdata, sizeof(rdata), fptr) != NULL) + *r_data = strtol(rdata, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int +dni_bmc_fanpresent_info_get(int *r_data) +{ + int rv = ONLP_STATUS_OK; + char cmd[30] = {0}; + char str_data[100] = {0}; + FILE *fptr = NULL; + + sprintf(cmd, "ipmitool raw 0x38 0x0e"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + *r_data = strtol(str_data, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + return rv; +} + +int hex_to_int(char hex_input) +{ + int first = hex_input / 16 - 3; + int second = hex_input % 16; + int result = first * 10 + second; + + if(result > 9) result--; + return result; +} + +int hex_to_ascii(char hex_high, char hex_low) +{ + int high = hex_to_int(hex_high) * 16; + int low = hex_to_int(hex_low); + + return high + low; +} +int dni_psu_present(int *r_data) +{ + FILE *fptr = NULL; + int rv = ONLP_STATUS_OK; + char cmd[35] = {0}; + char str_data[50] = {0}; + sprintf(cmd, "ipmitool raw 0x38 0x2 3 0x6a 0x03 1"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + *r_data = strtol(str_data, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + return rv; +} + +int +dni_psui_eeprom_info_get(char * r_data,char *device_name,int number) +{ + int i = 0; + int rv = ONLP_STATUS_OK; + FILE *fptr = NULL; + char cmd[35] = {0}; + char str_data[50] = {0} ; + char buf; + char* renewCh; + sprintf(cmd, "ipmitool fru print %d | grep '%s' | awk -F':' '{print $2}'",number,device_name); + fptr = popen(cmd, "r"); + while((buf = fgetc(fptr)) != EOF) + { + if( buf != ' ') + { + str_data[i] = buf; + i++; + } + } + for(i = 0; i < PSU_NUM_LENGTH; i++) + r_data[i] = str_data[i]; + pclose(fptr); + + renewCh = strstr(r_data,"\n"); + if(renewCh) + *renewCh= '\0'; + + return rv; +} + + +int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info) +{ + int r_data=0; + DNI_BUS_LOCK(); + if(dev_info->size == 1) + r_data = onlp_i2c_readb(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + else + r_data = onlp_i2c_readw(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + + DNI_BUS_UNLOCK(); + return r_data; +} + +int dni_i2c_lock_write( mux_info_t * mux_info, dev_info_t * dev_info) +{ + DNI_BUS_LOCK(); + /* Write size */ + if(dev_info->size == 1) + onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); + else + onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); + + DNI_BUS_UNLOCK(); + return 0; +} +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) +{ + + int fd, nbytes = 10, rv = -1; + char r_data[10] = {0}; + + DNI_BUS_LOCK(); + if ((fd = open(fullpath, O_RDONLY)) >= 0) + { + if ((read(fd, r_data, nbytes)) > 0) + rv = atoi(r_data); + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath) +{ + int fd, nbytes = 10, rv = -1; + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(fullpath, O_WRONLY, 0644)) >= 0) + { + if (write(fd, data, (ssize_t)nbytes) > 0) + { + fsync(fd); + rv = 0; + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} +/* Use this function to select MUX and read data on CPLD */ +int dni_lock_cpld_read_attribute(char *cpld_path, int addr) +{ + int fd, fd1, nbytes = 10, data = 0, rv = -1; + char r_data[10] = {0}; + char address[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + sprintf(cpld_data_path, "%s/swpld1_reg_value", cpld_path); + sprintf(cpld_addr_path, "%s/swpld1_reg_addr", cpld_path); + sprintf(address, "0x%02x", addr); + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(cpld_addr_path, O_WRONLY, 0644)) >= 0) + { + if (write(fd, address, 4) > 0) + { + fsync(fd); + if ((fd1 = open(cpld_data_path, O_RDONLY, 0644)) >= 0) + { + if ((read(fd1, r_data, nbytes)) > 0) + { + sscanf(r_data, "%x", &data); + rv = data; + } + } + close(fd1); + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} +/* Use this function to select MUX and write data on CPLD */ +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data) +{ + int fd, fd1, rv = -1; + char address[10] = {0}; + char datas[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/swpld1_reg_value", cpld_path); + sprintf(cpld_addr_path, "%s/swpld1_reg_addr", cpld_path); + sprintf(address, "0x%02x", addr); + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(cpld_addr_path, O_WRONLY, 0644)) >= 0) + { + if ((write(fd, address, 4)) > 0) + { + fsync(fd); + if ((fd1 = open(cpld_data_path, O_WRONLY, 0644)) >= 0) + { + sprintf(datas, "0x%02x", data); + if (write(fd1, datas, 4) > 0) + { + fsync(fd1); + rv = 0; + } + } + close(fd1); + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +int +dni_fanpresent_info_get(int *r_data) +{ + int rv = ONLP_STATUS_OK; + char cmd[30] = {0}; + char str_data[100] = {0}; + FILE *fptr = NULL; + + sprintf(cmd, "ipmitool raw 0x38 0x0e"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + { + *r_data = strtol(str_data, NULL, 16); + } + else + { + rv = ONLP_STATUS_E_INVALID; + } + } + else + { + rv = ONLP_STATUS_E_INVALID; + } + pclose(fptr); + return rv; +} +int +dni_fan_present(int id){ + int rv; + dev_info_t dev_info; + int bit_data = 0; + int data = 0; + uint8_t present_bit = 0x00; + int fantray_present = 0; + + if(dni_bmc_check() == BMC_ON) + { + rv = dni_fanpresent_info_get(&bit_data); + + if(rv == ONLP_STATUS_OK) + { + present_bit = bit_data; + data = (present_bit & (1 << -(id - 9))); + if(data == 0) + rv = ONLP_STATUS_OK; + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + } + else if(dni_bmc_check() == BMC_OFF){ + switch(id){ + case LED_REAR_FAN_TRAY_1: + dev_info.addr = FAN_TRAY_1; + dev_info.bus = I2C_BUS_25; + break; + case LED_REAR_FAN_TRAY_2: + dev_info.addr = FAN_TRAY_2; + dev_info.bus = I2C_BUS_24; + break; + case LED_REAR_FAN_TRAY_3: + dev_info.addr = FAN_TRAY_3; + dev_info.bus = I2C_BUS_23; + break; + case LED_REAR_FAN_TRAY_4: + dev_info.addr = FAN_TRAY_4; + dev_info.bus = I2C_BUS_22; + break; + case LED_REAR_FAN_TRAY_5: + dev_info.addr = FAN_TRAY_5; + dev_info.bus = I2C_BUS_21; + break; + } + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + if(fantray_present >= 0) + rv = ONLP_STATUS_OK; + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + + return rv; +} +int dni_fan_speed_good() +{ + int rpm = 0, rpm1 = 0, speed_good = 0; + + rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + rpm = dni_i2c_lock_read_attribute(NULL, FAN5_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN5_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + return speed_good; +} + + +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd,len,rv=0; + DNI_BUS_LOCK(); + if ((buffer == NULL) || (buf_size < 0)) { + rv = -1; + goto ERROR; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + rv = -1; + goto ERROR; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + rv = -1; + goto ERROR; + } + + if ((close(fd) == -1)) { + rv = -1; + goto ERROR; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + rv = -1; + goto ERROR; + } +ERROR: + DNI_BUS_UNLOCK(); + return rv; +} + +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) + return -1; + + ret = dni_i2c_read_attribute_binary(filename, buffer, buf_size-1, data_len); + if (ret == 0) + buffer[buf_size-1] = '\0'; + + return ret; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..b03e35fe --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,217 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_delta_ag9032v2a_log.h" +#include +#include +typedef unsigned int UINT4; + +/* CPLD numbrt & peripherals */ +#define NUM_OF_SFP (1) +#define NUM_OF_QSFP (32) +#define NUM_OF_PORT NUM_OF_SFP + NUM_OF_QSFP +#define NUM_OF_THERMAL_ON_MAIN_BROAD (5) +#define NUM_OF_LED_ON_MAIN_BROAD (9) +#define NUM_OF_FAN_ON_MAIN_BROAD (10) +#define NUM_OF_PSU_ON_MAIN_BROAD (2) +#define NUM_OF_SENSORS (47) +#define CHASSIS_FAN_COUNT (10) +#define CHASSIS_THERMAL_COUNT (5) +#define NUM_OF_THERMAL (7) +#define PSU1_ID (1) +#define PSU2_ID (2) +#define PSU_NUM_LENGTH (15) +#define MAX_FRONT_FAN_SPEED (23000) +#define MAX_PSU_FAN_SPEED (18380) +#define MAX_REAR_FAN_SPEED (20500) +#define FAN_ZERO_RPM (960) +#define FAN_SPEED_NORMALLY (5) +#define ALL_FAN_TRAY_EXIST (5) +#define BMC_OFF (1) +#define BMC_ON (0) +#define PSU_NODE_MAX_PATH_LEN (64) + +#define CPU_CPLD_VERSION "/sys/devices/platform/delta-ag9032v2a-cpld.0/cpld_ver" +#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-2/2-0053/eeprom" +#define SWPLD1_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0" +#define SWPLD2_PATH "/sys/devices/platform/delta-ag9032v2a-swpld2.0" +#define FAN1_FRONT "/sys/bus/i2c/device/i2c-26/26-002c/fan1_input" +#define FAN1_REAR "/sys/bus/i2c/device/i2c-26/26-002d/fan1_input" +#define FAN2_FRONT "/sys/bus/i2c/device/i2c-26/26-002c/fan2_input" +#define FAN2_REAR "/sys/bus/i2c/device/i2c-26/26-002d/fan2_input" +#define FAN3_FRONT "/sys/bus/i2c/device/i2c-26/26-002c/fan3_input" +#define FAN3_REAR "/sys/bus/i2c/device/i2c-26/26-002d/fan3_input" +#define FAN4_FRONT "/sys/bus/i2c/device/i2c-26/26-002c/fan4_input" +#define FAN4_REAR "/sys/bus/i2c/device/i2c-26/26-002d/fan4_input" +#define FAN5_FRONT "/sys/bus/i2c/device/i2c-26/26-002c/fan5_input" +#define FAN5_REAR "/sys/bus/i2c/device/i2c-26/26-002d/fan5_input" +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define SFP_SELECT_PORT_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_select_port" +#define SFP_IS_PRESENT_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_is_present" +#define SFP_IS_PRESENT_ALL_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_is_present_all" +#define QSFP_RESET_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_reset" +#define QSFP_LP_MODE_PATH "/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_lp_mode" +#define PREFIX_PATH "/sys/bus/i2c/devices/" +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/4-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/5-0058/" +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +/* REG define*/ +#define SWPLD_1_ADDR (0x6A) +#define SWPLD_2_ADDR (0x73) +#define SWPLD_3_ADDR (0x75) +#define PSU_EEPROM (0x50) +#define FAN_TRAY_1 (0x51) +#define FAN_TRAY_2 (0x52) +#define FAN_TRAY_3 (0x53) +#define FAN_TRAY_4 (0x54) +#define FAN_TRAY_5 (0x55) +#define FAN_IO_CTL (0x27) +#define SYS_LED1_REGISTER (0x21) +#define SYS_LED3_REGISTER (0x23) +#define FAN_LED_REGISTER (0x20) +#define POWER_STATUS_REGISTER (0x03) +#define DEFAULT_FLAG (0x00) + +/*SFP REG define*/ +#define SFP_RESPOND_1 (0x0A) +#define SFP_RESPOND_2 (0x0B) +#define SFP_RESPOND_3 (0x0C) +#define SFP_RESPOND_4 (0x0D) + + +typedef struct mux_info_s +{ + uint8_t offset; + uint8_t channel; + char dev_data[10]; + uint32_t flags; + +}mux_info_t; + +typedef struct dev_info_s +{ + int bus; + int size; + uint8_t addr; + uint8_t data_8; + uint16_t data_16; + uint8_t offset; + uint32_t flags; + +}dev_info_t; +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len); + +int dni_fanpresent_info_get(int *r_data); +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data); +int dni_lock_cpld_read_attribute(char *cpld_path, int addr); +int dni_fan_present(int id); +int dni_fan_speed_good(); +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len); +int dni_bmc_sensor_read(char *device_name, UINT4 *num, UINT4 multiplier); +int dni_psui_eeprom_info_get(char *r_data,char *device_name,int number); +int dni_bmc_check(); +int dni_bmc_fanpresent_info_get(int *r_data); +int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info); +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath); +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath); +int dni_psu_present(int *r_data); +int dni_bmc_data_get(int bus, int addr, int reg, int len, int *r_data); +void lockinit(); +char dev_name[50][32]; +float dev_sensor[50]; + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_WIND_ON_ADAPTER_BOARD, + THERMAL_1_ON_MAIN_BOARD, + THERMAL_2_ON_MAIN_BOARD, + THERMAL_3_ON_MAIN_BOARD, + THERMAL_4_ON_CPU_BOARD, + THERMAL_5_ON_PSU1, + THERMAL_6_ON_PSU2 +}; + +typedef enum +{ + FAN_RESERVED = 0, + FAN_1_ON_FAN_BOARD, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_7_ON_FAN_BOARD, + FAN_8_ON_FAN_BOARD, + FAN_9_ON_FAN_BOARD, + FAN_10_ON_FAN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2 +} onlp_fan_id; + +typedef enum +{ + LED_RESERVED = 0, + LED_FRONT_FAN, + LED_FRONT_SYS, + LED_FRONT_PWR1, + LED_FRONT_PWR2, + LED_REAR_FAN_TRAY_1, + LED_REAR_FAN_TRAY_2, + LED_REAR_FAN_TRAY_3, + LED_REAR_FAN_TRAY_4, + LED_REAR_FAN_TRAY_5 +}onlp_led_id; + + +enum bus +{ + I2C_BUS_0 = 0, + I2C_BUS_1, + I2C_BUS_2, + I2C_BUS_3, + I2C_BUS_4, + I2C_BUS_5, + I2C_BUS_6, + I2C_BUS_7, + I2C_BUS_8, + I2C_BUS_9, + I2C_BUS_10, + I2C_BUS_11, + I2C_BUS_21 = 21, + I2C_BUS_22, + I2C_BUS_23, + I2C_BUS_24, + I2C_BUS_25, + I2C_BUS_26, + I2C_BUS_27, + I2C_BUS_28, +}; +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/psui.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..e6f0fb3c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/psui.c @@ -0,0 +1,318 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include "x86_64_delta_ag9032v2a_int.h" +#include +#include "platform_lib.h" +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +static int +dni_psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + switch (id) { + case PSU1_ID: + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + break; + case PSU2_ID: + sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + break; + default: + break; + } + + /* Read attribute value */ + *value = dni_i2c_lock_read_attribute(NULL, node_path); + + return ret; +} + +int +onlp_psui_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +static int +dni_psu_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int i=0; + int local_id; + UINT4 multiplier = 1000; + UINT4 u4Data = 0; + + char device_name[10] = {0}; + char name[20]={0}; + char name1[20]={0}; + char *module_name =name ; + char *module_name1 =name1 ; + int val = 0; + local_id = ONLP_OID_ID_GET(info->hdr.id); + char val_char[16] = {'\0'}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {'\0'}; + + /* Set the associated oid_table + * Set PSU's fan and thermal to child OID + */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(local_id + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(local_id + CHASSIS_THERMAL_COUNT); + if(dni_bmc_check()==BMC_ON) + { + /*get psu Pin/Pout*/ + sprintf(device_name, "PSU%d_Pin",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == 0){ + if (u4Data==0) + { + info->status = ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } + info->mpin = u4Data ; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_PIN; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + + sprintf(device_name, "PSU%d_Pout",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == 0){ + info->mpout = u4Data ; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_POUT; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + //get psu Iin/Iout + sprintf(device_name, "PSU%d_Iin",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK){ + info->miin = u4Data ; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_IIN; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + sprintf(device_name, "PSU%d_Iout",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK){ + info->miout = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + //get psu Vin/Vout + sprintf(device_name, "PSU%d_Vin",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK){ + info->mvin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VIN; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + sprintf(device_name, "PSU%d_Vout",local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK){ + info->mvout = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + else{ + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + //get psu model name + if( dni_psui_eeprom_info_get(name, "Product Name" ,local_id ) ==ONLP_STATUS_OK){ + for(i = 0; i< PSU_NUM_LENGTH; i++) + { + name[i]=*(module_name + i ); + } + strcpy(info->model, module_name); + } + else + strcpy(info->model, "ONLP_STATUS_E_UNSUPPORTED"); + //get psu serial number + if(dni_psui_eeprom_info_get(name1, "Product Serial", local_id) ==ONLP_STATUS_OK){ + for(i = 0; i< PSU_NUM_LENGTH; i++) + { + name1[i]=*(module_name1 + i ); + } + strcpy(info->serial, module_name1); + } + else + strcpy(info->serial, "ONLP_STATUS_E_UNSUPPORTED"); + } + else + { int index = ONLP_OID_ID_GET(info->hdr.id); + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_model"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->model, val_char); + + /* Read PSU serial number from attribute */ + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_serial"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->serial, val_char); + + /* Read voltage, current and power */ + if (dni_psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_v_in", &val) == 0) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + if (dni_psu_pmbus_info_get(index, "psu_i_in", &val) == 0) { + info->miin = val; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_in", &val) == 0) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + } + return ONLP_STATUS_OK; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + dev_info_t dev_info; + char device_name[10] = {0}; + UINT4 u4Data = 0; + UINT4 multiplier = 1000; + + VALIDATE(id); + + /* Set the onlp_oid_hdr_t */ + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; + + switch (index) { + case PSU1_ID: + dev_info.bus = 4; + break; + case PSU2_ID: + dev_info.bus = 5; + break; + default: + break; + } + + if(dni_bmc_check() == BMC_ON) + { + /* Check PSU have voltage input or not */ + sprintf(device_name, "PSU%d_Vin", index); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + if(u4Data == 0) + { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; + } + info->mpin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VIN; + } + } + else + { + dev_info.addr = PSU_EEPROM; + dev_info.offset = 0x00; /* In EEPROM address 0x00 */ + dev_info.flags = DEFAULT_FLAG; + + + /* Check PSU have voltage input or not */ + dni_psu_pmbus_info_get(index, "psu_v_in", &val); + + /* Check PSU is PRESENT or not + * Read PSU EEPROM 1 byte from adress 0x00 + * if not present, return Negative value. + */ + if(val == 0 && dni_i2c_lock_read(NULL, &dev_info) < 0) + { + /* Unable to read PSU EEPROM */ + /* Able to read PSU VIN(psu_power_not_good) */ + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } + else if(val == 0){ + /* Unable to read PSU VIN(psu_power_good) */ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } + else { + info->status |= ONLP_PSU_STATUS_PRESENT; + } + } + ret = dni_psu_info_get(id,info); + return ret; + +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..1e3289ec --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,476 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +/******************* Utility Function *****************************************/ + +int sfp_map_bus[] ={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}; + +int +ag9032v2a_get_respond_val(int port){ + int respond_default = 0xff; + int value = 0x00; + int port_select; + if(port > 0 && port <= 32){ + port_select = (port % 8); + + if (port_select==0){ + value = respond_default & (~(1 << 0)); + } + else{ + value = respond_default & (~(1 << (8 - port_select))); + } + return value; + } + else{ + return respond_default; + } +} + +int +ag9032v2a_get_respond_reg(int port){ + uint8_t reg_offset = 0x00; + if (port < 9) + reg_offset = SFP_RESPOND_1; + else if (port > 8 && port < 17) + reg_offset = SFP_RESPOND_2; + else if (port > 16 && port < 25) + reg_offset = SFP_RESPOND_3; + else if (port > 24 && port < 33) + reg_offset = SFP_RESPOND_4; + else + reg_offset = 0x00; + + return reg_offset; +} + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ + +int +onlp_sfpi_init(void){ + /* Called at initialization time */ + lockinit(); + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_map_bus_index(int port) +{ + if(port < 0 || port > 33) + return ONLP_STATUS_E_INTERNAL; + return sfp_map_bus[port-1]; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap){ + /*Ports {1, 33}*/ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 1; p <= NUM_OF_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port){ + char port_data[2]; + int present, present_bit; + + if(port > 0 && port < 34) + { + /* Select QSFP/SFP port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_ERROR("Unable to select port(%d)\r\n", port); + } + + /* Read QSFP/SFP MODULE is present or not */ + present_bit = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH); + if(present_bit < 0){ + AIM_LOG_ERROR("Unable to read present or not from port(%d)\r\n", port); + } + } + + /* From sfp_is_present value, + * return 0 = The module is preset + * return 1 = The module is NOT present + */ + if(present_bit == 0) { + present = 1; + } else if (present_bit == 1) { + present = 0; + AIM_LOG_ERROR("Unble to present status from port(%d)\r\n", port); + } else { + /* Port range over 1-33, return -1 */ + AIM_LOG_ERROR("Error to present status from port(%d)\r\n", port); + present = -1; + } + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + char present_all_data[12] = {'\0'}; + char *r_byte; + char *r_array[4]; + uint8_t bytes[4]; + char port_data[2]; + int count = 0; + uint8_t sfp_presence; + + /* Read presence bitmap from SWPLD QSFP28 Presence Register + * if only port 0 is present, return 7F FF FF FF + * if only port 0 and 1 present, return 3F FF FF FF + */ + if(dni_i2c_read_attribute_string(SFP_IS_PRESENT_ALL_PATH, present_all_data, + sizeof(present_all_data), 0) < 0) { + return -1; + } + + /* String split */ + r_byte = strtok(present_all_data, " "); + while (r_byte != NULL) { + r_array[count++] = r_byte; + r_byte = strtok(NULL, " "); + } + + /* Convert a string to long integer + * and saved into bytes[] + */ + for (count = 0; count < 4; count++) { + bytes[count] = ~strtol(r_array[count], NULL, 16); + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + int j = 31; + uint32_t presence_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap & remap*/ + for(i = 0; presence_all; i++) + { + if(23 < j) + AIM_BITMAP_MOD(dst, (j - 24)+1,(presence_all & 1)); + else if(15 < j && j < 24) + AIM_BITMAP_MOD(dst, (j - 8)+1,(presence_all & 1)); + else if(7 < j && j < 16) + AIM_BITMAP_MOD(dst, (j + 8)+1,(presence_all & 1)); + else + AIM_BITMAP_MOD(dst, (j + 24)+1,(presence_all & 1)); + presence_all >>= 1; + j--; + } + + /* Populate SFP bitmap */ + int port = 33; + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_ERROR("Unable to select port(%d)\r\n", port); + } + sfp_presence = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH);; + + AIM_BITMAP_MOD(dst, 33, !(sfp_presence & 1)); + + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + int sfp_respond_reg; + int sfp_respond_val; + int size = 0; + + /* Get respond register if port have it */ + sfp_respond_reg = ag9032v2a_get_respond_reg(port); + + /* Set respond val */ + sfp_respond_val = ag9032v2a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD1_PATH, sfp_respond_reg, sfp_respond_val); + + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + +} + +int onlp_sfpi_port_map(int port, int* rport) +{ + *rport = port; + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int value_t; + char port_data[2]; + + if(port > 0 && port < 34) + { + /* Select QSFP port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + *value = dni_i2c_lock_read_attribute(NULL, QSFP_RESET_PATH); + /* From sfp_reset value, + * return 0 = The module is in Reset + * return 1 = The module is NOT in Reset + */ + if (*value == 0) + { + *value = 1; + } + else if (*value == 1) + { + *value = 0; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + *value = 0; + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + *value = 0; + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_LP_MODE: + /* From sfp_lp_mode value, + * return 0 = The module is NOT in LP mode + * return 1 = The moduel is in LP mode + */ + *value = dni_i2c_lock_read_attribute(NULL, QSFP_LP_MODE_PATH); + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return value_t; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int value_t; + char port_data[2]; + + if(port > 0 && port < 33) + { + /* Select QSFP port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + sprintf(port_data, "%d", value); + if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_RESET_PATH) < 0){ + AIM_LOG_INFO("Unable to control reset state from port(%d)\r\n", port); + value_t = ONLP_STATUS_E_INTERNAL; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_LP_MODE: + sprintf(port_data, "%d", value); + if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_LP_MODE_PATH) < 0){ + AIM_LOG_INFO("Unable to control LP mode from port(%d)\r\n", port); + value_t = ONLP_STATUS_E_INTERNAL; + } + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return value_t; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); + +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + char port_data[2] ; + + if(port > 0 && port < 33) + { + /* Select QSFP port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + if(port > 0 && port < 33){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + case ONLP_SFP_CONTROL_RX_LOS: + *rv = 0; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + *rv = 0; + break; + case ONLP_SFP_CONTROL_LP_MODE: + if(port > 0 && port < 33){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + default: + break; + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_post_insert(int port, sff_info_t* info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +void +onlp_sfpi_debug(int port, aim_pvs_t* pvs) +{ +} + +int +onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sysi.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..5553286f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,386 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_delta_ag9032v2a_int.h" +#include "x86_64_delta_ag9032v2a_log.h" +#include "platform_lib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int +decide_percentage(int *percentage, int temper) +{ + int level; + + if(temper <= 50) + { + *percentage = 50; + level = 1; + } + else if(temper > 50 && temper <= 55) + { + *percentage = 58; + level = 2; + } + else if(temper > 55 && temper <= 60) + { + *percentage = 65; + level = 3; + } + else if(temper > 60 && temper <= 65) + { + *percentage = 80; + level = 4; + } + else if(temper > 65) + { + *percentage = 100; + level = 5; + } + else + { + *percentage = 100; + level = 6; + } + + return level; +} + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-delta-ag9032v2a-r0"; +} + +int +onlp_sysi_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) + { + if(*size == 256) + { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int cpld_version = 0; + cpld_version = dni_i2c_lock_read_attribute(NULL, CPU_CPLD_VERSION); + pi->cpld_versions = aim_fstrdup("%d", cpld_version); + + return ONLP_STATUS_OK; +} + +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + aim_free(data); +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i = 0; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return ONLP_STATUS_OK; +} +int +onlp_sysi_platform_manage_fans(void) +{ + int i, new_percentage, highest_temp = 0; + onlp_thermal_info_t thermal; + + // if BMC is working, do not control fan + if(dni_bmc_check() == BMC_ON) + return ONLP_STATUS_OK; + + /* Get all thermal current temperature and decide fan percentage */ + for(i = 1; i <= NUM_OF_THERMAL; ++i) + { + if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + + thermal.mcelsius /= 1000; + if(thermal.mcelsius > highest_temp) + { + highest_temp = thermal.mcelsius; + } + + decide_percentage(&new_percentage, highest_temp); + } + + /* Set fantray RPM and PSU fan percentage */ + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_1_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_2_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_3_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_4_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_5_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_6_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_7_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_8_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_9_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_10_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1), new_percentage); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2), new_percentage); + + return ONLP_STATUS_OK; +} +int +onlp_sysi_platform_manage_leds(void) +{ + int fantray_present = -1, rpm = 0, rpm1 = 0, count = 0; + int rv; + int fantray_count; + uint8_t psu_state; + int psu_present_data = 0; + dev_info_t dev_info; + + if( dni_bmc_check()== BMC_ON){ + rv = ONLP_STATUS_OK; + } + else{ + dev_info.offset = 0x00; + dev_info.flags = DEFAULT_FLAG; + + /* Fan tray 1 */ + dev_info.addr = FAN_TRAY_1; + dev_info.bus = I2C_BUS_25; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); + + if(fantray_present >= 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + /* Fan tray 2 */ + dev_info.addr = FAN_TRAY_2; + dev_info.bus = I2C_BUS_24; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); + if(fantray_present >= 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 3 */ + dev_info.addr = FAN_TRAY_3; + dev_info.bus = I2C_BUS_23; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); + + if(fantray_present >= 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 4 */ + dev_info.addr = FAN_TRAY_4; + dev_info.bus = I2C_BUS_22; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); + + if(fantray_present >= 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 5 */ + dev_info.addr = FAN_TRAY_5; + dev_info.bus = I2C_BUS_21; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN5_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN5_REAR); + + if(fantray_present >= 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_5),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_5),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + + /* FRONT FAN & SYS LED */ + for(fantray_count = 0; fantray_count < 5; fantray_count++) + { + dev_info.addr = FAN_TRAY_1 + fantray_count; + dev_info.bus = I2C_BUS_25 - fantray_count; + fantray_present = dni_i2c_lock_read(NULL, &dev_info); + if( fantray_present >= 0) + count++; + } + if(count == ALL_FAN_TRAY_EXIST && dni_fan_speed_good() == FAN_SPEED_NORMALLY) + { + if((onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) || + (onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_SYS),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK)) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Solid Amber FAN or more failed*/ + if((onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) || + (onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_SYS),ONLP_LED_MODE_RED) != ONLP_STATUS_OK)) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Set front light of PWR */ + dev_info.bus = I2C_BUS_4; + dev_info.offset = 0x00; + dev_info.flags = DEFAULT_FLAG; + dev_info.addr = PSU_EEPROM; + psu_state = dni_i2c_lock_read(NULL, &dev_info); + psu_present_data = dni_lock_cpld_read_attribute(SWPLD1_PATH,POWER_STATUS_REGISTER); + + if(psu_state == 1 && (psu_present_data & 0x60) == 0x60) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR1), ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR1), ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + dev_info.bus = I2C_BUS_5; + + psu_state = dni_i2c_lock_read(NULL, &dev_info); + + if(psu_state == 1 && (psu_present_data & 0x06) == 0x06) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR2), ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR2), ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + rv = ONLP_STATUS_OK; + } + + return rv; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/thermali.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..6be39008 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,203 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ + +#include "platform_lib.h" +#include +#include +#include "x86_64_delta_ag9032v2a_log.h" + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define dni_onlp_thermal_threshold(WARNING_DEFAULT, ERROR_DEFAULT, SHUTDOWN_DEFAULT){ \ + WARNING_DEFAULT, \ + ERROR_DEFAULT, \ + SHUTDOWN_DEFAULT, \ +} +static char* path[] = /* must map with onlp_thermal_id */ +{ + "reserved", + NULL, /* CPU Core */ + "27-004f/hwmon/hwmon7/temp1_input", + "8-004c/hwmon/hwmon1/temp1_input", + "8-004d/hwmon/hwmon2/temp1_input", + "8-004e/hwmon/hwmon3/temp1_input", + "8-004f/hwmon/hwmon4/temp1_input", + "4-0058/psu_temp1_input", + "5-0058/psu_temp1_input", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp1_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp2_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp3_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp4_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_WIND_ON_ADAPTER_BOARD), "Wind thermal sensor", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BOARD), "MAC up side thermal sensor", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BOARD), "MAC down side thermal sensor", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BOARD), "Surroundings thermal sensor", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_CPU_BOARD), "ON CPU BOARD", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + uint8_t local_id = 0; + UINT4 multiplier = 1000; + UINT4 u4Data = 0; + char device_buf[20] = {0}; + int temp_base = 1; + + int rv; + char fullpath[50] = {0}; + int r_data = 0; + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + if(local_id == THERMAL_4_ON_CPU_BOARD) { + rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + if(dni_bmc_check()==BMC_ON) + { + switch(local_id) + { + case THERMAL_WIND_ON_ADAPTER_BOARD: + case THERMAL_1_ON_MAIN_BOARD: + case THERMAL_2_ON_MAIN_BOARD: + case THERMAL_3_ON_MAIN_BOARD: + case THERMAL_4_ON_CPU_BOARD: + sprintf(device_buf, "Sensor_Temp_%d", local_id); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + case THERMAL_5_ON_PSU1: + sprintf(device_buf, "PSU1_Temp_1"); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + case THERMAL_6_ON_PSU2: + sprintf(device_buf, "PSU2_Temp_1"); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + default: + AIM_LOG_ERROR("Invalid Thermal ID!!\n"); + return ONLP_STATUS_E_PARAM; + } + + if (u4Data == 0 || rv == ONLP_STATUS_E_GENERIC){ + return ONLP_STATUS_E_INTERNAL; + } + else{ + info->mcelsius = u4Data; + return 0; + } + } + else + { + switch (local_id) + { + case THERMAL_WIND_ON_ADAPTER_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_1_ON_MAIN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_2_ON_MAIN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_3_ON_MAIN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_4_ON_CPU_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_5_ON_PSU1: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_6_ON_PSU2: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + } + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + info->mcelsius = r_data / temp_base; + } + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_config.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_config.c new file mode 100755 index 00000000..d2788126 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_config.c @@ -0,0 +1,91 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(_x) __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(_x) +x86_64_delta_ag9032v2a_config_settings_t x86_64_delta_ag9032v2a_config_settings[] = +{ +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_LOGGING(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_PORTING_STDLIB(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_SFP_COUNT(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX + { __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME(X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX), __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE(X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX) }, +#else +{ X86_64_DELTA_AG9032V2A_CONFIG_FAN_RPM_MAX(__x86_64_delta_ag9032v2a_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_delta_ag9032v2a_config_STRINGIFY_VALUE +#undef __x86_64_delta_ag9032v2a_config_STRINGIFY_NAME + +const char* +x86_64_delta_ag9032v2a_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_delta_ag9032v2a_config_settings[i].name; i++) { + if(!strcmp(x86_64_delta_ag9032v2a_config_settings[i].name, setting)) { + return x86_64_delta_ag9032v2a_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_delta_ag9032v2a_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_delta_ag9032v2a_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_delta_ag9032v2a_config_settings[i].name, x86_64_delta_ag9032v2a_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_enums.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_enums.c new file mode 100644 index 00000000..94a68562 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_int.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_int.h new file mode 100644 index 00000000..be7ebcd2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_delta_ag9032v2a Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_ag9032v2a_INT_H__ +#define __x86_64_delta_ag9032v2a_INT_H__ + +#include + + +#endif /* __x86_64_delta_ag9032v2a_INT_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.c new file mode 100755 index 00000000..9689269f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_ag9032v2a_log.h" +/* + * x86_64_delta_ag9032v2a log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_DELTA_AG9032V2A_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_DELTA_AG9032V2A_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_DELTA_AG9032V2A_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.h b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.h new file mode 100644 index 00000000..012e66f4 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_delta_ag9032v2a_LOG_H__ +#define __x86_64_delta_ag9032v2a_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_delta_ag9032v2a +#include + +#endif /* __x86_64_delta_ag9032v2a_LOG_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_module.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_module.c new file mode 100644 index 00000000..b956515d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_ag9032v2a_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_delta_ag9032v2a_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_delta_ag9032v2a_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_ucli.c b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_ucli.c new file mode 100755 index 00000000..788fa2c9 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/onlp/builds/src/module/src/x86_64_delta_ag9032v2a_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_DELTA_AG9032V2A_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_delta_ag9032v2a_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_delta_ag9032v2a) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_delta_ag9032v2a_ucli_module__ = + { + "x86_64_delta_ag9032v2a_ucli", + NULL, + x86_64_delta_ag9032v2a_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_delta_ag9032v2a_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_delta_ag9032v2a_ucli_module__); + n = ucli_node_create("x86_64_delta_ag9032v2a", NULL, &x86_64_delta_ag9032v2a_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_delta_ag9032v2a")); + return n; +} + +#else +void* +x86_64_delta_ag9032v2a_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/PKG.yml new file mode 100644 index 00000000..e1ea5c10 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/PKG.yml @@ -0,0 +1,2 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=delta BASENAME=x86-64-delta-ag9032v2a REVISION=r0 + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/lib/x86-64-delta-ag9032v2a-r0.yml b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/lib/x86-64-delta-ag9032v2a-r0.yml new file mode 100755 index 00000000..e48eb520 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/lib/x86-64-delta-ag9032v2a-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AG9032V2A +# +###################################################################### + +x86-64-delta-ag9032v2a-r0: + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-9 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/python/x86_64_delta_ag9032v2a_r0/__init__.py b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/python/x86_64_delta_ag9032v2a_r0/__init__.py new file mode 100644 index 00000000..17611ffc --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ag9032v2a/platform-config/r0/src/python/x86_64_delta_ag9032v2a_r0/__init__.py @@ -0,0 +1,30 @@ +from onl.platform.base import * +from onl.platform.delta import * + +class OnlPlatform_x86_64_delta_ag9032v2a_r0(OnlPlatformDelta, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-delta-ag9032v2a-r0' + MODEL="AG9032V2A" + SYS_OBJECT_ID=".9032.2.1" + + + def baseconfig(self): + #Check cpld default data + os.system("i2cset -y 0 0x31 0x14 0xfd") + os.system("echo 1 > /sys/bus/i2c/devices/i2c-0/firmware_node/physical_node/remove") + os.system("echo 1 > /sys/bus/pci/rescan") + + #insert sfp module + self.insmod('delta_ag9032v2a_platform') + + #Insert psu module + self.insmod('dni_ag9032v2a_psu') + + #insert fan module + self.insmod('dni_emc2305') + + #insert qsfp mosule + self.insmod('optoe') + + return True + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/PKG.yml new file mode 100644 index 00000000..bd7254d1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=delta BASENAME=x86-64-delta-agc7648sv1 ARCH=amd64 KERNELS="onl-kernel-4.9-lts-x86-64-all:amd64" diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/Makefile new file mode 100644 index 00000000..6656aa61 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/Makefile @@ -0,0 +1,7 @@ +KERNELS := onl-kernel-4.9-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := delta +BASENAME := x86-64-delta-agc7648sv1 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/delta_agc7648sv1_platform.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/delta_agc7648sv1_platform.c new file mode 100755 index 00000000..58d0cdf1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/delta_agc7648sv1_platform.c @@ -0,0 +1,3370 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPUPLD_ADDR 0x31 +#define SWPLD1_ADDR 0x6a +#define SWPLD2_ADDR 0x75 +#define SWPLD3_ADDR 0x73 +#define DEFAULT_CPLD 0 + +#define MUX_VAL_SERDES_SWPLD3 0xFF +#define MUX_VAL_IDEEPROM 0xFC +#define MUX_VAL_PCA9547 0xFD + +#define MUX_VAL_FAN1_EEPROM 0x00 +#define MUX_VAL_FAN2_EEPROM 0x01 +#define MUX_VAL_FAN3_EEPROM 0x02 +#define MUX_VAL_FAN4_EEPROM 0x03 +#define MUX_VAL_FAN_CTL 0x05 +#define MUX_VAL_FAN_TMP75 0x06 +#define MUX_VAL_FAN_IO_CTL 0x07 + +#define MUX_VAL_PSU1 0x00 +#define MUX_VAL_PSU2 0x02 + +#define DEF_DEV_NUM 1 +#define BUS0_DEV_NUM 3 +#define BUS0_BASE_NUM 1 +#define BUS0_MUX_REG 0x14 + +#define BUS2_QSFP_DEV_NUM 6 +#define BUS2_QSFP_BASE_NUM 41 +#define BUS2_QSFP_MUX_REG 0x20 +#define BUS2_SFP_DEV_NUM 48 +#define BUS2_SFP_BASE_NUM 51 +#define BUS2_SFP_MUX_REG 0x21 +#define BUS5_DEV_NUM 7 +#define BUS5_BASE_NUM 21 +#define BUS5_MUX_REG 0x67 + +#define BUS6_DEV_NUM 2 +#define BUS6_BASE_NUM 31 +#define BUS6_MUX_REG 0x1f + +/* on SWPLD3 */ +#define SWPLD3_SFP_CH1_EN 0x00 +#define SWPLD3_SFP_CH2_EN 0x01 +#define SWPLD3_SFP_CH3_EN 0x02 +#define SWPLD3_SFP_CH4_EN 0x03 +#define SWPLD3_SFP_CH5_EN 0x04 +#define SWPLD3_SFP_CH6_EN 0x05 +#define SWPLD3_QSFP_CH_EN 0x06 +#define SWPLD3_SFP_CH_DISABLE 0x07 + +#define SWPLD3_SFP_PORT_9 9 +#define SWPLD3_SFP_PORT_19 19 +#define SWPLD3_SFP_PORT_29 29 +#define SWPLD3_SFP_PORT_39 39 +#define SWPLD3_SFP_PORT_48 48 + +/* on SWPLD2 */ +#define SFP_PRESENCE_1 0x30 +#define SFP_PRESENCE_2 0x31 +#define SFP_PRESENCE_3 0x32 +#define SFP_PRESENCE_4 0x33 +#define SFP_PRESENCE_5 0x34 +#define SFP_PRESENCE_6 0x35 +#define SFP_RXLOS_1 0x36 +#define SFP_RXLOS_2 0x37 +#define SFP_RXLOS_3 0x38 +#define SFP_RXLOS_4 0x39 +#define SFP_RXLOS_5 0x3A +#define SFP_RXLOS_6 0x3B +#define SFP_TXDIS_1 0x3C +#define SFP_TXDIS_2 0x3D +#define SFP_TXDIS_3 0x3E +#define SFP_TXDIS_4 0x3F +#define SFP_TXDIS_5 0x40 +#define SFP_TXDIS_6 0x41 +#define SFP_TXFAULT_1 0x42 +#define SFP_TXFAULT_2 0x43 +#define SFP_TXFAULT_3 0x44 +#define SFP_TXFAULT_4 0x45 +#define SFP_TXFAULT_5 0x46 +#define SFP_TXFAULT_6 0x47 + +/* on SWPLD1 */ +#define QSFP_PRESENCE 0x63 +#define QSFP_LPMODE 0x62 +#define QSFP_RESET 0x3c + +#define SWPLD1_QSFP_MODSEL_REG 0x64 +#define SWPLD1_QSFP_MODSEL_VAL 0x3f + +/* BMC IMPI CMD */ +#define IPMI_MAX_INTF (4) +#define DELTA_NETFN 0x38 +#define CMD_SETDATA 0x03 +#define CMD_GETDATA 0x02 +#define CMD_DIAGMODE 0x1a +#define BMC_DIAG_STATE 0x00 +#define BMC_ERR (-6) +#define BMC_NOT_EXIST 0xc1 +#define BMC_SWPLD_BUS 2 + + +/* Check cpld read results */ +#define VALIDATED_READ(_buf, _rv, _read, _invert) \ + do { \ + _rv = _read; \ + if (_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if (_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) \ + +struct mutex dni_lock; + +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 int dni_bmc_exist_check(void); +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 +}; + +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); + +int dni_bmc_exist_check(void) +{ + uint8_t set_cmd; + uint8_t cmd_data[1] = {0}; + int cmd_data_len, rv = 0; + + set_cmd = CMD_DIAGMODE; + cmd_data[0] = BMC_DIAG_STATE; + cmd_data_len = sizeof(cmd_data); + rv = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + return rv; +} +EXPORT_SYMBOL(dni_bmc_exist_check); + +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); + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, +}; + +#define agc7648sv1_i2c_device_num(NUM){ \ + .name = "delta-agc7648sv1-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &agc7648sv1_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +static struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[350]; +}; + +enum cpld_type { + system_cpld, +}; + +enum swpld1_type { + swpld1, +}; + +enum swpld2_type { + swpld2, +}; + +enum swpld3_type { + swpld3, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum cpld_attributes { +//CPLDs address and value + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD1_REG_ADDR, + SWPLD1_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, +//CPLD + CPU_BOARD_ID1, + CPU_BOARD_ID2, + BOARD_VER, + CPULD_VER, + CPU_SYS_PWR_OK, + PLAT_RST, + CPLD_VR_HOT, + CPU_OVER_TMP, + DDR_OVER_TMP, + CPU_PWR_RST, + CPU_HARD_RST, + CPLD_RST, + MB_PWR_ENABLE, + MB_PWR_PGD, + MB_RST_DONE, + MB_RST, + EEPROM_WP, + PSU_FAN_EVENT, + CPU_I2C_MUX_EN, + CPU_I2C_MUX_SEL, +//SWPLD1 + BOARD_ID, + BCM88375_RST, + B54616S_RST, + PSU1_EN, + PSU2_EN, + PSU1_PWR_FAN_OK, + PSU2_PWR_FAN_OK, + PSU2_PRESENT, + PSU1_PRESENT, + PSU2_PWR_INT, + PSU1_PWR_INT, + BCM88375_INT, + BCM54616S_IRQ, + LED_SYS, + LED_PWR, + LED_FAN, + PSU_I2C_SEL, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN_I2C_SEL, +//SWPLD3 + QSFP_I2C_SEL, + SFP_CHAN_EN, + SFP_SEL, +}; + +enum agc7648sv1_sfp_sysfs_attributes +{ + SFP_SELECT_PORT, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_RESET, + SFP_RX_LOS, + SFP_RX_LOS_ALL, + SFP_TX_DISABLE, + SFP_TX_FAULT +}; + +static struct cpld_attribute_data attribute_data[] = { +//CPLDs address and value + [CPLD_REG_ADDR] = { + }, + [CPLD_REG_VALUE] = { + }, + [SWPLD1_REG_ADDR] = { + }, + [SWPLD1_REG_VALUE] = { + }, + [SWPLD2_REG_ADDR] = { + }, + [SWPLD2_REG_VALUE] = { + }, + [SWPLD3_REG_ADDR] = { + }, +//CPLD + [CPU_BOARD_ID1] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x00, .mask = 0xff, + .note = "Configured by PLD editor.\n0x15 : BROADWELL D-1527" + }, + [CPU_BOARD_ID2] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x01, .mask = 0xff, + .note = "Configured by PLD editor.\n0x27 : BROADWELL D-1527" + }, + [BOARD_VER] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0xff, + .note = "Controlled by external resistors.\n0x00: EVT1\n0x01: EVT2\n0x02: EVT3\n0x03: EVT4\n0x10: DVT1\n0x11: DVT2\n0x20: PVT1" + }, + [CPULD_VER] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x03, .mask = 0xff, + .note = "CPLD Version, controlled by CPLD editor." + }, + [CPU_SYS_PWR_OK] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x06, .mask = 1 << 2, + .note = "Indicate CPU that System Power is OK.\n\"1\" = System Power is OK\n\"0\" = System Power is not OK" + }, + [PLAT_RST] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x09, .mask = 1 << 4, + .note = "Indicate Platform Reset.\n\"1\" = Platform Reset\n\"0\" = Platform Not Reset" + }, + [CPLD_VR_HOT] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 3, + .note = "Indicate Power Rail Over temperature\n\"1\" = Not over temperature\n\"0\" = Over temperature" + }, + [CPU_OVER_TMP] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 1, + .note = "CPU Disomic temperature sensor\n\"1\" = Not over temperature.\n\"0\" = Over temperature." + }, + [DDR_OVER_TMP] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 0, + .note = "DDR over temperature sensor\n\"1\" = Not over temperature.\n\"0\" = Over temperature." + }, + [CPU_PWR_RST] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 4, + .note = "Software execute the CPU Power On reset\n\"0\" = Reset\n\"1\" = Normal operation" + }, + [CPU_HARD_RST] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 2, + .note = "Software execute the CPU Hard reset\n\"0\" = Reset\n\"1\" = Normal operation" + }, + [CPLD_RST] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 0, + .note = "Software reset the CPLD system\n\"0\" = Reset\n\"1\" = Normal operation" + }, + [MB_PWR_ENABLE] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 3, + .note = "Software Enable Main board Power\n\"0\" = Disable.\n\"1\" = Enable." + }, + [MB_PWR_PGD] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 2, + .note = "Indicate the Main board all power good\n\"0\" = Power rail is failed\n\"1\" = Power rail is good" + }, + [MB_RST_DONE] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 1, + .note = "Main board reset done.\n\"0\" = Reset\n\"1\" = Normal operation" + }, + [MB_RST] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 0, + .note = "Software reset Main board\n\"0\" = Reset\n\"1\" = Normal operation" + }, + [EEPROM_WP] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x14, .mask = 1 << 3, + .note = "ID EEPROM Write Protect\n\"1\" = enables the lock-down mechanism.\n\"0\" = overrides the lock-down function enabling blocks to be erased or programmed using software commands." + }, + [PSU_FAN_EVENT] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 1, + .note = "Indicate the PSU Fan interrupt occurs or not.\n\"0\" = Interrupt occurs\n\"1\" = Interrupt doesn't occur" + }, + [CPU_I2C_MUX_EN] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x14, .mask = 1 << 2, + .note = "CPU I2C MUX Enable\n\"0\" = Enable CPU I2C MUX\n\"1\" = Disable CPU I2C MUX" + }, + [CPU_I2C_MUX_SEL] = { + .bus = BUS3, .addr = CPUPLD_ADDR, + .reg = 0x14, .mask = 0x03, + .note = "CPU I2C MUX Selection\n\"0x00\" = CPUBD devices\n\"0x01\" = SWBD devices\n\"0x02\" = SWPLDs\n\"0x03\" = QSFP-DD module devices" + }, +//SWPLD1 + [BOARD_ID] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x00, .mask = 0xf0, + .note = "SW Board ID\n\"0000\": AGC7648." + }, + [BCM88375_RST] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x04, .mask = 1 << 6, + .note = "software Reset for MAC\n\"0\" = Reset.\n\"1\" = Normal Operation." + }, + [B54616S_RST] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x04, .mask = 1 << 5, + .note = "Software Reset for PHY\n\"0\" = Reset.\n\"1\" = Normal Operation." + }, + [PSU1_EN] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x08, .mask = 1 << 7, + .note = "Enable/Disable the Power Supply 1\n\"0\" = Enabled.\n\"1\" = Disabled." + }, + [PSU2_EN] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x08, .mask = 1 << 6, + .note = "Enable/Disable the Power Supply 2\n\"0\" = Enabled.\n\"1\" = Disabled." + }, + [PSU1_PWR_FAN_OK] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0b, .mask = 1 << 7, + .note = "Indicate the Power Supply 1 power good\n\"1\" = Power rail is good\n\"0\" = Power rail is failed" + }, + [PSU2_PWR_FAN_OK] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0b, .mask = 1 << 6, + .note = "Indicate the Power Supply 2 power good\n\"1\" = Power rail is good\n\"0\" = Power rail is failed" + }, + [PSU2_PRESENT] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0d, .mask = 1 << 1, + .note = "Indicate PSU2 present or not.\n\"0\" = YES.\n\"1\" = NO." + }, + [PSU1_PRESENT] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0d, .mask = 1 << 0, + .note = "Indicate PSU1 present or not.\n\"0\" = YES.\n\"1\" = NO." + }, + [PSU2_PWR_INT] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0e, .mask = 1 << 5, + .note = "Indicate the PSU2 interrupt occurs or not.\n\"0\" = Interrupt occurs\n\"1\" = Interrupt doesn't occur" + }, + [PSU1_PWR_INT] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0e, .mask = 1 << 4, + .note = "Indicate the PSU1 interrupt occurs or not.\n\"0\" = Interrupt occurs\n\"1\" = Interrupt doesn't occur" + }, + [BCM88375_INT] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x0e, .mask = 1 << 3, + .note = "Indicate BCM88375 Interrupt occurs or not.\n\"0\" = Interrupt occurs\n\"1\" = Interrupt doesn't occur" + }, + [BCM54616S_IRQ] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x16, .mask = 1 << 7, + .note = "Indicate the BCM54616S interrupt occurs or not.\n\"0\" = Interrupt occurs\n\"1\" = Interrupt doesn't occur" + }, + [LED_SYS] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x1c, .mask = 0xf0, + .note = "\"0x00\"= Off (No Power)\n\"0x01\"= Solid Amber(System Fault)\n\"0x02\"= Solid Green(System Normal Operation)\n\"0x05\"= Blinking Green(1/4S)(System Booting)\n\"0x06\"= Blinking Amber(1/4S)\n\"0x09\"= Blinking Green(1/2S)\n\"0x0A\"= Blinking Amber(1/2S)\n\"0x0D\"= Blinking Green(1S)\n\"0x0E\"= Blinking Amber(1S)" + }, + [LED_PWR] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x1c, .mask = 0x0c, + .note = "\"0x00\"= Off (No Power)\n\"0x01\"= Solid Green(PSU Normal Operation)\n\"0x02\"= Solid Amber(POST in progress)\n\"0x03\"= (Not define)" + }, + [LED_FAN] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x1c, .mask = 0x03, + .note = "\"0x00\"= Off (No Power)\n\"0x01\"= Solid Green(Fan Normal Operation)\n\"0x02\"= Solid Amber(Fan not present)\n\"0x03\"= Blinking Amber(Fan failed)" + }, + [PSU_I2C_SEL] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x1f, .mask = 0x03, + .note = "FAN I2C channel selection\n\"0x00\" = PS1 EEPROM\n\"0x01\" = PS1 HOT SWAP IC\n\"0x02\" = PS2 EEPROM\n\"0x03\" = PS2 HOT SWAP IC\n" + }, + [FAN1_LED] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x65, .mask = 0xc0, + .note = "Indicate the FAN Tray 1 LED status\n\"0x00\" = Off\n\"0x01\" = Solid Green.\n\"0x02\" = Solid Red.\n\"0x03\" = Off\n" + }, + [FAN2_LED] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x65, .mask = 0x30, + .note = "Indicate the FAN Tray 2 LED status\n\"0x00\" = Off\n\"0x01\" = Solid Green.\n\"0x02\" = Solid Red.\n\"0x03\" = Off\n" + }, + [FAN3_LED] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x65, .mask = 0x0c, + .note = "Indicate the FAN Tray 3 LED status\n\"0x00\" = Off\n\"0x01\" = Solid Green.\n\"0x02\" = Solid Red.\n\"0x03\" = Off\n" + }, + [FAN4_LED] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x65, .mask = 0x03, + .note = "Indicate the FAN Tray 4 LED status\n\"0x00\" = Off\n\"0x01\" = Solid Green.\n\"0x02\" = Solid Red.\n\"0x03\" = Off\n" + }, + [FAN_I2C_SEL] = { + .bus = BUS7, .addr = SWPLD1_ADDR, + .reg = 0x67, .mask = 0x07, + .note = "FAN I2C channel selection\n\"0x00\" = FAN TRAY 1 EEPROM\n\"0x01\" = FAN TRAY 2 EEPROM\n\"0x02\" = FAN TRAY 3 EEPROM\n\"0x03\" = FAN TRAY 4 EEPROM\n\"0x04\" = Reserved;(Do not use)\n\"0x05\" = FAN Control IC (EMC2305)\n\"0x06\" = FAN Thermal Sensor (TMP75A)\n\"0x07\" = FAN IO Control (PCA9555DB)" + }, +//SWPLD3 + [QSFP_I2C_SEL] = { + .bus = BUS7, .addr = SWPLD3_ADDR, + .reg = 0x20, .mask = 0x07, + .note = "QSFP28 I2C channel selection.\n\"0x00\" : QSFP28 Port 0\n\"0x01\" : QSFP28 Port 1\n\"0x02\" : QSFP28 Port 2\n\"0x03\" : QSFP28 Port 3\n\"0x04\" : QSFP28 Port 4\n\"0x05\" : QSFP28 Port 5" + }, + [SFP_CHAN_EN] = { + .bus = BUS7, .addr = SWPLD3_ADDR, + .reg = 0x21, .mask = 0x70, + .note = "SFP+ I2C Nth channel and QSFP channel enable index\n\"0x00\": means SFP+ N=0 and 1th channel enable.\n\"0x01\": means SFP+ N=1 and 2th channel enable.\n ...\n\"0x05\": means SFP+ N=5 and 6th channel enable.\n\"0x06\": means QSFP channel enable.\n\"0x07\": Disable all channels." + }, + [SFP_SEL] = { + .bus = BUS7, .addr = SWPLD3_ADDR, + .reg = 0x21, .mask = 0x07, + .note = "SFP+ I2C Mth selection. (From PORT1 ~ PORT48)\n\"0x00\": means M=0.\n\"0x01\": means M=1.\n...\n\"0x07\": means M=7\nSFP I2C Channel Number = 8 * N + M +1" + }, +}; + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +struct i2c_client * i2c_client_9547; + +static struct cpld_platform_data agc7648sv1_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = CPUPLD_ADDR, + }, +}; + +static struct cpld_platform_data agc7648sv1_swpld1_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, +}; + +static struct cpld_platform_data agc7648sv1_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data agc7648sv1_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +// pca9548 - add 8 bus +static struct pca954x_platform_mode pca954x_mode[] = +{ + { + .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, + }, + { + .adap_id = 10, + .deselect_on_exit = 1, + }, + { + .adap_id = 11, + .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, + }, +}; + +/* ---------------- IPMI - start ------------- */ +int dni_create_user(void) +{ + int rv, i; + + for (i = 0, rv = 1; i < IPMI_MAX_INTF && rv; i++) + { + rv = ipmi_create_user(i, &ipmi_hndlrs, NULL, &ipmi_mh_user); + } + if(rv == 0) + { + printk("Enable IPMI protocol.\n"); + return rv; + } +} +EXPORT_SYMBOL(dni_create_user); + +int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len) +{ + int rv; + struct ipmi_system_interface_addr addr; + struct kernel_ipmi_msg msg; + struct completion comp; + + addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + addr.channel = IPMI_BMC_CHANNEL; + addr.lun = 0; + + msg.netfn = DELTA_NETFN; + msg.cmd = set_cmd; + msg.data_len = cmd_data_len; + msg.data = cmd_data; + + init_completion(&comp); + rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0, &msg, &comp, &halt_smi_msg, &halt_recv_msg, 0); + if(rv) + return BMC_ERR; + + wait_for_completion(&comp); + + switch(msg.cmd) + { + case CMD_GETDATA: + if(rv == 0) + return halt_recv_msg.msg.data[1]; + else + { + printk(KERN_ERR "IPMI get error!\n"); + return BMC_ERR; + } + break; + case CMD_SETDATA: + if(rv == 0) + return rv; + else + { + printk(KERN_ERR "IPMI set error!\n"); + return BMC_ERR; + } + case CMD_DIAGMODE: + if(rv == 0 && (halt_recv_msg.msg.data[0] != BMC_NOT_EXIST)) + return halt_recv_msg.msg.data[1]; + else + { + printk(KERN_ERR "BMC is not exist!\n"); + return BMC_ERR; + } + } + + ipmi_free_recv_msg(&halt_recv_msg); + + return rv; +} +EXPORT_SYMBOL(dni_bmc_cmd); +/* ---------------- IPMI - stop ------------- */ + +/* ---------------- I2C device - start ------------- */ +static struct i2c_device_platform_data agc7648sv1_i2c_device_platform_data[] = { + { + // id eeprom + .parent = 1, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4b) }, + .client = NULL, + }, + { + // tmp431 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp431", 0x4c) }, + .client = NULL, + }, + { + // tmp432 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp432", 0x4d) }, + .client = NULL, + }, + { + // tmp75 + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + // tmp75 cpu + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + // fan control 1 + .parent = 25, + .info = { I2C_BOARD_INFO("emc2305", 0x2c) }, + .client = NULL, + }, + { + // fan control 2 + .parent = 25, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + // tmp75 fan + .parent = 26, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + // fan IO CTRL + .parent = 27, + .info = { I2C_BOARD_INFO("pca9555", 0x27) }, + .client = NULL, + }, + { + // PSU 1 eeprom + .parent = 31, + .info = { I2C_BOARD_INFO("24c02", 0x50) }, + .client = NULL, + }, + { + // PSU 2 eeprom + .parent = 32, + .info = { I2C_BOARD_INFO("24c02", 0x50) }, + .client = NULL, + }, + { + // PSU 1 control + .parent = 31, + .info = { I2C_BOARD_INFO("dni_agc7648sv1_psu", 0x58) }, + .client = NULL, + }, + { + // PSU 2 control + .parent = 32, + .info = { I2C_BOARD_INFO("dni_agc7648sv1_psu", 0x58) }, + .client = NULL, + }, + { + // qsfp 1 (0x50) + .parent = 41, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 2 (0x50) + .parent = 42, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 3 (0x50) + .parent = 43, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 4 (0x50) + .parent = 44, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 5 (0x50) + .parent = 45, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 6 (0x50) + .parent = 46, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 1 (0x50) + .parent = 51, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 2 (0x50) + .parent = 52, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 3 (0x50) + .parent = 53, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 4 (0x50) + .parent = 54, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 5 (0x50) + .parent = 55, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 6 (0x50) + .parent = 56, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 7 (0x50) + .parent = 57, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 8 (0x50) + .parent = 58, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 9 (0x50) + .parent = 59, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 10 (0x50) + .parent = 60, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 11 (0x50) + .parent = 61, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 12 (0x50) + .parent = 62, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 13 (0x50) + .parent = 63, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 14 (0x50) + .parent = 64, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 15 (0x50) + .parent = 65, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 16 (0x50) + .parent = 66, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 17 (0x50) + .parent = 67, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 18 (0x50) + .parent = 68, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 19 (0x50) + .parent = 69, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 20 (0x50) + .parent = 70, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 21 (0x50) + .parent = 71, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 22 (0x50) + .parent = 72, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 23 (0x50) + .parent = 73, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 24 (0x50) + .parent = 74, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 25 (0x50) + .parent = 75, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 26 (0x50) + .parent = 76, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 27 (0x50) + .parent = 77, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 28 (0x50) + .parent = 78, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 29 (0x50) + .parent = 79, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 30 (0x50) + .parent = 80, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 31 (0x50) + .parent = 81, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 32 (0x50) + .parent = 82, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 33 (0x50) + .parent = 83, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 34 (0x50) + .parent = 84, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 35 (0x50) + .parent = 85, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 36 (0x50) + .parent = 86, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 37 (0x50) + .parent = 87, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 38 (0x50) + .parent = 88, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 39 (0x50) + .parent = 89, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 40 (0x50) + .parent = 90, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 41 (0x50) + .parent = 91, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 42 (0x50) + .parent = 92, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 43 (0x50) + .parent = 93, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 44 (0x50) + .parent = 94, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 45 (0x50) + .parent = 95, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 46 (0x50) + .parent = 96, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 47 (0x50) + .parent = 97, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 48 (0x50) + .parent = 98, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct platform_device agc7648sv1_i2c_device[] = { + agc7648sv1_i2c_device_num(0), + agc7648sv1_i2c_device_num(1), + agc7648sv1_i2c_device_num(2), + agc7648sv1_i2c_device_num(3), + agc7648sv1_i2c_device_num(4), + agc7648sv1_i2c_device_num(5), + agc7648sv1_i2c_device_num(6), + agc7648sv1_i2c_device_num(7), + agc7648sv1_i2c_device_num(8), + agc7648sv1_i2c_device_num(9), + agc7648sv1_i2c_device_num(10), + agc7648sv1_i2c_device_num(11), + agc7648sv1_i2c_device_num(12), + agc7648sv1_i2c_device_num(13), + agc7648sv1_i2c_device_num(14), + agc7648sv1_i2c_device_num(15), + agc7648sv1_i2c_device_num(16), + agc7648sv1_i2c_device_num(17), + agc7648sv1_i2c_device_num(18), + agc7648sv1_i2c_device_num(19), + agc7648sv1_i2c_device_num(20), + agc7648sv1_i2c_device_num(21), + agc7648sv1_i2c_device_num(22), + agc7648sv1_i2c_device_num(23), + agc7648sv1_i2c_device_num(24), + agc7648sv1_i2c_device_num(25), + agc7648sv1_i2c_device_num(26), + agc7648sv1_i2c_device_num(27), + agc7648sv1_i2c_device_num(28), + agc7648sv1_i2c_device_num(29), + agc7648sv1_i2c_device_num(30), + agc7648sv1_i2c_device_num(31), + agc7648sv1_i2c_device_num(32), + agc7648sv1_i2c_device_num(33), + agc7648sv1_i2c_device_num(34), + agc7648sv1_i2c_device_num(35), + agc7648sv1_i2c_device_num(36), + agc7648sv1_i2c_device_num(37), + agc7648sv1_i2c_device_num(38), + agc7648sv1_i2c_device_num(39), + agc7648sv1_i2c_device_num(40), + agc7648sv1_i2c_device_num(41), + agc7648sv1_i2c_device_num(42), + agc7648sv1_i2c_device_num(43), + agc7648sv1_i2c_device_num(44), + agc7648sv1_i2c_device_num(45), + agc7648sv1_i2c_device_num(46), + agc7648sv1_i2c_device_num(47), + agc7648sv1_i2c_device_num(48), + agc7648sv1_i2c_device_num(49), + agc7648sv1_i2c_device_num(50), + agc7648sv1_i2c_device_num(51), + agc7648sv1_i2c_device_num(52), + agc7648sv1_i2c_device_num(53), + agc7648sv1_i2c_device_num(54), + agc7648sv1_i2c_device_num(55), + agc7648sv1_i2c_device_num(56), + agc7648sv1_i2c_device_num(57), + agc7648sv1_i2c_device_num(58), + agc7648sv1_i2c_device_num(59), + agc7648sv1_i2c_device_num(60), + agc7648sv1_i2c_device_num(61), + agc7648sv1_i2c_device_num(62), + agc7648sv1_i2c_device_num(63), + agc7648sv1_i2c_device_num(64), + agc7648sv1_i2c_device_num(65), + agc7648sv1_i2c_device_num(66), + agc7648sv1_i2c_device_num(67), +}; +/* ---------------- 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-agc7648sv1-i2c-device", + } +}; +/* ---------------- I2C driver - end ------------- */ + +/* ---------------- SFP attribute read/write - start -------- */ +long sfp_port_data = 0; +static struct kobject *kobj_cpld; +static struct kobject *kobj_swpld1; +static struct kobject *kobj_swpld2; +static struct kobject *kobj_swpld3; + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf){ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld1); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld2); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + long port_t = 0; + u8 reg_t = 0x00; + int values[7] = {'\0'}; + int bit_t = 0x00; + mutex_lock(&dni_lock); + + switch (attr->index) { + case SFP_IS_PRESENT: + port_t = sfp_port_data; + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_PRESENCE_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_PRESENCE_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_PRESENCE_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_PRESENCE_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_PRESENCE_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_PRESENCE_6; + } else if (port_t > 48 && port_t < 55) { /* QSFP Port 1-6 */ + reg_t = QSFP_PRESENCE; + } else { + values[0] = 1; /* return 1, module NOT present */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 48 && port_t < 55) { /* QSFP */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + mutex_unlock(&dni_lock); + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + } + else { /* SFP */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata2[swpld2].client, reg_t), 0); + mutex_unlock(&dni_lock); + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + } + + /* sfp_is_present value + * return 0 is module present + * return 1 is module NOT present */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_IS_PRESENT_ALL: + /* Report the SFP/QSFP ALL PRESENCE status + * This data information form SWPLD2(SFP) and SWPLD1(QSFP). */ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_1), 0); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_2), 0); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_3), 0); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_4), 0); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_5), 0); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_6), 0); + /* QSFP_PRESENT Ports 49-54 */ + VALIDATED_READ(buf, values[6], + i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE), 0); + + values[6] = values[6] & 0x3F; + + /* sfp_is_present_all value + * return 0 is module present + * return 1 is module NOT present */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X\n", values[6], values[5], values[4],values[3], values[2], values[1], values[0]); + + case SFP_LP_MODE: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_LPMODE; + } else { + values[0] = 0; /* return 0, module is NOT in LP mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + } else { /* In agc7648sv1 only QSFP support control LP MODE */ + values[0] = 0; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_lp_mode value + * return 0 is module NOT in LP mode + * return 1 is module in LP mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_RESET: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_RESET; + } else { + values[0] = 1; /* return 1, module NOT in reset mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata1[swpld1].client, reg_t), 0); + } else { /* In agc7648sv1 only QSFP support control RESET MODE */ + values[0] = 1; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_reset value + * return 0 is module Reset + * return 1 is module Normal */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_RX_LOS: + port_t = sfp_port_data; + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_RXLOS_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_RXLOS_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_RXLOS_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_RXLOS_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_RXLOS_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_RXLOS_6; + } else { + values[0] = 1; /* return 1, module Error */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 0 && port_t < 49) { /* SFP */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata2[swpld2].client, reg_t), 0); + } else { /* In agc7648sv1 only SFP support control RX_LOS MODE */ + values[0] = 1; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_rx_los value + * return 0 is module Normal Operation + * return 1 is module Error */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_RX_LOS_ALL: + /* Report the SFP ALL RXLOS status + * This data information form SWPLD2. */ + + /* SFP_RXLOS Ports 1-8 */ + VALIDATED_READ(buf, values[0], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_1), 0); + /* SFP_RXLOS Ports 9-16 */ + VALIDATED_READ(buf, values[1], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_2), 0); + /* SFP_RXLOS Ports 17-24 */ + VALIDATED_READ(buf, values[2], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_3), 0); + /* SFP_RXLOS Ports 25-32 */ + VALIDATED_READ(buf, values[3], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_4), 0); + /* SFP_RXLOS Ports 33-40 */ + VALIDATED_READ(buf, values[4], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_5), 0); + /* SFP_RXLOS Ports 41-48 */ + VALIDATED_READ(buf, values[5], + i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_RXLOS_6), 0); + + /* sfp_rx_los_all value + * return 0 is module Normal Operation + * return 1 is module Error */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%02X %02X %02X %02X %02X %02X\n", values[5], values[4],values[3], values[2], values[1], values[0]); + + case SFP_TX_DISABLE: + port_t = sfp_port_data; + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_TXDIS_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_TXDIS_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_TXDIS_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_TXDIS_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_TXDIS_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_TXDIS_6; + } else { + values[0] = 1; /* return 1, module Transmitter Disabled */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 0 && port_t < 49) { /* SFP */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata2[swpld2].client, reg_t), 0); + } else { /* In agc7648sv1 only SFP support control TX_DISABLE MODE */ + values[0] = 1; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_tx_disable value + * return 0 is module Enable Transmitter on + * return 1 is module Transmitter Disabled */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + case SFP_TX_FAULT: + port_t = sfp_port_data; + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_TXFAULT_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_TXFAULT_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_TXFAULT_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_TXFAULT_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_TXFAULT_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_TXFAULT_6; + } else { + values[0] = 1; /* return 1, module is Fault */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + + if (port_t > 0 && port_t < 49) { /* SFP */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata2[swpld2].client, reg_t), 0); + } else { /* In agc7648sv1 only SFP support control TX_FAULT MODE */ + values[0] = 1; + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + } + port_t = port_t - 1; + bit_t = 1 << (port_t % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_tx_fault value + * return 0 is module Normal + * return 1 is module Fault */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values[0]); + + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } +} + +static ssize_t get_port_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + return sprintf(buf, "%ld\n", sfp_port_data); +} + +static ssize_t set_port_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + long data; + int error; + + error = kstrtol(buf, 10, &data); + if(error) + return error; + + if(data < 1 || data > 54) /* valid port is 1-54 */ + { + printk(KERN_ALERT "select port out of range (1-54)\n"); + return count; + } + else + sfp_port_data = data; + + return count; +} + +static ssize_t set_lpmode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + mutex_lock(&dni_lock); + port_t = sfp_port_data; + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_LPMODE; + } else { + values = 0; /* return 0, module NOT in LP mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values); + } + + values = i2c_smbus_read_byte_data(pdata[swpld1].client, reg_t); + if (values < 0){ + mutex_unlock(&dni_lock); + return -EIO; + } + /* Indicate the module is in LP mode or not + * 0 = Disable + * 1 = Enable */ + port_t = port_t - 1; + if (data == 0) + { + bit_t = ~(1 << (port_t % 8)); + values = values & bit_t; + } + else if (data == 1){ + bit_t = (1 << (port_t % 8)); + values = values | bit_t; + } + else + { + mutex_unlock(&dni_lock); + return -EINVAL; + } + if (i2c_smbus_write_byte_data(pdata[swpld1].client, reg_t, (u8)values) < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + mutex_unlock(&dni_lock); + return count; +} + +static ssize_t set_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + mutex_lock(&dni_lock); + port_t = sfp_port_data; + + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_RESET; + } else { + values = 1; /* return 1, module NOT in reset mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values); + } + + values = i2c_smbus_read_byte_data(pdata[swpld1].client, reg_t); + if (values < 0){ + mutex_unlock(&dni_lock); + return -EIO; + } + /* Indicate the module is in reset mode or not + * 0 = Reset + * 1 = Normal */ + port_t = port_t - 1; + if (data == 0) + { + bit_t = ~(1 << (port_t % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = (1 << (port_t % 8)); + values = values | bit_t; + } + else + { + mutex_unlock(&dni_lock); + return -EINVAL; + } + if (i2c_smbus_write_byte_data(pdata[swpld1].client, reg_t, (u8)values) < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + mutex_unlock(&dni_lock); + return count; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld2); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + mutex_lock(&dni_lock); + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_TXDIS_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_TXDIS_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_TXDIS_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_TXDIS_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_TXDIS_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_TXDIS_6; + } else { + values = 1; /* return 1, module NOT in reset mode */ + mutex_unlock(&dni_lock); + return sprintf(buf, "%d\n", values); + } + + values = i2c_smbus_read_byte_data(pdata[swpld2].client, reg_t); + if (values < 0){ + mutex_unlock(&dni_lock); + return -EIO; + } + /* Indicate the module is Enable Transmitter on or not + * 0 = Enable + * 1 = Disable */ + port_t = port_t - 1; + if (data == 0) + { + bit_t = ~(1 << (port_t % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = (1 << (port_t % 8)); + values = values | bit_t; + } + else + { + mutex_unlock(&dni_lock); + return -EINVAL; + } + if (i2c_smbus_write_byte_data(pdata[swpld2].client, reg_t, (u8)values) < 0) + { + mutex_unlock(&dni_lock); + return -EIO; + } + mutex_unlock(&dni_lock); + return count; +} +/* ---------------- SFP attribute read/write - end -------- */ + +/* ---------------- CPLD - start ------------- */ +unsigned char cpupld_reg_addr; +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; + +/* CPLD -- device */ +static struct platform_device cpld_device = { + .name = "delta-agc7648sv1-cpld", + .id = 0, + .dev = { + .platform_data = agc7648sv1_cpld_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld1_device = { + .name = "delta-agc7648sv1-swpld1", + .id = 0, + .dev = { + .platform_data = agc7648sv1_swpld1_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld2_device = { + .name = "delta-agc7648sv1-swpld2", + .id = 0, + .dev = { + .platform_data = agc7648sv1_swpld2_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld3_device = { + .name = "delta-agc7648sv1-swpld3", + .id = 0, + .dev = { + .platform_data = agc7648sv1_swpld3_platform_data, + .release = device_release + }, +}; + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[450]; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + mutex_lock(&dni_lock); + switch (attr->index) { + case CPLD_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case SWPLD1_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld1_reg_addr); + case SWPLD2_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case CPLD_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, cpupld_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD1_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld1].client, swpld1_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD2_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld2].client, swpld2_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD3_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld3].client, swpld3_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case CPU_BOARD_ID1 ... SFP_SEL: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[DEFAULT_CPLD].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = value & mask; + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xff: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0f: + case 0x07: + case 0x03: + break; + case 0x0c: + value = value >> 2; + break; + case 0xf0: + case 0x70: + case 0x30: + value = value >> 4; + break; + case 0xe0: + value = value >> 5; + break; + case 0xc0: + value = value >> 6; + break; + default : + value = value >> dni_log2(mask); + mutex_unlock(&dni_lock); + return sprintf(buf, "%d%s", value, note); + } + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%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; + } + + mutex_lock(&dni_lock); + + switch (attr->index) { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_ADDR: + swpld1_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld1].client, swpld1_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld2].client, swpld2_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld3].client, swpld3_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case CPU_BOARD_ID1 ... SFP_SEL: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[DEFAULT_CPLD].client, reg); + mask_out = value & ~(mask); + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0x03: + case 0x07: + case 0x0f: + case 0xff: + set_data = mask_out | (set_data & mask); + break; + case 0x0c: + set_data = set_data << 2; + set_data = mask_out | (set_data & mask); + break; + case 0xf0: + case 0x70: + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xe0: + set_data = set_data << 5; + set_data = mask_out | (set_data & mask); + break; + case 0xc0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + switch (attr->index) { + case CPU_BOARD_ID1 ... SFP_SEL: + i2c_smbus_write_byte_data(pdata[DEFAULT_CPLD].client, reg, set_data); + mutex_unlock(&dni_lock); + break; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "cpld not found"); + } + + return count; +} + +//address and value +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(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_VALUE); + +//CPLD +static SENSOR_DEVICE_ATTR(cpu_board_id1, S_IRUGO, get_cpld_reg, NULL, CPU_BOARD_ID1); +static SENSOR_DEVICE_ATTR(cpu_board_id2, S_IRUGO, get_cpld_reg, NULL, CPU_BOARD_ID2); +static SENSOR_DEVICE_ATTR(board_ver, S_IRUGO, get_cpld_reg, NULL, BOARD_VER); +static SENSOR_DEVICE_ATTR(cpuld_ver, S_IRUGO, get_cpld_reg, NULL, CPULD_VER); +static SENSOR_DEVICE_ATTR(cpu_sys_pwr_ok, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPU_SYS_PWR_OK); +static SENSOR_DEVICE_ATTR(plat_rst, S_IRUGO, get_cpld_reg, NULL, PLAT_RST); +static SENSOR_DEVICE_ATTR(cpld_vr_hot, S_IRUGO, get_cpld_reg, NULL, CPLD_VR_HOT); +static SENSOR_DEVICE_ATTR(cpu_over_tmp, S_IRUGO, get_cpld_reg, NULL, CPU_OVER_TMP); +static SENSOR_DEVICE_ATTR(ddr_over_tmp, S_IRUGO, get_cpld_reg, NULL, DDR_OVER_TMP); +static SENSOR_DEVICE_ATTR(cpu_pwr_rst, S_IRUGO, get_cpld_reg, NULL, CPU_PWR_RST); +static SENSOR_DEVICE_ATTR(cpu_hard_rst, S_IRUGO, get_cpld_reg, NULL, CPU_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_enable, S_IRUGO, get_cpld_reg, NULL, MB_PWR_ENABLE); +static SENSOR_DEVICE_ATTR(mb_pwr_pgd, S_IRUGO, get_cpld_reg, NULL, MB_PWR_PGD); +static SENSOR_DEVICE_ATTR(mb_rst_done, S_IRUGO, get_cpld_reg, NULL, MB_RST_DONE); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, MB_RST); +static SENSOR_DEVICE_ATTR(eeprom_wp, S_IRUGO, get_cpld_reg, NULL, EEPROM_WP); +static SENSOR_DEVICE_ATTR(psu_fan_event, S_IRUGO, get_cpld_reg, NULL, PSU_FAN_EVENT); +static SENSOR_DEVICE_ATTR(cpu_i2c_mux_en, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPU_I2C_MUX_EN); +static SENSOR_DEVICE_ATTR(cpu_i2c_mux_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPU_I2C_MUX_SEL); + +//SWPLD1 +static SENSOR_DEVICE_ATTR(board_id, S_IRUGO, get_cpld_reg, NULL, BOARD_ID); +static SENSOR_DEVICE_ATTR(bcm88375_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, BCM88375_RST); +static SENSOR_DEVICE_ATTR(b54616s_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, B54616S_RST); +static SENSOR_DEVICE_ATTR(psu1_en, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, PSU1_EN); +static SENSOR_DEVICE_ATTR(psu2_en, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, PSU2_EN); +static SENSOR_DEVICE_ATTR(psu1_pwr_fan_ok, S_IRUGO, get_cpld_reg, NULL, PSU1_PWR_FAN_OK); +static SENSOR_DEVICE_ATTR(psu2_pwr_fan_ok, S_IRUGO, get_cpld_reg, NULL, PSU2_PWR_FAN_OK); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, get_cpld_reg, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, get_cpld_reg, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_pwr_int, S_IRUGO, get_cpld_reg, NULL, PSU2_PWR_INT); +static SENSOR_DEVICE_ATTR(psu1_pwr_int, S_IRUGO, get_cpld_reg, NULL, PSU1_PWR_INT); +static SENSOR_DEVICE_ATTR(bcm88375_int, S_IRUGO, get_cpld_reg, NULL, BCM88375_INT); +static SENSOR_DEVICE_ATTR(bcm54616s_irq, S_IRUGO, get_cpld_reg, NULL, BCM54616S_IRQ); +static SENSOR_DEVICE_ATTR(led_sys, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, LED_SYS); +static SENSOR_DEVICE_ATTR(led_pwr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, LED_PWR); +static SENSOR_DEVICE_ATTR(led_fan, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, LED_FAN); +static SENSOR_DEVICE_ATTR(psu_i2c_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, PSU_I2C_SEL); +static SENSOR_DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, FAN4_LED); +static SENSOR_DEVICE_ATTR(fan_i2c_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, FAN_I2C_SEL); + +//SWPLD3 +static SENSOR_DEVICE_ATTR(qsfp_i2c_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, QSFP_I2C_SEL); +static SENSOR_DEVICE_ATTR(sfp_chan_en, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SFP_CHAN_EN); +static SENSOR_DEVICE_ATTR(sfp_sel, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SFP_SEL); + +//SFP, QSFP +static SENSOR_DEVICE_ATTR(sfp_select_port, S_IRUGO | S_IWUSR, get_port_data, set_port_data, SFP_SELECT_PORT); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, for_status, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, for_status, set_lpmode_data, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, for_status, set_reset_data, SFP_RESET); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, for_status, NULL, SFP_RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, for_status, NULL, SFP_RX_LOS_ALL); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, for_status, set_tx_disable, SFP_TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, for_status, NULL, SFP_TX_FAULT); + +static struct attribute *cpld_attrs[] = { + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, + &sensor_dev_attr_cpu_board_id1.dev_attr.attr, + &sensor_dev_attr_cpu_board_id2.dev_attr.attr, + &sensor_dev_attr_board_ver.dev_attr.attr, + &sensor_dev_attr_cpuld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_sys_pwr_ok.dev_attr.attr, + &sensor_dev_attr_plat_rst.dev_attr.attr, + &sensor_dev_attr_cpld_vr_hot.dev_attr.attr, + &sensor_dev_attr_cpu_over_tmp.dev_attr.attr, + &sensor_dev_attr_ddr_over_tmp.dev_attr.attr, + &sensor_dev_attr_cpu_pwr_rst.dev_attr.attr, + &sensor_dev_attr_cpu_hard_rst.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_pwr_enable.dev_attr.attr, + &sensor_dev_attr_mb_pwr_pgd.dev_attr.attr, + &sensor_dev_attr_mb_rst_done.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_psu_fan_event.dev_attr.attr, + &sensor_dev_attr_cpu_i2c_mux_en.dev_attr.attr, + &sensor_dev_attr_cpu_i2c_mux_sel.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld1_attrs[] = { + //SWPLD1 + &sensor_dev_attr_swpld1_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld1_reg_addr.dev_attr.attr, + &sensor_dev_attr_board_id.dev_attr.attr, + &sensor_dev_attr_bcm88375_rst.dev_attr.attr, + &sensor_dev_attr_b54616s_rst.dev_attr.attr, + &sensor_dev_attr_psu1_en.dev_attr.attr, + &sensor_dev_attr_psu2_en.dev_attr.attr, + &sensor_dev_attr_psu1_pwr_fan_ok.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_fan_ok.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_int.dev_attr.attr, + &sensor_dev_attr_psu1_pwr_int.dev_attr.attr, + &sensor_dev_attr_bcm88375_int.dev_attr.attr, + &sensor_dev_attr_bcm54616s_irq.dev_attr.attr, + &sensor_dev_attr_led_sys.dev_attr.attr, + &sensor_dev_attr_led_pwr.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + &sensor_dev_attr_psu_i2c_sel.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_fan_i2c_sel.dev_attr.attr, + //SFP, QSFP + &sensor_dev_attr_sfp_select_port.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_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_reset.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, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + &sensor_dev_attr_qsfp_i2c_sel.dev_attr.attr, + &sensor_dev_attr_sfp_chan_en.dev_attr.attr, + &sensor_dev_attr_sfp_sel.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_attr_grp = { + .attrs = cpld_attrs, +}; + +static struct attribute_group swpld1_attr_grp = { + .attrs = swpld1_attrs, +}; + +static struct attribute_group swpld2_attr_grp = { + .attrs = swpld2_attrs, +}; + +static struct attribute_group swpld3_attr_grp = { + .attrs = swpld3_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(BUS0); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS0); + 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_cpld = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_cpld); + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __init swpld1_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, "SWPLD1 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[swpld1].client = i2c_new_dummy(parent, pdata[swpld1].reg_addr); + if (!pdata[swpld1].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld1].reg_addr); + goto error; + } + + kobj_swpld1 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + return 0; + +error: + kobject_put(kobj_swpld1); + i2c_unregister_device(pdata[swpld1].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __init swpld2_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, "SWPLD2 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[swpld2].client = i2c_new_dummy(parent, pdata[swpld2].reg_addr); + if (!pdata[swpld2].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld2].reg_addr); + goto error; + } + + kobj_swpld2 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld2); + i2c_unregister_device(pdata[swpld2].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __init swpld3_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, "SWPLD3 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[swpld3].client = i2c_new_dummy(parent, pdata[swpld3].reg_addr); + if (!pdata[swpld3].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld3].reg_addr); + goto error; + } + + kobj_swpld3 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld3); + i2c_unregister_device(pdata[swpld3].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, &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 int __exit swpld1_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, &swpld1_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld1].client) { + if (!parent) { + parent = (pdata[swpld1].client)->adapter; + } + i2c_unregister_device(pdata[swpld1].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld2_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, &swpld2_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld2].client) { + if (!parent) { + parent = (pdata[swpld2].client)->adapter; + } + i2c_unregister_device(pdata[swpld2].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld3_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, &swpld3_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld3].client) { + if (!parent) { + parent = (pdata[swpld3].client)->adapter; + } + i2c_unregister_device(pdata[swpld3].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-agc7648sv1-cpld", + }, +}; + +static struct platform_driver swpld1_driver = { + .probe = swpld1_probe, + .remove = __exit_p(swpld1_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-swpld1", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-swpld3", + }, +}; +/* ---------------- CPLD - end ------------- */ + +/* ---------------- MUX - start ------------- */ +struct cpld_mux_platform_data { + int parent; + int base_nr; + struct i2c_client *cpld; + int reg_addr; +}; + +struct cpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct cpld_mux_platform_data data; +}; + +static struct cpld_mux_platform_data agc7648sv1_cpld_mux_platform_data[] = { + { + .parent = BUS0, + .base_nr = BUS0_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS0_MUX_REG, + }, +}; + +static struct cpld_mux_platform_data agc7648sv1_swpld1_mux_platform_data[] = { + { + .parent = BUS5, + .base_nr = BUS5_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS5_MUX_REG, + }, + { + .parent = BUS6, + .base_nr = BUS6_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS6_MUX_REG, + }, +}; + +static struct cpld_mux_platform_data agc7648sv1_swpld3_mux_platform_data[] = { + { + .parent = BUS2, + .base_nr = BUS2_QSFP_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS2_QSFP_MUX_REG, + }, + { + .parent = BUS2, + .base_nr = BUS2_SFP_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS2_SFP_MUX_REG, + }, +}; + +static struct platform_device cpld_mux_device[] = +{ + { + .name = "delta-agc7648sv1-cpld-mux", + .id = 0, + .dev = { + .platform_data = &agc7648sv1_cpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static struct platform_device swpld1_mux_device[] = +{ + { + .name = "delta-agc7648sv1-swpld1-mux", + .id = 0, + .dev = { + .platform_data = &agc7648sv1_swpld1_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-agc7648sv1-swpld1-mux", + .id = 1, + .dev = { + .platform_data = &agc7648sv1_swpld1_mux_platform_data[1], + .release = device_release, + }, + }, +}; + +static struct platform_device swpld3_mux_device[] = +{ + { + .name = "delta-agc7648sv1-swpld3-mux", + .id = 0, + .dev = { + .platform_data = &agc7648sv1_swpld3_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-agc7648sv1-swpld3-mux", + .id = 1, + .dev = { + .platform_data = &agc7648sv1_swpld3_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 cpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 cpld_mux_val = 0; + + if ( mux->data.base_nr == BUS0_BASE_NUM ){ + switch (chan) { + case 0: + cpld_mux_val = MUX_VAL_IDEEPROM; + break; + case 1: + cpld_mux_val = MUX_VAL_SERDES_SWPLD3; + break; + case 2: + default: + cpld_mux_val = MUX_VAL_PCA9547; + break; + } + } + else + { + printk(KERN_ERR "CPLD mux select error\n"); + return 0; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(cpld_mux_val & 0xff)); +} + +static int swpld1_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld1_mux_val = 0; + u8 bmc_swpld1_mux_val = 0; + int ret; + uint8_t cmd_data[4] = {0}; + uint8_t set_cmd; + int cmd_data_len; + + ret = dni_bmc_exist_check(); + if(ret == 0) //BMC monitor on + { + if ( mux->data.base_nr == BUS5_BASE_NUM ){ + switch (chan) { + case 0: + bmc_swpld1_mux_val = MUX_VAL_FAN_TMP75; + break; + case 1: + bmc_swpld1_mux_val = MUX_VAL_FAN_IO_CTL; + break; + case 2: + bmc_swpld1_mux_val = (MUX_VAL_FAN1_EEPROM + 0x08); + break; + case 3: + bmc_swpld1_mux_val = (MUX_VAL_FAN2_EEPROM + 0x09); + break; + case 4: + bmc_swpld1_mux_val = (MUX_VAL_FAN3_EEPROM + 0x09); + break; + case 5: + bmc_swpld1_mux_val = (MUX_VAL_FAN4_EEPROM + 0x09); + break; + case 6: + bmc_swpld1_mux_val = (MUX_VAL_FAN_CTL + 0x08); + break; + default: + bmc_swpld1_mux_val = (MUX_VAL_FAN_CTL + 0x08); + break; + } + + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_SWPLD_BUS; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = BUS5_MUX_REG; + cmd_data[3] = bmc_swpld1_mux_val; + cmd_data_len = sizeof(cmd_data); + } + else if ( mux->data.base_nr == BUS6_BASE_NUM ){ + switch (chan) { + case 0: + bmc_swpld1_mux_val = MUX_VAL_PSU1; + break; + case 1: + bmc_swpld1_mux_val = MUX_VAL_PSU2; + break; + default: + bmc_swpld1_mux_val = MUX_VAL_PSU1; + break; + } + + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_SWPLD_BUS; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = BUS6_MUX_REG; + cmd_data[3] = bmc_swpld1_mux_val; + cmd_data_len = sizeof(cmd_data); + } + else + { + printk(KERN_ERR "SWPLD1 mux select error\n"); + return 0; + } + return dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else //BMC monitor off or BMC is not exist + { + if ( mux->data.base_nr == BUS5_BASE_NUM ){ + switch (chan) { + case 0: + swpld1_mux_val = MUX_VAL_FAN1_EEPROM; + break; + case 1: + swpld1_mux_val = MUX_VAL_FAN2_EEPROM; + break; + case 2: + swpld1_mux_val = MUX_VAL_FAN3_EEPROM; + break; + case 3: + swpld1_mux_val = MUX_VAL_FAN4_EEPROM; + break; + case 4: + swpld1_mux_val = MUX_VAL_FAN_CTL; + break; + case 5: + swpld1_mux_val = MUX_VAL_FAN_TMP75; + break; + case 6: + swpld1_mux_val = MUX_VAL_FAN_IO_CTL; + break; + default: + swpld1_mux_val = MUX_VAL_FAN_CTL; + break; + } + } + else if ( mux->data.base_nr == BUS6_BASE_NUM ){ + switch (chan) { + case 0: + swpld1_mux_val = MUX_VAL_PSU1; + break; + case 1: + swpld1_mux_val = MUX_VAL_PSU2; + break; + default: + swpld1_mux_val = MUX_VAL_PSU1; + break; + } + } + else + { + printk(KERN_ERR "SWPLD1 mux select error\n"); + return 0; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld1_mux_val & 0xff)); + } +} + +static int swpld3_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + u8 swpld3_mux_val = 0; + u8 swpld3_qsfp_ch_en = 0; + u8 swpld1_qsfp_modsel_val = 0; + int ret; + uint8_t cmd_data[4] = {0}; + uint8_t set_cmd; + int cmd_data_len; + + ret = dni_bmc_exist_check(); + + if ( mux->data.base_nr == BUS2_QSFP_BASE_NUM ){ + /* Set QSFP module respond */ + swpld1_qsfp_modsel_val = SWPLD1_QSFP_MODSEL_VAL & (~(1 << chan)); + if (ret == 0) //BMC monitor on + { + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_SWPLD_BUS; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = SWPLD1_QSFP_MODSEL_REG; + cmd_data[3] = swpld1_qsfp_modsel_val; + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else //BMC monitor off or BMC is not exist + { + if (cpld_reg_write_byte(pdata[swpld1].client, SWPLD1_QSFP_MODSEL_REG, swpld1_qsfp_modsel_val) < 0) + return -EIO; + } + + /* QSFP channel enable */ + swpld3_qsfp_ch_en |= SWPLD3_QSFP_CH_EN << 4; + if (cpld_reg_write_byte(mux->data.cpld, BUS2_SFP_MUX_REG, swpld3_qsfp_ch_en) < 0) + return -EIO; + + /* QSFP channel selection */ + swpld3_mux_val = chan; + } + else if ( mux->data.base_nr == BUS2_SFP_BASE_NUM ){ + /* Disable all QSFP modules respond */ + swpld1_qsfp_modsel_val |= SWPLD1_QSFP_MODSEL_VAL; + if (ret == 0) //BMC monitor on + { + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_SWPLD_BUS; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = SWPLD1_QSFP_MODSEL_REG; + cmd_data[3] = swpld1_qsfp_modsel_val; + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else //BMC monitor off or BMC is not exist + { + if (cpld_reg_write_byte(pdata[swpld1].client, SWPLD1_QSFP_MODSEL_REG, swpld1_qsfp_modsel_val) < 0) + return -EIO; + } + + /* SFP port 51-59, 9 ports, chan 0-8 */ + if ( chan < SWPLD3_SFP_PORT_9 ){ + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH1_EN << 4; + swpld3_mux_val = swpld3_qsfp_ch_en | (chan + 1); + } + /* SFP port 60-69, 10 ports, chan 9-18 */ + else if ( chan >= SWPLD3_SFP_PORT_9 && chan < SWPLD3_SFP_PORT_19 ){ + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH2_EN << 4; + swpld3_mux_val = swpld3_qsfp_ch_en | (chan - SWPLD3_SFP_PORT_9); + } + /* SFP port 70-79, 10 ports, chan 19-28 */ + else if ( chan >= SWPLD3_SFP_PORT_19 && chan < SWPLD3_SFP_PORT_29 ){ + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH3_EN << 4; + swpld3_mux_val = swpld3_qsfp_ch_en | (chan - SWPLD3_SFP_PORT_19); + } + /* SFP port 80-89, 10 ports, chan 29-38 */ + else if ( chan >= SWPLD3_SFP_PORT_29 && chan < SWPLD3_SFP_PORT_39 ){ + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH4_EN << 4; + swpld3_mux_val = swpld3_qsfp_ch_en | (chan - SWPLD3_SFP_PORT_29); + } + /* SFP port 90-98, 9 ports, chan 39-47 */ + else if ( chan >= SWPLD3_SFP_PORT_39 && chan < SWPLD3_SFP_PORT_48 ){ + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH5_EN << 4; + swpld3_mux_val = swpld3_qsfp_ch_en | (chan - SWPLD3_SFP_PORT_39); + } + else { + swpld3_qsfp_ch_en |= SWPLD3_SFP_CH_DISABLE << 4; + swpld3_mux_val = swpld3_qsfp_ch_en; + } + } + else { + printk(KERN_ERR "SWPLD3 mux select error\n"); + return 0; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld3_mux_val & 0xff)); +} + +static int __init cpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD 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 BUS0: + dev_num = BUS0_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, cpld_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; +} + +static int __init swpld1_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD1 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 BUS5: + dev_num = BUS5_DEV_NUM; + break; + case BUS6: + dev_num = BUS6_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, swpld1_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; +} + +static int __init swpld3_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD3 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->base_nr) { + case BUS2_QSFP_BASE_NUM: + dev_num = BUS2_QSFP_DEV_NUM; + break; + case BUS2_SFP_BASE_NUM: + dev_num = BUS2_SFP_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, swpld3_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; +} + +static int __exit cpld_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; +} + +static int __exit swpld1_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; +} + +static int __exit swpld3_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; +} + +static struct platform_driver cpld_mux_driver = { + .probe = cpld_mux_probe, + .remove = __exit_p(cpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-cpld-mux", + }, +}; + +static struct platform_driver swpld1_mux_driver = { + .probe = swpld1_mux_probe, + .remove = __exit_p(swpld1_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-swpld1-mux", + }, +}; + +static struct platform_driver swpld3_mux_driver = { + .probe = swpld3_mux_probe, + .remove = __exit_p(swpld3_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc7648sv1-swpld3-mux", + }, +}; +/* ---------------- MUX - end ------------- */ + +/* ---------------- module initialization ------------- */ +static int __init delta_agc7648sv1_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_mux_platform_data *cpld_mux_pdata; + struct cpld_platform_data *cpld_pdata; + struct cpld_mux_platform_data *swpld1_mux_pdata; + struct cpld_platform_data *swpld1_pdata; + struct cpld_mux_platform_data *swpld3_mux_pdata; + struct cpld_platform_data *swpld3_pdata; + int ret,i = 0; + + mutex_init(&dni_lock); + printk("agc7648sv1_platform module initialization\n"); + + ret = dni_create_user(); + if (ret != 0) { + printk(KERN_WARNING "Fail to create IPMI user\n"); + } + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpld_driver; + } + + // 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; + } + + // 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; + } + + // 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 mux prob which call the SWPLD + ret = platform_driver_register(&cpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_cpld_mux_driver; + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&swpld1_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld1 mux driver\n"); + goto error_swpld1_mux_driver; + } + + // register the mux prob which call the SWPLD3 + ret = platform_driver_register(&swpld3_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld3 mux driver\n"); + goto error_swpld3_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 CPUPLD + ret = platform_device_register(&cpld_device); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_cpld_device; + } + + // link the CPLD and the Mux + cpld_pdata = agc7648sv1_cpld_platform_data; + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) + { + cpld_mux_pdata = cpld_mux_device[i].dev.platform_data; + cpld_mux_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&cpld_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_cpld_mux; + } + } + + adapter = i2c_get_adapter(BUS3); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_put_adapter(adapter); + + // register the SWPLD1 + ret = platform_device_register(&swpld1_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld1 device\n"); + goto error_swpld1_device; + } + + // register the SWPLD2 + ret = platform_device_register(&swpld2_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld2 device\n"); + goto error_swpld2_device; + } + + // register the SWPLD3 + ret = platform_device_register(&swpld3_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld3 device\n"); + goto error_swpld3_device; + } + + // link the SWPLD1 and the Mux + swpld1_pdata = agc7648sv1_swpld1_platform_data; + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) + { + swpld1_mux_pdata = swpld1_mux_device[i].dev.platform_data; + swpld1_mux_pdata->cpld = swpld1_pdata[swpld1].client; + ret = platform_device_register(&swpld1_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld1 mux %d\n", i); + goto error_agc7648sv1_swpld1_mux; + } + } + + // link the SWPLD3 and the Mux + swpld3_pdata = agc7648sv1_swpld3_platform_data; + for (i = 0; i < ARRAY_SIZE(swpld3_mux_device); i++) + { + swpld3_mux_pdata = swpld3_mux_device[i].dev.platform_data; + swpld3_mux_pdata->cpld = swpld3_pdata[swpld3].client; + ret = platform_device_register(&swpld3_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld3 mux %d\n", i); + goto error_agc7648sv1_swpld3_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(agc7648sv1_i2c_device); i++) + { + ret = platform_device_register(&agc7648sv1_i2c_device[i]); + if (ret) + { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_agc7648sv1_i2c_device; + } + } + if (ret) + goto error_cpld_mux; + return 0; + +error_agc7648sv1_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&agc7648sv1_i2c_device[i]); + } + i = ARRAY_SIZE(swpld3_mux_device); +error_agc7648sv1_swpld3_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&swpld3_mux_device[i]); + } + i = ARRAY_SIZE(swpld1_mux_device); +error_agc7648sv1_swpld1_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&swpld1_mux_device[i]); + } + platform_device_unregister(&swpld3_device); +error_swpld3_device: + platform_device_unregister(&swpld2_device); +error_swpld2_device: + platform_device_unregister(&swpld1_device); +error_swpld1_device: + i2c_unregister_device(i2c_client_9547); + i = ARRAY_SIZE(cpld_mux_device); +error_cpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&cpld_mux_device[i]); + } + platform_device_unregister(&cpld_device); +error_cpld_device: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld3_mux_driver); +error_swpld3_mux_driver: + platform_driver_unregister(&swpld1_mux_driver); +error_swpld1_mux_driver: + platform_driver_unregister(&cpld_mux_driver); +error_cpld_mux_driver: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_driver_unregister(&swpld1_driver); +error_swpld1_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_agc7648sv1_platform_exit(void) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(agc7648sv1_i2c_device); i++) { + platform_device_unregister(&agc7648sv1_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(swpld3_mux_device); i++) { + platform_device_unregister(&swpld3_mux_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) { + platform_device_unregister(&swpld1_mux_device[i]); + } + + 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); + + i2c_unregister_device(i2c_client_9547); + + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) { + platform_device_unregister(&cpld_mux_device[i]); + } + + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld3_mux_driver); + platform_driver_unregister(&swpld1_mux_driver); + platform_driver_unregister(&cpld_mux_driver); + platform_device_unregister(&cpld_device); + platform_driver_unregister(&cpld_driver); +} + +module_init(delta_agc7648sv1_platform_init); +module_exit(delta_agc7648sv1_platform_exit); + +MODULE_DESCRIPTION("DELTA agc7648sv1 Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/dni_agc7648sv1_psu.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/dni_agc7648sv1_psu.c new file mode 100644 index 00000000..4ba6e2c8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/dni_agc7648sv1_psu.c @@ -0,0 +1,495 @@ +/* + * An hwmon driver for delta AGV7648SV1 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * Aries Lin + * + * 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 + +/* 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 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[2]; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_model[14]; + u8 mfr_serial[14]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(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_fault(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); + +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, +}; + +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 \ + *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; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle[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->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 for_fan_fault(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_fault >> 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->v_out; + return (exponent > 0) ? sprintf(buf, "%d\n", \ + mantissa * (1 << exponent)) : \ + sprintf(buf, "%d\n", mantissa / (1 << -exponent) * multiplier); + +} + +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); + + 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_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])}, + {0x90, &(data->fan_speed[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 */ + 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[0] = '\0'; + } + + 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->mfr_serial[0] = '\0'; + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, \ + S_IRUGO | S_IWUSR, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +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 struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.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_agc7648sv1_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_agc7648sv1_psu", dni_agc7648sv1_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/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/dni_emc2305.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/dni_emc2305.c new file mode 100644 index 00000000..73d9900a --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/modules/builds/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/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/PKG.yml new file mode 100644 index 00000000..eee0b187 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-delta-agc7648sv1 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/Makefile new file mode 100644 index 00000000..2b1ca74c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-delta-agc7648sv1 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_delta_agc7648sv1 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-delta-agc7648sv1.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/libonlp-x86-64-delta-agc7648sv1-r0.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/libonlp-x86-64-delta-agc7648sv1-r0.mk new file mode 100644 index 00000000..16e01bbf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/lib/libonlp-x86-64-delta-agc7648sv1-r0.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-delta-agc7648sv1-r0 module. +# +# Autogenerated 2016-03-16 22:11:47.698846 +# +############################################################################### +libonlp-x86-64-delta-agc7648sv1-r0_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/onlpdump/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..bf472fe6 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_delta_agc7648sv1 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/.module b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/.module new file mode 100644 index 00000000..b9e80409 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_delta_agc7648sv1 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/Makefile new file mode 100644 index 00000000..e385dfe2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/Makefile @@ -0,0 +1,10 @@ +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.mk + +MODULE := x86_64_delta_agc7648sv1 +AUTOMODULE := x86_64_delta_agc7648sv1 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..8f4a18e0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# x86_64_delta_agc7648sv1 Autogeneration +# +############################################################################### + +x86_64_delta_agc7648sv1_AUTO_DEFS := module/auto/x86_64_delta_agc7648sv1.yml +x86_64_delta_agc7648sv1_AUTO_DIRS := module/inc/x86_64_delta_agc7648sv1 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/x86_64_delta_agc7648sv1.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/x86_64_delta_agc7648sv1.yml new file mode 100755 index 00000000..99d94f52 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/auto/x86_64_delta_agc7648sv1.yml @@ -0,0 +1,55 @@ +############################################################################### +# +# x86_64_delta_agc7648sv1 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_DELTA_agc7648sv1_CONFIG_PORTING_STDLIB +- X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 +- X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT: + doc: "SFP port numbers." + default: 4 +- X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX: + doc: "Max fan speed." + default: 18000 + +definitions: + cdefs: + X86_64_DELTA_AGC7648SV1_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_delta_agc7648sv1_config + + portingmacro: + X86_64_DELTA_agc7648sv1: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1.x b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1.x new file mode 100644 index 00000000..e7839305 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1.x @@ -0,0 +1,16 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ + + +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_config.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_config.h new file mode 100755 index 00000000..84bdbedf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_config.h @@ -0,0 +1,157 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_agc7648sv1 Configuration Header + * + * @addtogroup x86_64_delta_agc7648sv1-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_AGC7648SV1_CONFIG_H__ +#define __X86_64_DELTA_AGC7648SV1_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_DELTA_AGC7648SV1_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING +#define X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT +#define X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB +#define X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_DELTA_agc7648sv1_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI +#define X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT + * + * SFP port numbers. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT +#define X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT 4 +#endif + +/** + * X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX + * + * Max fan speed. */ + + +#ifndef X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX +#define X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX 18000 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_delta_agc7648sv1_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_delta_agc7648sv1_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_delta_agc7648sv1_config_settings table. */ +extern x86_64_delta_agc7648sv1_config_settings_t x86_64_delta_agc7648sv1_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_delta_agc7648sv1_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_delta_agc7648sv1_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_delta_agc7648sv1_porting.h" + +#endif /* __x86_64_delta_agc7648sv1_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_dox.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_dox.h new file mode 100644 index 00000000..67eaa614 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_delta_agc7648sv1 Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_agc7648sv1_DOX_H__ +#define _X86_64_DELTA_agc7648sv1_DOX_H__ + +/** + * @defgroup x86_64_delta_agc7648sv1 x86_64_delta_agc7648sv1 - x86_64_delta_agc7648sv1 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_delta_agc7648sv1-x86_64_delta_agc7648sv1 Public Interface + * @defgroup x86_64_delta_agc7648sv1-config Compile Time Configuration + * @defgroup x86_64_delta_agc7648sv1-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_DELTA_agc7648sv1_DOX_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_porting.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_porting.h new file mode 100755 index 00000000..a21610ef --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/inc/x86_64_delta_agc7648sv1/x86_64_delta_agc7648sv1_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_agc7648sv1 Porting Macros. + * + * @addtogroup x86_64_delta_agc7648sv1-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_AGC7648SV1_PORTING_H__ +#define __X86_64_DELTA_AGC7648SV1_PORTING_H__ + + +/* */ +#if X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_DELTA_AGC7648SV1_MALLOC GLOBAL_MALLOC + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_MALLOC malloc + #else + #error The macro X86_64_DELTA_AGC7648SV1_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_FREE + #if defined(GLOBAL_FREE) + #define X86_64_DELTA_AGC7648SV1_FREE GLOBAL_FREE + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_FREE free + #else + #error The macro X86_64_DELTA_AGC7648SV1_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_DELTA_AGC7648SV1_MEMSET GLOBAL_MEMSET + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_MEMSET memset + #else + #error The macro X86_64_DELTA_AGC7648SV1_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_DELTA_AGC7648SV1_MEMCPY GLOBAL_MEMCPY + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_MEMCPY memcpy + #else + #error The macro X86_64_DELTA_AGC7648SV1_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_DELTA_AGC7648SV1_STRNCPY GLOBAL_STRNCPY + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_STRNCPY strncpy + #else + #error The macro X86_64_DELTA_AGC7648SV1_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_DELTA_AGC7648SV1_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_VSNPRINTF vsnprintf + #else + #error The macro X86_64_DELTA_AGC7648SV1_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_DELTA_AGC7648SV1_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_SNPRINTF snprintf + #else + #error The macro X86_64_DELTA_AGC7648SV1_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_DELTA_AGC7648SV1_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_DELTA_AGC7648SV1_STRLEN GLOBAL_STRLEN + #elif X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB == 1 + #define X86_64_DELTA_AGC7648SV1_STRLEN strlen + #else + #error The macro X86_64_DELTA_AGC7648SV1_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* _X86_64_DELTA_AGC7648SV1_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..e5ffb6ee --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_delta_agc7648sv1_INCLUDES := -I $(THIS_DIR)inc +x86_64_delta_agc7648sv1_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_delta_agc7648sv1_DEPENDMODULE_ENTRIES := init:x86_64_delta_agc7648sv1 ucli:x86_64_delta_agc7648sv1 + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..d7537072 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_delta_agc7648sv1_ucli.c + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/fani.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..e57d9651 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/fani.c @@ -0,0 +1,447 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include + +typedef struct fan_path_S +{ + char *status; + char *speed; + char *ctrl_speed; +}fan_path_T; + +static fan_path_T fan_path[] = /* must map with onlp_fan_id */ +{ + { NULL, NULL, NULL }, + { "25-002c/fan4_fault", "25-002c/fan4_input", "25-002c/fan4_input_percentage" }, + { "25-002c/fan3_fault", "25-002c/fan3_input", "25-002c/fan3_input_percentage" }, + { "25-002c/fan2_fault", "25-002c/fan2_input", "25-002c/fan2_input_percentage" }, + { "25-002c/fan1_fault", "25-002c/fan1_input", "25-002c/fan1_input_percentage" }, + { "25-002d/fan4_fault", "25-002d/fan4_input", "25-002d/fan4_input_percentage" }, + { "25-002d/fan3_fault", "25-002d/fan3_input", "25-002d/fan3_input_percentage" }, + { "25-002d/fan2_fault", "25-002d/fan2_input", "25-002d/fan2_input_percentage" }, + { "25-002d/fan1_fault", "25-002d/fan1_input", "25-002d/fan1_input_percentage" }, + { "31-0058/psu_fan1_fault", "31-0058/psu_fan1_speed_rpm", "31-0058/psu_fan1_duty_cycle_percentage" }, + { "32-0058/psu_fan1_fault", "32-0058/psu_fan1_speed_rpm", "32-0058/psu_fan1_duty_cycle_percentage" } +}; + +#define MAKE_FAN_INFO_NODE_ON_FAN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_FAN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[] = { + { }, // Not used + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info, char *dev_name) +{ + int bit_data = 0; + int rpm = 0; + char fullpath[100] = {0}; + int rv = ONLP_STATUS_OK; + uint8_t present_bit = 0x00; + UINT4 multiplier = 1; + UINT4 u4Data = 0; + int fantray_present = -1; + + if(dni_bmc_check() == BMC_ON) + { + if(dni_bmc_sensor_read(dev_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->rpm = u4Data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + } + + rv = dni_bmc_fanpresent_info_get(&bit_data); + if(rv == ONLP_STATUS_OK && bit_data != 0) + present_bit = bit_data; + else + rv = ONLP_STATUS_E_INVALID; + + switch(local_id) { + case FAN_4_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + if((present_bit & 1) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_3_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + if((present_bit & (1 << 1)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_2_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + if((present_bit & (1 << 2)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_1_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + if((present_bit & (1 << 3)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + } + } + else + { + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + rpm = dni_i2c_lock_read_attribute(NULL, fullpath); + info->rpm = rpm; + + /* If rpm is FAN_ZERO_TACH, then the rpm value is zero. */ + if(info->rpm == 960) + info->rpm = 0; + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100)/MAX_FRONT_FAN_SPEED; + + switch(local_id) { + case FAN_4_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN4_PRESENT_PATH); + if(fantray_present == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_3_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN3_PRESENT_PATH); + if(fantray_present == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_2_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN2_PRESENT_PATH); + if(fantray_present == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + case FAN_1_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN1_PRESENT_PATH); + if(fantray_present == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + } + } + + return rv; +} + +static int dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info, char *dev_name) +{ + int rpm_data = 0; + int r_data = 0; + int bit_data = 0; + int rv = ONLP_STATUS_OK; + int psu_present = 0; + UINT4 multiplier = 1; + UINT4 u4Data = 0; + char fullpath[100] = {0}; + + if(dni_bmc_check() == BMC_ON) + { + rv = dni_psu_present(&bit_data); + psu_present = bit_data; + rv = dni_bmc_sensor_read(dev_name, &u4Data, multiplier); + rpm_data = (int)u4Data; + + switch(local_id) + { + case FAN_1_ON_PSU1: + if((psu_present & 0x01) != 0x01) + { + info->rpm = rpm_data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_FAILED; + rv = ONLP_STATUS_E_INVALID; + } + break; + case FAN_1_ON_PSU2: + if((psu_present & 0x02) != 0x02) + { + info->rpm = rpm_data; + info->percentage = (info->rpm * 100) / MAX_FRONT_FAN_SPEED; + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_FAILED; + rv = ONLP_STATUS_E_INVALID; + } + break; + } + } + else + { + switch(local_id) { + case FAN_1_ON_PSU1: + psu_present = dni_i2c_lock_read_attribute(NULL, PSU1_PRESENT_PATH); + break; + case FAN_1_ON_PSU2: + psu_present = dni_i2c_lock_read_attribute(NULL, PSU2_PRESENT_PATH); + break; + default: + break; + } + if(psu_present == 0) + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + else if(psu_present == 1) + info->status |= ONLP_FAN_STATUS_FAILED; + + /* Read PSU FAN speed from psu_fan1_speed_rpm */ + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + info->rpm = r_data; + + /* Calculate psu fan duty cycle based on rpm */ + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + + return rv; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int onlp_fani_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[ONLP_OID_ID_GET(id)]; + + switch(local_id) { + case FAN_1_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_1"); + break; + case FAN_2_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_2"); + break; + case FAN_3_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_3"); + break; + case FAN_4_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_1_4"); + break; + case FAN_5_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_1"); + break; + case FAN_6_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_2"); + break; + case FAN_7_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_3"); + break; + case FAN_8_ON_FAN_BOARD: + rv = dni_fani_info_get_fan(local_id, info, "Fantray_2_4"); + break; + case FAN_1_ON_PSU1: + rv = dni_fani_info_get_fan_on_psu(local_id, info, "PSU1_Fan"); + break; + case FAN_1_ON_PSU2: + rv = dni_fani_info_get_fan_on_psu(local_id, info, "PSU2_Fan"); + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + + return rv; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + int local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + switch (local_id) { + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + sprintf(data, "%d", rpm); + dni_i2c_lock_write_attribute(NULL, data, fullpath); + + return ONLP_STATUS_OK; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* Select PSU member */ + switch (local_id) { + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + case FAN_6_ON_FAN_BOARD: + case FAN_7_ON_FAN_BOARD: + case FAN_8_ON_FAN_BOARD: + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + break; + default: + return ONLP_STATUS_E_INVALID; + } + + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].ctrl_speed); + /* Write percentage to psu_fan1_duty_cycle_percentage */ + sprintf(data, "%d", p); + dni_i2c_lock_write_attribute(NULL, data, fullpath); + + return ONLP_STATUS_OK; +} + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/ledi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..6c858fd0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,503 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* Get the information for the given LED OID. */ +static onlp_led_info_t linfo[] = +{ + { }, // Not used + { + { ONLP_LED_ID_CREATE(LED_FRONT_FAN), "FRONT LED (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_YELLOW_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_PWR), "FRONT LED (PWR LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_SYS), "FRONT LED (SYS LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_GREEN_BLINKING | \ + ONLP_LED_CAPS_YELLOW_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1), "FAN TRAY 1 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2), "FAN TRAY 2 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3), "FAN TRAY 3 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4), "FAN TRAY 4 LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + }, +}; + + +/* This function will be called prior to any other onlp_ledi_* functions. */ +int onlp_ledi_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int r_data = 0; + int bit_data = 0; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[ONLP_OID_ID_GET(id)]; + + if(dni_bmc_check() == BMC_ON) + { + switch(local_id) { + case LED_FRONT_FAN: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, SYS_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0x03) == 0x03) + info->mode = ONLP_LED_MODE_YELLOW_BLINKING; + else if((r_data & 0x03) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, SYS_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0x0c) == 0x0c || (r_data & 0x0c) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_SYS: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, SYS_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if((r_data & 0xf0) == 0x10) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0xf0) == 0x20) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xf0) == 0x90) // 0.5S + info->mode = ONLP_LED_MODE_GREEN_BLINKING; + else if((r_data & 0xf0) == 0xa0) // 0.5S + info->mode = ONLP_LED_MODE_YELLOW_BLINKING; + else if ((r_data & 0xf0) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_REAR_FAN_TRAY_1: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_1) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_2: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_2) == ONLP_STATUS_OK){ + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_3: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_3) == ONLP_STATUS_OK){ + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_4: + if( dni_bmc_data_get(BMC_SWPLD_BUS, SWPLD_1_ADDR, FAN_LED_REGISTER, 1, &bit_data) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + r_data = bit_data; + if(dni_fan_present(LED_REAR_FAN_TRAY_4) == ONLP_STATUS_OK){ + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + } + } + else{ + switch(local_id) + { + case LED_FRONT_FAN: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0x03) == 0x03) + info->mode = ONLP_LED_MODE_YELLOW_BLINKING; + else if((r_data & 0x03) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_PWR: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + if((r_data & 0x0c) == 0x4) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x8) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0x0c) == 0xc || (r_data & 0x0c) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_FRONT_SYS: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + if((r_data & 0xf0) == 0x10) + info->mode = ONLP_LED_MODE_YELLOW; + else if((r_data & 0xf0) == 0x20) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xf0) == 0x90) // 0.5S + info->mode = ONLP_LED_MODE_GREEN_BLINKING; + else if((r_data & 0xf0) == 0xa0) // 0.5S + info->mode = ONLP_LED_MODE_YELLOW_BLINKING; + else if ((r_data & 0xf0) == 0x00) + info->mode = ONLP_LED_MODE_OFF; + else + return ONLP_STATUS_E_INTERNAL; + break; + + case LED_REAR_FAN_TRAY_1: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_1) == ONLP_STATUS_OK){ + if((r_data & 0xc0) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0xc0) == 0x80) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_2: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_2) == ONLP_STATUS_OK){ + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_3: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_3) == ONLP_STATUS_OK){ + if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + case LED_REAR_FAN_TRAY_4: + r_data = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + if(dni_fan_present(LED_REAR_FAN_TRAY_4) == ONLP_STATUS_OK){ + if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_RED; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + } + } + + /* Set the on/off status */ + if (info->mode == ONLP_LED_MODE_OFF) + info->status = ONLP_LED_STATUS_FAILED; + else + info->status |= ONLP_LED_STATUS_PRESENT; + + return ONLP_STATUS_OK; +} + +/* Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. */ +int onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + if (!on_or_off) + { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. */ +int onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + VALIDATE(id); + int local_id = ONLP_OID_ID_GET(id); + uint8_t front_panel_led_value = 0; + uint8_t fan_tray_led_reg_value = 0; + + if(dni_bmc_check() == BMC_ON) + { + return ONLP_STATUS_OK; + } + else{ + switch(local_id) + { + case LED_FRONT_FAN: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + front_panel_led_value &= ~0x03; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x01; + } + else if(mode == ONLP_LED_MODE_YELLOW){ + front_panel_led_value |= 0x02; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, SYS_LED_REGISTER, front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_FRONT_PWR: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + front_panel_led_value &= ~0x0c; + + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x04; + } + else if(mode == ONLP_LED_MODE_YELLOW){ + front_panel_led_value |= 0x08; + } + else{ + front_panel_led_value = front_panel_led_value; + } + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, SYS_LED_REGISTER, front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_FRONT_SYS: + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, SYS_LED_REGISTER); + front_panel_led_value &= ~0xf0; + + if(mode == ONLP_LED_MODE_YELLOW){ + front_panel_led_value |= 0x10; + } + else if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x20; + } + else if(mode == ONLP_LED_MODE_GREEN_BLINKING){ // 0.5S + front_panel_led_value |= 0x90; + } + else if(mode == ONLP_LED_MODE_YELLOW_BLINKING){ // 0.5S + front_panel_led_value |= 0xa0; + } + else{ + front_panel_led_value = front_panel_led_value; + } + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, SYS_LED_REGISTER, front_panel_led_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_REAR_FAN_TRAY_1: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0xc0; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x40; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x80; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_REAR_FAN_TRAY_2: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x30; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x10; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x20; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_REAR_FAN_TRAY_3: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x0c; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x04; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x08; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + + case LED_REAR_FAN_TRAY_4: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(SWPLD1_PATH, FAN_LED_REGISTER); + fan_tray_led_reg_value &= ~0x03; + + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x01; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x02; + } + else{ + fan_tray_led_reg_value = fan_tray_led_reg_value;; + } + + if(dni_lock_cpld_write_attribute(SWPLD1_PATH, FAN_LED_REGISTER, fan_tray_led_reg_value) != 0){ + AIM_LOG_ERROR("Unable to set led(%d) status\r\n", local_id); + return ONLP_STATUS_E_INTERNAL; + } + break; + } + } + return ONLP_STATUS_OK; +} + +/* Generic LED ioctl interface. */ +int onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..70160b4c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_delta_agc7648sv1 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..1219c0cb --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,490 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include "platform_lib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include + +static onlp_shlock_t* dni_lock = NULL; + +#define DNI_BUS_LOCK() \ + do{ \ + onlp_shlock_take(dni_lock); \ + }while(0) + +#define DNI_BUS_UNLOCK() \ + do{ \ + onlp_shlock_give(dni_lock); \ + }while(0) + +#define DNILOCK_MAGIC 0xA6D2B4E8 + +void lockinit() +{ + static int sem_inited = 0; + if(!sem_inited) + { + onlp_shlock_create(DNILOCK_MAGIC, &dni_lock, "bus-lock"); + sem_inited = 1; + } +} + +int dni_bmc_sensor_read(char *device_name, UINT4 *num, UINT4 multiplier) +{ + FILE *fpRead; + char Buf[10] = {0}; + char ipmi_command[120] = {0}; + int lenth = 10; + float num_f; + + sprintf(ipmi_command, "ipmitool sdr get %s |grep 'Sensor Reading'| awk -F':' '{print $2}'| awk -F' ' '{ print $1}'", device_name); + fpRead = popen(ipmi_command, "r"); + + if(fpRead == NULL){ + pclose(fpRead); + return ONLP_STATUS_E_GENERIC; + } + fgets(Buf, lenth , fpRead); + num_f = atof(Buf); + *num = num_f * multiplier; + pclose(fpRead); + + return ONLP_STATUS_OK; +} + +int dni_bmc_check() +{ + char cmd[30] = {0}; + char str_data[100] = {0}; + FILE *fptr = NULL; + int rv = 0; + + sprintf(cmd, "ipmitool raw 0x38 0x1a 0x00"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + rv = strtol(str_data, NULL, 16); + if(rv == 1) + rv = BMC_OFF; + else + rv = BMC_ON; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int dni_bmc_data_get(int bus, int addr, int reg, int len, int *r_data) +{ + int rv = ONLP_STATUS_OK; + char cmd[50] = {0}; + char rdata[10] = {0}; + FILE *fptr = NULL; + + sprintf(cmd, "ipmitool raw 0x38 0x2 %d 0x%x 0x%x %d", bus ,addr, reg, len); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(rdata, sizeof(rdata), fptr) != NULL) + *r_data = strtol(rdata, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int dni_bmc_fanpresent_info_get(int *r_data) +{ + int rv = ONLP_STATUS_OK; + char cmd[30] = {0}; + char str_data[100] = {0}; + FILE *fptr = NULL; + + sprintf(cmd, "ipmitool raw 0x38 0x0e"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + *r_data = strtol(str_data, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int hex_to_int(char hex_input) +{ + int first = hex_input / 16 - 3; + int second = hex_input % 16; + int result = first * 10 + second; + + if(result > 9) result--; + return result; +} + +int hex_to_ascii(char hex_high, char hex_low) +{ + int high = hex_to_int(hex_high) * 16; + int low = hex_to_int(hex_low); + + return high + low; +} + +int dni_psu_present(int *r_data) +{ + FILE *fptr = NULL; + int rv = ONLP_STATUS_OK; + char cmd[35] = {0}; + char str_data[50] = {0}; + + sprintf(cmd, "ipmitool raw 0x38 0x2 2 0x6a 0x0d 1"); + fptr = popen(cmd, "r"); + if(fptr != NULL) + { + if(fgets(str_data, sizeof(str_data), fptr) != NULL) + *r_data = strtol(str_data, NULL, 16); + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + pclose(fptr); + + return rv; +} + +int dni_psui_eeprom_info_get(char * r_data, char *device_name, int number) +{ + int i = 0; + int rv = ONLP_STATUS_OK; + FILE *fptr = NULL; + char cmd[35] = {0}; + char str_data[50] = {0}; + char buf; + char* renewCh; + + sprintf(cmd, "ipmitool fru print %d | grep '%s' | awk -F':' '{print $2}'",number,device_name); + fptr = popen(cmd, "r"); + while((buf = fgetc(fptr)) != EOF) + { + if(buf != ' ') + { + str_data[i] = buf; + i++; + } + } + for(i = 0; i < PSU_NUM_LENGTH; i++) + r_data[i] = str_data[i]; + pclose(fptr); + + renewCh = strstr(r_data,"\n"); + if(renewCh) + *renewCh= '\0'; + + return rv; +} + +int dni_i2c_lock_read(mux_info_t * mux_info, dev_info_t * dev_info) +{ + int r_data = 0; + + DNI_BUS_LOCK(); + if(dev_info->size == 1) + r_data = onlp_i2c_readb(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + else + r_data = onlp_i2c_readw(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + + DNI_BUS_UNLOCK(); + return r_data; +} + +int dni_i2c_lock_write(mux_info_t * mux_info, dev_info_t * dev_info) +{ + DNI_BUS_LOCK(); + /* Write size */ + if(dev_info->size == 1) + onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); + else + onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); + + DNI_BUS_UNLOCK(); + return 0; +} + +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) +{ + int fd, nbytes = 10, rv = -1; + char r_data[10] = {0}; + + DNI_BUS_LOCK(); + if ((fd = open(fullpath, O_RDONLY)) >= 0) + { + if ((read(fd, r_data, nbytes)) > 0) + rv = atoi(r_data); + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath) +{ + int fd, rv = -1; + + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(fullpath, O_WRONLY, 0644)) >= 0) + { + if (write(fd, data, strlen(data)) > 0) + { + fsync(fd); + rv = 0; + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +/* Use this function to select MUX and read data on CPLD */ +int dni_lock_cpld_read_attribute(char *cpld_path, int addr) +{ + int fd, fd1, nbytes = 10, data = 0, rv = -1; + char r_data[10] = {0}; + char address[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/swpld1_reg_value", cpld_path); + sprintf(cpld_addr_path, "%s/swpld1_reg_addr", cpld_path); + sprintf(address, "0x%02x", addr); + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(cpld_addr_path, O_WRONLY, 0644)) >= 0) + { + if (write(fd, address, strlen(address)) > 0) + { + fsync(fd); + if ((fd1 = open(cpld_data_path, O_RDONLY, 0644)) >= 0) + { + if ((read(fd1, r_data, nbytes)) > 0) + { + sscanf(r_data, "%x", &data); + rv = data; + } + } + close(fd1); + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +/* Use this function to select MUX and write data on CPLD */ +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data) +{ + int fd, fd1, rv = -1; + char address[10] = {0}; + char datas[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/swpld1_reg_value", cpld_path); + sprintf(cpld_addr_path, "%s/swpld1_reg_addr", cpld_path); + sprintf(address, "0x%02x", addr); + DNI_BUS_LOCK(); + /* Create output file descriptor */ + if ((fd = open(cpld_addr_path, O_WRONLY, 0644)) >= 0) + { + if ((write(fd, address, strlen(address))) > 0) + { + fsync(fd); + if ((fd1 = open(cpld_data_path, O_WRONLY, 0644)) >= 0) + { + sprintf(datas, "0x%02x", data); + if (write(fd1, datas, strlen(datas)) > 0) + { + fsync(fd1); + rv = 0; + } + } + close(fd1); + } + } + close(fd); + DNI_BUS_UNLOCK(); + return rv; +} + +int dni_fan_present(int id) +{ + int rv; + int bit_data = 0; + int data = 0; + uint8_t present_bit = 0x00; + int fantray_present = -1; + + if(dni_bmc_check() == BMC_ON) + { + rv = dni_bmc_fanpresent_info_get(&bit_data); + if(rv == ONLP_STATUS_OK) + { + present_bit = bit_data; + data = (present_bit & (1 << -(id - NUM_OF_LED_ON_MAIN_BROAD))); + if(data == 0) + rv = ONLP_STATUS_OK; + else + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + } + else if(dni_bmc_check() == BMC_OFF) + { + switch(id) { + case LED_REAR_FAN_TRAY_1: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN1_PRESENT_PATH); + break; + case LED_REAR_FAN_TRAY_2: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN2_PRESENT_PATH); + break; + case LED_REAR_FAN_TRAY_3: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN3_PRESENT_PATH); + break; + case LED_REAR_FAN_TRAY_4: + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN4_PRESENT_PATH); + break; + } + if(fantray_present == 0) + rv = ONLP_STATUS_OK; + else if(fantray_present == 1) + rv = ONLP_STATUS_E_INVALID; + } + else + rv = ONLP_STATUS_E_INVALID; + + return rv; +} + +int dni_fan_speed_good() +{ + int rpm = 0, rpm1 = 0, speed_good = 0; + + rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); + if(rpm != 0 && rpm != 960 && rpm1 != 0 && rpm1 != 960) + speed_good++; + + rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); + if(rpm != 0 && rpm != 960 && rpm1 != 0 && rpm1 != 960) + speed_good++; + + rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); + if(rpm != 0 && rpm != 960 && rpm1 != 0 && rpm1 != 960) + speed_good++; + + rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); + if(rpm != 0 && rpm != 960 && rpm1 != 0 && rpm1 != 960) + speed_good++; + + return speed_good; +} + +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd, rv = 0; + int len; + DNI_BUS_LOCK(); + + if ((buffer == NULL) || (buf_size < 0)) { + rv = -1; + goto ERROR; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + rv = -1; + goto ERROR; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + rv = -1; + goto ERROR; + } + + if ((close(fd) == -1)) { + rv = -1; + goto ERROR; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + rv = -1; + goto ERROR; + } + +ERROR: + DNI_BUS_UNLOCK(); + return rv; +} + +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) + return -1; + + ret = dni_i2c_read_attribute_binary(filename, buffer, buf_size-1, data_len); + if (ret == 0) + buffer[buf_size-1] = '\0'; + + return ret; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..ebc694e5 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,227 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_delta_agc7648sv1_log.h" +#include +#include + +typedef unsigned int UINT4; + +/* CPLD numbrt & peripherals */ +#define NUM_OF_SFP (48) +#define NUM_OF_QSFP (6) +#define NUM_OF_PORT NUM_OF_SFP + NUM_OF_QSFP +#define NUM_OF_THERMAL_ON_MAIN_BROAD (9) +#define NUM_OF_LED_ON_MAIN_BROAD (7) +#define NUM_OF_FAN_ON_MAIN_BROAD (8) +#define NUM_OF_PSU_ON_MAIN_BROAD (2) +#define NUM_OF_SENSORS (47) +#define CHASSIS_FAN_COUNT (8) +#define CHASSIS_THERMAL_COUNT (9) +#define NUM_OF_THERMAL (11) +#define PSU1_ID (1) +#define PSU2_ID (2) +#define PSU_NUM_LENGTH (15) +#define MAX_FRONT_FAN_SPEED (23000) +#define MAX_PSU_FAN_SPEED (18380) +#define MAX_REAR_FAN_SPEED (20500) +#define FAN_ZERO_RPM (960) +#define FAN_SPEED_NORMALLY (4) +#define ALL_FAN_TRAY_EXIST (4) +#define BMC_OFF (1) +#define BMC_ON (0) +#define PSU_NODE_MAX_PATH_LEN (64) + +#define CPU_CPLD_VERSION "/sys/devices/platform/delta-agc7648sv1-cpld.0/cpuld_ver" +#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0053/eeprom" +#define SWPLD1_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0" +#define SWPLD2_PATH "/sys/devices/platform/delta-agc7648sv1-swpld2.0" +#define FAN1_FRONT "/sys/bus/i2c/devices/i2c-25/25-002c/fan4_input" +#define FAN1_REAR "/sys/bus/i2c/devices/i2c-25/25-002d/fan4_input" +#define FAN2_FRONT "/sys/bus/i2c/devices/i2c-25/25-002c/fan3_input" +#define FAN2_REAR "/sys/bus/i2c/devices/i2c-25/25-002d/fan3_input" +#define FAN3_FRONT "/sys/bus/i2c/devices/i2c-25/25-002c/fan2_input" +#define FAN3_REAR "/sys/bus/i2c/devices/i2c-25/25-002d/fan2_input" +#define FAN4_FRONT "/sys/bus/i2c/devices/i2c-25/25-002c/fan1_input" +#define FAN4_REAR "/sys/bus/i2c/devices/i2c-25/25-002d/fan1_input" +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define SFP_SELECT_PORT_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_select_port" +#define SFP_IS_PRESENT_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_is_present" +#define SFP_IS_PRESENT_ALL_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_is_present_all" +#define SFP_RX_LOS_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_rx_los" +#define SFP_RX_LOS_ALL_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_rx_los_all" +#define SFP_TX_DISABLE_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_tx_disable" +#define SFP_TX_FAULT_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_tx_fault" +#define QSFP_RESET_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_reset" +#define QSFP_LP_MODE_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/sfp_lp_mode" +#define PREFIX_PATH "/sys/bus/i2c/devices/" +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/31-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/32-0058/" +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node +#define FAN1_PRESENT_PATH "/sys/class/gpio/gpio499/value" +#define FAN2_PRESENT_PATH "/sys/class/gpio/gpio498/value" +#define FAN3_PRESENT_PATH "/sys/class/gpio/gpio497/value" +#define FAN4_PRESENT_PATH "/sys/class/gpio/gpio496/value" +#define PSU1_PRESENT_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/psu1_present" +#define PSU2_PRESENT_PATH "/sys/devices/platform/delta-agc7648sv1-swpld1.0/psu2_present" + +/* REG define */ +#define SWPLD_1_ADDR (0x6A) +#define SWPLD_2_ADDR (0x75) +#define SWPLD_3_ADDR (0x73) +#define PSU_EEPROM (0x50) +#define FAN_TRAY_1 (0x52) +#define FAN_TRAY_2 (0x53) +#define FAN_TRAY_3 (0x54) +#define FAN_TRAY_4 (0x55) +#define FAN_IO_CTL (0x27) +#define SYS_LED_REGISTER (0x1C) +#define FAN_LED_REGISTER (0x65) +#define POWER_STATUS_REGISTER (0x0B) +#define POWER_INT_REGISTER (0x0E) +#define DEFAULT_FLAG (0x00) + +/* BMC BUS define */ +#define BMC_SWPLD_BUS (2) + +/* SFP REG define */ +#define SFP_RESPOND_1 (0x0A) +#define SFP_RESPOND_2 (0x0B) +#define SFP_RESPOND_3 (0x0C) +#define SFP_RESPOND_4 (0x0D) + +typedef struct mux_info_s +{ + uint8_t offset; + uint8_t channel; + char dev_data[10]; + uint32_t flags; + +}mux_info_t; + +typedef struct dev_info_s +{ + int bus; + int size; + uint8_t addr; + uint8_t data_8; + uint16_t data_16; + uint8_t offset; + uint32_t flags; + +}dev_info_t; + +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len); +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data); +int dni_lock_cpld_read_attribute(char *cpld_path, int addr); +int dni_fan_present(int id); +int dni_fan_speed_good(); +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len); +int dni_bmc_sensor_read(char *device_name, UINT4 *num, UINT4 multiplier); +int dni_psui_eeprom_info_get(char *r_data,char *device_name,int number); +int dni_bmc_check(); +int dni_bmc_fanpresent_info_get(int *r_data); +int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info); +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath); +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath); +int dni_psu_present(int *r_data); +int dni_bmc_data_get(int bus, int addr, int reg, int len, int *r_data); +void lockinit(); + +char dev_name[50][32]; +float dev_sensor[50]; + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_1_ON_FAN_BOARD, + THERMAL_2_ON_CPU_BOARD, + THERMAL_3_ON_MAIN_BOARD_TEMP_1, + THERMAL_4_ON_MAIN_BOARD_TEMP_2, + THERMAL_5_ON_MAIN_BOARD_TEMP_1, + THERMAL_6_ON_MAIN_BOARD_TEMP_2, + THERMAL_7_ON_MAIN_BOARD_TEMP_3, + THERMAL_8_ON_MAIN_BOARD, + THERMAL_9_ON_MAIN_BOARD, + THERMAL_10_ON_PSU1, + THERMAL_11_ON_PSU2 +}; + +typedef enum +{ + FAN_RESERVED = 0, + FAN_1_ON_FAN_BOARD, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD, + FAN_6_ON_FAN_BOARD, + FAN_7_ON_FAN_BOARD, + FAN_8_ON_FAN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2 +} onlp_fan_id; + +typedef enum +{ + LED_RESERVED = 0, + LED_FRONT_FAN, + LED_FRONT_PWR, + LED_FRONT_SYS, + LED_REAR_FAN_TRAY_1, + LED_REAR_FAN_TRAY_2, + LED_REAR_FAN_TRAY_3, + LED_REAR_FAN_TRAY_4 +}onlp_led_id; + +enum bus +{ + I2C_BUS_0 = 0, + I2C_BUS_1, + I2C_BUS_2, + I2C_BUS_3, + I2C_BUS_4, + I2C_BUS_5, + I2C_BUS_6, + I2C_BUS_7, + I2C_BUS_8, + I2C_BUS_9, + I2C_BUS_10, + I2C_BUS_11, + I2C_BUS_21 = 21, + I2C_BUS_22, + I2C_BUS_23, + I2C_BUS_24, + I2C_BUS_25, + I2C_BUS_26, + I2C_BUS_27, + I2C_BUS_31 = 31, + I2C_BUS_32 +}; +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/psui.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..9cf7906e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/psui.c @@ -0,0 +1,314 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include "x86_64_delta_agc7648sv1_int.h" +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +static int dni_psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = ONLP_STATUS_OK; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + switch (id) { + case PSU1_ID: + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + break; + case PSU2_ID: + sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + break; + default: + break; + } + /* Read attribute value */ + *value = dni_i2c_lock_read_attribute(NULL, node_path); + + return ret; +} + +int onlp_psui_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +static int dni_psu_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int i = 0; + int ret = ONLP_STATUS_OK; + int local_id; + char device_name[10] = {0}; + UINT4 u4Data = 0; + UINT4 multiplier = 1000; + char name[20] = {0}; + char name1[20] = {0}; + char *module_name = name; + char *module_name1 = name1; + int val = 0; + char val_char[16] = {'\0'}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {'\0'}; + + local_id = ONLP_OID_ID_GET(info->hdr.id); + + /* Set the associated oid_table + * Set PSU's fan and thermal to child OID */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(local_id + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(local_id + CHASSIS_THERMAL_COUNT); + if(dni_bmc_check() == BMC_ON) + { + /* get psu model name */ + if(dni_psui_eeprom_info_get(name, "Product Name", local_id) == ONLP_STATUS_OK) + { + for(i = 0; i < PSU_NUM_LENGTH; i++) + name[i] = *(module_name + i); + strcpy(info->model, module_name); + } + else + strcpy(info->model, "ONLP_STATUS_E_UNSUPPORTED"); + + /* get psu serial number */ + if(dni_psui_eeprom_info_get(name1, "Product Serial", local_id) == ONLP_STATUS_OK) + { + for(i = 0; i < PSU_NUM_LENGTH; i++) + name1[i] = *(module_name1 + i); + strcpy(info->serial, module_name1); + } + else + strcpy(info->serial, "ONLP_STATUS_E_UNSUPPORTED"); + + /* get psu Vin/Vout */ + sprintf(device_name, "PSU%d_Vin", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->mvin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VIN; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + + sprintf(device_name, "PSU%d_Vout", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->mvout = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + + /* get psu Iin/Iout */ + sprintf(device_name, "PSU%d_Iin", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->miin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_IIN; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + + sprintf(device_name, "PSU%d_Iout", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->miout = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + + /* get psu Pin/Pout */ + sprintf(device_name, "PSU%d_Pin", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->mpin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_PIN; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + + sprintf(device_name, "PSU%d_Pout", local_id); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + info->mpout = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_POUT; + } + else + info->caps |= ONLP_PSU_STATUS_UNPLUGGED; + } + else + { + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Read PSU product name from attribute */ + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_model"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->model, val_char); + + /* Read PSU serial number from attribute */ + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_serial"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->serial, val_char); + + /* Read voltage, current and power */ + if (dni_psu_pmbus_info_get(index, "psu_v_in", &val) == 0) + { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_v_out", &val) == 0) + { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_i_in", &val) == 0) + { + info->miin = val; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_i_out", &val) == 0) + { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_in", &val) == 0) + { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_out", &val) == 0) + { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + } + return ret; +} + +int onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + char device_name[10] = {0}; + UINT4 u4Data = 0; + UINT4 multiplier = 1000; + int psu_present = -1; + + VALIDATE(id); + + /* Set the onlp_oid_hdr_t */ + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; + + switch (index) { + case PSU1_ID: + psu_present = dni_i2c_lock_read_attribute(NULL, PSU1_PRESENT_PATH); + break; + case PSU2_ID: + psu_present = dni_i2c_lock_read_attribute(NULL, PSU2_PRESENT_PATH); + break; + default: + break; + } + + if(dni_bmc_check() == BMC_ON) + { + /* Check PSU have voltage input or not */ + sprintf(device_name, "PSU%d_Vin", index); + if(dni_bmc_sensor_read(device_name, &u4Data, multiplier) == ONLP_STATUS_OK) + { + if(u4Data == 0) + { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; + } + info->mpin = u4Data; + info->status = ONLP_PSU_STATUS_PRESENT; + info->caps |= ONLP_PSU_CAPS_VIN; + } + } + else + { + /* Check PSU have voltage input or not */ + dni_psu_pmbus_info_get(index, "psu_v_in", &val); + + /* Check PSU is PRESENT or not */ + if(psu_present == 0) + info->status |= ONLP_PSU_STATUS_PRESENT; + else if(val == 0 && psu_present == 1) + { + /* PSU is not PRESENT */ + /* Able to read PSU VIN(psu_power_not_good) */ + info->status |= ONLP_PSU_STATUS_FAILED; + return ret; + } + else + { + /* Unable to read PSU VIN(psu_power_good) */ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } + } + + ret = dni_psu_info_get(id, info); + return ret; +} + +int onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..7ecd9892 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,467 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +/******************* Utility Function *****************************************/ +int sfp_map_bus[] = { + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, /* SFP */ + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, /* SFP */ + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, /* SFP */ + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, /* SFP */ + 91, 92, 93, 94, 95, 96, 97, 98, /* SFP */ + 41, 42, 43, 44, 45, 46, /* QSFP */ +}; + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int onlp_sfpi_init(void) +{ + /* Called at initialization time */ + lockinit(); + return ONLP_STATUS_OK; +} + +int onlp_sfpi_map_bus_index(int port) +{ + if(port < 0 || port > 54) + return ONLP_STATUS_E_INTERNAL; + return sfp_map_bus[port-1]; +} + +int onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* Ports {1, 54} */ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 1; p <= NUM_OF_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + return ONLP_STATUS_OK; +} + +int onlp_sfpi_is_present(int port) +{ + char port_data[3] = {'\0'}; + int present, present_bit; + + if(port > 0 && port < 55) + { + /* Select QSFP/SFP port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_ERROR("Unable to select port(%d)\r\n", port); + } + + /* Read QSFP/SFP MODULE is present or not */ + present_bit = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH); + if(present_bit < 0){ + AIM_LOG_ERROR("Unable to read present or not from port(%d)\r\n", port); + } + } + + /* From sfp_is_present value, + * return 0 = The module is preset + * return 1 = The module is NOT present */ + if(present_bit == 0) { + present = 1; + } else if (present_bit == 1) { + present = 0; + AIM_LOG_ERROR("Unble to present status from port(%d)\r\n", port); + } else { + /* Port range over 1-54, return -1 */ + AIM_LOG_ERROR("Error to present status from port(%d)\r\n", port); + present = -1; + } + return present; +} + +int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + char present_all_data[21] = {'\0'}; + char *r_byte; + char *r_array[7]; + uint8_t bytes[7] = {0}; + int count = 0; + + /* Read presence bitmap from SWPLD2 SFP+ and SWPLD1 QSFP28 Presence Register + * if only port 0 is present, return 3F FF FF FF FF FF FE + * if only port 0 and 1 present, return 3F FF FF FF FF FF FC */ + + if(dni_i2c_read_attribute_string(SFP_IS_PRESENT_ALL_PATH, present_all_data, + sizeof(present_all_data), 0) < 0) { + return -1; + } + + /* String split */ + r_byte = strtok(present_all_data, " "); + while (r_byte != NULL) { + r_array[count++] = r_byte; + r_byte = strtok(NULL, " "); + } + + /* Convert a string to unsigned 8 bit integer + * and saved into bytes[] */ + for (count = 0; count < 7; count++) { + bytes[count] = ~strtol(r_array[count], NULL, 16); + } + + /* Mask out non-existant SFP/QSFP ports */ + bytes[0] &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0; + + for(i = 0; i < AIM_ARRAYSIZE(bytes); i++) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap & remap */ + for(i = 0; presence_all; i++) + { + AIM_BITMAP_MOD(dst, i+1, (presence_all & 1)); + presence_all >>= 1; + } + return ONLP_STATUS_OK; +} + +int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + int size = 0; + + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return ONLP_STATUS_OK; +} + +int onlp_sfpi_port_map(int port, int* rport) +{ + *rport = port; + return ONLP_STATUS_OK; +} + +int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int value_t; + char port_data[3] = {'\0'}; + + if(port > 0 && port < 55) + { + /* Select SFP(1-48), QSFP(49-54) port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + /* From sfp_reset value, + * return 0 = The module is in Reset + * return 1 = The module is NOT in Reset */ + *value = dni_i2c_lock_read_attribute(NULL, QSFP_RESET_PATH); + if (*value == 0) + { + *value = 1; + } + else if (*value == 1) + { + *value = 0; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + /* From sfp_rx_los value, + * return 0 = The module is Normal Operation + * return 1 = The module is Error */ + *value = dni_i2c_lock_read_attribute(NULL, SFP_RX_LOS_PATH); + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + /* From sfp_tx_disable value, + * return 0 = The module is Enable Transmitter on + * return 1 = The module is Transmitter Disabled */ + *value = dni_i2c_lock_read_attribute(NULL, SFP_TX_DISABLE_PATH); + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_TX_FAULT: + /* From sfp_tx_fault value, + * return 0 = The module is Normal + * return 1 = The module is Fault */ + *value = dni_i2c_lock_read_attribute(NULL, SFP_TX_FAULT_PATH); + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_LP_MODE: + /* From sfp_lp_mode value, + * return 0 = The module is NOT in LP mode + * return 1 = The module is in LP mode */ + *value = dni_i2c_lock_read_attribute(NULL, QSFP_LP_MODE_PATH); + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return value_t; +} + +int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int value_t; + char port_data[3] = {'\0'}; + + if(port > 0 && port < 55) + { + /* Select SFP(1-48), QSFP(49-54) port */ + sprintf(port_data, "%d", port ); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + sprintf(port_data, "%d", value); + if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_RESET_PATH) < 0){ + AIM_LOG_INFO("Unable to control reset state from port(%d)\r\n", port); + value_t = ONLP_STATUS_E_INTERNAL; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + sprintf(port_data, "%d", value); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_TX_DISABLE_PATH) < 0){ + AIM_LOG_INFO("Unable to control tx disable from port(%d)\r\n", port); + value_t = ONLP_STATUS_E_INTERNAL; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_TX_FAULT: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_LP_MODE: + sprintf(port_data, "%d", value); + if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_LP_MODE_PATH) < 0){ + AIM_LOG_INFO("Unable to control LP mode from port(%d)\r\n", port); + value_t = ONLP_STATUS_E_INTERNAL; + } + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return value_t; +} + +int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); + +} + +int onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus; + + bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + char port_data[3] = {'\0'}; + + if(port > 0 && port < 55) + { + /* Select SFP(1-48), QSFP(49-54) port */ + sprintf(port_data, "%d", port); + if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ + AIM_LOG_INFO("Unable to select port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + } + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + if(port > 48 && port < 55) /* QSFP */ + *rv = 1; + else + *rv = 0; + break; + case ONLP_SFP_CONTROL_RX_LOS: + if(port > 0 && port < 49) /* SFP */ + *rv = 1; + else + *rv = 0; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + if(port > 0 && port < 49) /* SFP */ + *rv = 1; + else + *rv = 0; + break; + case ONLP_SFP_CONTROL_TX_FAULT: + if(port > 0 && port < 49) /* SFP */ + *rv = 1; + else + *rv = 0; + break; + case ONLP_SFP_CONTROL_LP_MODE: + if(port > 48 && port < 55) /* QSFP */ + *rv = 1; + else + *rv = 0; + break; + default: + break; + } + return ONLP_STATUS_OK; +} + +int onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + +int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + char rxlos_all_data[18] = {'\0'}; + char *r_byte; + char *r_array[6]; + uint8_t bytes[6] = {0}; + int count = 0; + + /* Read rx_los bitmap from SWPLD2 SFP+ LOSS Register + * if only port 0 is normal operation, return FF FF FF FF FF FE + * if only port 0 and 1 normal operation, return FF FF FF FF FF FC */ + + if(dni_i2c_read_attribute_string(SFP_RX_LOS_ALL_PATH, rxlos_all_data, + sizeof(rxlos_all_data), 0) < 0) { + return -1; + } + + /* String split */ + r_byte = strtok(rxlos_all_data, " "); + while (r_byte != NULL) { + r_array[count++] = r_byte; + r_byte = strtok(NULL, " "); + } + + /* Convert a string to unsigned 8 bit integer + * and saved into bytes[] */ + for (count = 0; count < 6; count++) { + bytes[count] = strtol(r_array[count], NULL, 16); + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t rxlos_all = 0; + + for(i = 0; i < AIM_ARRAYSIZE(bytes); i++) { + rxlos_all <<= 8; + rxlos_all |= bytes[i]; + } + + for(i = 0; i < 48; i++) + { + AIM_BITMAP_MOD(dst, i+1, (rxlos_all & 1)); + rxlos_all >>= 1; + } + + /* Mask out non-existant QSFP ports */ + for(i = 48; i < 54; i++) + AIM_BITMAP_MOD(dst, i+1, 0); + + return ONLP_STATUS_OK; +} + +int onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_OK; +} + +int onlp_sfpi_post_insert(int port, sff_info_t* info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +void onlp_sfpi_debug(int port, aim_pvs_t* pvs) +{ +} + +int onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sysi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..f9f78e85 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,351 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_delta_agc7648sv1_int.h" +#include "x86_64_delta_agc7648sv1_log.h" +#include "platform_lib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int decide_percentage(int *percentage, int temper) +{ + int level; + + if(temper <= 50) + { + *percentage = 50; + level = 1; + } + else if(temper > 50 && temper <= 55) + { + *percentage = 58; + level = 2; + } + else if(temper > 55 && temper <= 60) + { + *percentage = 65; + level = 3; + } + else if(temper > 60 && temper <= 65) + { + *percentage = 80; + level = 4; + } + else if(temper > 65) + { + *percentage = 100; + level = 5; + } + else + { + *percentage = 100; + level = 6; + } + + return level; +} + +const char* onlp_sysi_platform_get(void) +{ + return "x86-64-delta-agc7648sv1-r0"; +} + +int onlp_sysi_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +int onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) + { + if(*size == 256) + { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int cpld_version = 6; + cpld_version = dni_i2c_lock_read_attribute(NULL, CPU_CPLD_VERSION); + pi->cpld_versions = aim_fstrdup("%d", cpld_version); + + return ONLP_STATUS_OK; +} + +void onlp_sysi_onie_data_free(uint8_t* data) +{ + aim_free(data); +} + +void onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +int onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i = 0; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return ONLP_STATUS_OK; +} + +int onlp_sysi_platform_manage_fans(void) +{ + int i, new_percentage, highest_temp = 0; + onlp_thermal_info_t thermal; + int rv; + + if(dni_bmc_check() == BMC_ON) + { + rv = ONLP_STATUS_OK; + } + else{ + /* Get all thermal current temperature and decide fan percentage */ + for(i = 1; i <= NUM_OF_THERMAL; ++i) + { + if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + + thermal.mcelsius /= 1000; + if(thermal.mcelsius > highest_temp) + { + highest_temp = thermal.mcelsius; + } + decide_percentage(&new_percentage, highest_temp); + } + + /* Set fantray RPM and PSU fan percentage */ + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_1_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_2_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_3_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_4_ON_FAN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_5_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_6_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_7_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_8_ON_FAN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1), new_percentage); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2), new_percentage); + + rv = ONLP_STATUS_OK; + } + return rv; +} + +int onlp_sysi_platform_manage_leds(void) +{ + int rpm = 0, rpm1 = 0, count = 0; + int rv; + int fantray_count; + char fantray_count_str[2] = {'\0'}; + uint8_t psu_state; + int psu_pwr_status = 0; + int psu_pwr_int = 0; + int fantray_present = -1; + char fullpath[50] = {'\0'}; + + if(dni_bmc_check() == BMC_ON) + { + rv = ONLP_STATUS_OK; + } + else { + /* Fan tray 1 */ + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN1_PRESENT_PATH); + rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); + + if(fantray_present == 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 2 */ + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN2_PRESENT_PATH); + rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); + + if(fantray_present == 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 3 */ + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN3_PRESENT_PATH); + rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); + + if(fantray_present == 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 4 */ + fantray_present = dni_i2c_lock_read_attribute(NULL, FAN4_PRESENT_PATH); + rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); + + if(fantray_present == 0 && rpm != FAN_ZERO_RPM && rpm != 0 && rpm1 != FAN_ZERO_RPM && rpm1 != 0 ) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Red */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4),ONLP_LED_MODE_RED) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* FRONT FAN & SYS LED */ + for(fantray_count = 9; fantray_count > 5 ; fantray_count--) + { + sprintf(fantray_count_str, "%d", fantray_count); + sprintf(fullpath, "/sys/class/gpio/gpio49%s/value", fantray_count_str); + fantray_present = dni_i2c_lock_read_attribute(NULL, fullpath); + if(fantray_present == 0) + count++; + } + + if(count == ALL_FAN_TRAY_EXIST && dni_fan_speed_good() == FAN_SPEED_NORMALLY) + { + /* Green */ + if((onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) || + (onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_SYS),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK)) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Solid Amber FAN or more failed*/ + if((onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN),ONLP_LED_MODE_YELLOW) != ONLP_STATUS_OK) || + (onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_SYS),ONLP_LED_MODE_YELLOW) != ONLP_STATUS_OK)) + rv = ONLP_STATUS_E_INTERNAL; + } + + /* Set front light of PWR */ + psu_state = dni_i2c_lock_read_attribute(NULL, PSU1_PRESENT_PATH); + psu_pwr_status = dni_lock_cpld_read_attribute(SWPLD1_PATH,POWER_STATUS_REGISTER); + psu_pwr_int = dni_lock_cpld_read_attribute(SWPLD1_PATH,POWER_INT_REGISTER); + + if(psu_state == 0 && (psu_pwr_status & 0x80) == 0x80 && (psu_pwr_int & 0x10) == 0x10) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Amber */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR),ONLP_LED_MODE_YELLOW) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + + psu_state = dni_i2c_lock_read_attribute(NULL, PSU2_PRESENT_PATH); + + if(psu_state == 0 && (psu_pwr_status & 0x40) == 0x40 && (psu_pwr_int & 0x20) == 0x20) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR),ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + /* Amber */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR),ONLP_LED_MODE_YELLOW) != ONLP_STATUS_OK) + rv = ONLP_STATUS_E_INTERNAL; + } + rv = ONLP_STATUS_OK; + } + return rv; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/thermali.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..1a232070 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,227 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 (C) Delta Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ + +#include "platform_lib.h" +#include +#include +#include "x86_64_delta_agc7648sv1_log.h" + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define dni_onlp_thermal_threshold(WARNING_DEFAULT, ERROR_DEFAULT, SHUTDOWN_DEFAULT){ \ + WARNING_DEFAULT, \ + ERROR_DEFAULT, \ + SHUTDOWN_DEFAULT, \ +} +static char* path[] = /* must map with onlp_thermal_id */ +{ + "reserved", + "26-004f/hwmon/hwmon6/temp1_input", + "8-004b/hwmon/hwmon1/temp1_input", + "8-004c/hwmon/hwmon2/temp1_input", + "8-004c/hwmon/hwmon2/temp2_input", + "8-004d/hwmon/hwmon3/temp1_input", + "8-004d/hwmon/hwmon3/temp2_input", + "8-004d/hwmon/hwmon3/temp3_input", + "8-004e/hwmon/hwmon4/temp1_input", + "8-004f/hwmon/hwmon5/temp1_input", + "31-0058/psu_temp1_input", + "32-0058/psu_temp1_input" +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_FAN_BOARD), "Board sensor on Fan_BD", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_CPU_BOARD), "Board sensor near CPU", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BOARD_TEMP_1), "Board sensor near MAC temp-1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BOARD_TEMP_2), "Board sensor near MAC temp-2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BOARD_TEMP_1), "Board sensor near SyncE temp-1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BOARD_TEMP_2), "Board sensor near SyncE temp-2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_7_ON_MAIN_BOARD_TEMP_3), "Board sensor near SyncE temp-3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_8_ON_MAIN_BOARD), "Board sensor near MAC", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_9_ON_MAIN_BOARD), "Board sensor near MAC", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_10_ON_PSU1), "PSU-1 internal sensor", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_11_ON_PSU2), "PSU-2 internal Sensor", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + lockinit(); + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + uint8_t local_id = 0; + UINT4 multiplier = 1000; + UINT4 u4Data = 0; + char device_buf[20] = {0}; + int temp_base = 1; + int rv; + char fullpath[50] = {0}; + int r_data = 0; + + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + + if(dni_bmc_check() == BMC_ON) + { + switch(local_id) { + case THERMAL_1_ON_FAN_BOARD: + sprintf(device_buf, "Fan_Temp"); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + case THERMAL_2_ON_CPU_BOARD: + case THERMAL_3_ON_MAIN_BOARD_TEMP_1: + case THERMAL_4_ON_MAIN_BOARD_TEMP_2: + case THERMAL_5_ON_MAIN_BOARD_TEMP_1: + case THERMAL_6_ON_MAIN_BOARD_TEMP_2: + case THERMAL_7_ON_MAIN_BOARD_TEMP_3: + case THERMAL_8_ON_MAIN_BOARD: + case THERMAL_9_ON_MAIN_BOARD: + local_id--; + sprintf(device_buf, "Temp_Sensor_%d", local_id); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + case THERMAL_10_ON_PSU1: + sprintf(device_buf, "PSU1_Temp_1"); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + case THERMAL_11_ON_PSU2: + sprintf(device_buf, "PSU2_Temp_1"); + rv = dni_bmc_sensor_read(device_buf, &u4Data, multiplier); + break; + default: + AIM_LOG_ERROR("Invalid Thermal ID!!\n"); + return ONLP_STATUS_E_PARAM; + } + + if (u4Data == 0 || rv == ONLP_STATUS_E_GENERIC){ + return ONLP_STATUS_E_INTERNAL; + } + else{ + info->mcelsius = u4Data; + return 0; + } + } + else + { + switch (local_id) { + case THERMAL_1_ON_FAN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_2_ON_CPU_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_3_ON_MAIN_BOARD_TEMP_1: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_4_ON_MAIN_BOARD_TEMP_2: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_5_ON_MAIN_BOARD_TEMP_1: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_6_ON_MAIN_BOARD_TEMP_2: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_7_ON_MAIN_BOARD_TEMP_3: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_8_ON_MAIN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_9_ON_MAIN_BOARD: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_10_ON_PSU1: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + case THERMAL_11_ON_PSU2: + sprintf(fullpath,"%s%s", PREFIX_PATH, path[local_id]); + break; + } + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + info->mcelsius = r_data / temp_base; + } + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_config.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_config.c new file mode 100755 index 00000000..421e2320 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_config.c @@ -0,0 +1,91 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(_x) __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(_x) +x86_64_delta_agc7648sv1_config_settings_t x86_64_delta_agc7648sv1_config_settings[] = +{ +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_LOGGING(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_STDLIB(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_SFP_COUNT(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX + { __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME(X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX), __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE(X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX) }, +#else +{ X86_64_DELTA_AGC7648SV1_CONFIG_FAN_RPM_MAX(__x86_64_delta_agc7648sv1_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_delta_agc7648sv1_config_STRINGIFY_VALUE +#undef __x86_64_delta_agc7648sv1_config_STRINGIFY_NAME + +const char* +x86_64_delta_agc7648sv1_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_delta_agc7648sv1_config_settings[i].name; i++) { + if(!strcmp(x86_64_delta_agc7648sv1_config_settings[i].name, setting)) { + return x86_64_delta_agc7648sv1_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_delta_agc7648sv1_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_delta_agc7648sv1_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_delta_agc7648sv1_config_settings[i].name, x86_64_delta_agc7648sv1_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_enums.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_enums.c new file mode 100644 index 00000000..5ce2fa14 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_int.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_int.h new file mode 100644 index 00000000..6b86597d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_delta_agc7648sv1 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648sv1_INT_H__ +#define __x86_64_delta_agc7648sv1_INT_H__ + +#include + + +#endif /* __x86_64_delta_agc7648sv1_INT_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.c new file mode 100755 index 00000000..59daed67 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_agc7648sv1_log.h" +/* + * x86_64_delta_agc7648sv1 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_DELTA_AGC7648SV1_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_DELTA_AGC7648SV1_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_DELTA_AGC7648SV1_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.h new file mode 100644 index 00000000..66de4fcd --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648sv1_LOG_H__ +#define __x86_64_delta_agc7648sv1_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_delta_agc7648sv1 +#include + +#endif /* __x86_64_delta_agc7648sv1_LOG_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_module.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_module.c new file mode 100644 index 00000000..85efe84f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_agc7648sv1_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_delta_agc7648sv1_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_delta_agc7648sv1_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_ucli.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_ucli.c new file mode 100755 index 00000000..8746e060 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/onlp/builds/src/module/src/x86_64_delta_agc7648sv1_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_DELTA_AGC7648SV1_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_delta_agc7648sv1_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_delta_agc7648sv1) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_delta_agc7648sv1_ucli_module__ = + { + "x86_64_delta_agc7648sv1_ucli", + NULL, + x86_64_delta_agc7648sv1_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_delta_agc7648sv1_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_delta_agc7648sv1_ucli_module__); + n = ucli_node_create("x86_64_delta_agc7648sv1", NULL, &x86_64_delta_agc7648sv1_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_delta_agc7648sv1")); + return n; +} + +#else +void* +x86_64_delta_agc7648sv1_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/PKG.yml new file mode 100644 index 00000000..ffa172f2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/PKG.yml @@ -0,0 +1,2 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=delta BASENAME=x86-64-delta-agc7648sv1 REVISION=r0 + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/lib/x86-64-delta-agc7648sv1-r0.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/lib/x86-64-delta-agc7648sv1-r0.yml new file mode 100755 index 00000000..437129a5 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/lib/x86-64-delta-agc7648sv1-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AGC7648SV1 +# +###################################################################### + +x86-64-delta-agc7648sv1-r0: + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-9 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/python/x86_64_delta_agc7648sv1_r0/__init__.py b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/python/x86_64_delta_agc7648sv1_r0/__init__.py new file mode 100755 index 00000000..adaa869e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648sv1/platform-config/r0/src/python/x86_64_delta_agc7648sv1_r0/__init__.py @@ -0,0 +1,42 @@ +from onl.platform.base import * +from onl.platform.delta import * +import os.path + +class OnlPlatform_x86_64_delta_agc7648sv1_r0(OnlPlatformDelta, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-delta-agc7648sv1-r0' + MODEL="AGC7648SV1" + SYS_OBJECT_ID=".7648.1" + + + def baseconfig(self): + #Remove and rescan bus + os.system("echo 1 > /sys/bus/i2c/devices/i2c-0/firmware_node/physical_node/remove") + os.system("echo 1 > /sys/bus/pci/rescan") + + #Insert gpio_pca953x module + os.system('modprobe gpio_pca953x') + + #Insert tmp401(tmp431/tmp432) module + os.system('modprobe tmp401') + + #Insert platform module + self.insmod('delta_agc7648sv1_platform') + + #Insert psu module + self.insmod('dni_agc7648sv1_psu') + + #Insert fan module + self.insmod('dni_emc2305') + + #Insert qsfp mosule + self.insmod('optoe') + + #Fantray present(fan1:499, fan2:498, fan3:497, fan4:496) + os.system("echo 496 > /sys/class/gpio/export") + os.system("echo 497 > /sys/class/gpio/export") + os.system("echo 498 > /sys/class/gpio/export") + os.system("echo 499 > /sys/class/gpio/export") + + return True + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/delta_ak7448_platform.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/delta_ak7448_platform.c new file mode 100644 index 00000000..cdd078ac --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/delta_ak7448_platform.c @@ -0,0 +1,1439 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPLD_A_REG 0x33 +#define CPLD_B_REG 0x32 +#define BUS3_MUX_REG 0x11 +#define BUS8_MUX_REG 0x19 + +#define QSFP_P0_VAL 0x04 +#define QSFP_P1_VAL 0x03 +#define QSFP_P2_VAL 0x02 +#define QSFP_P3_VAL 0x00 + +#define SFP_PRESENCE_1 0x02 +#define SFP_PRESENCE_2 0x03 +#define SFP_PRESENCE_3 0x04 +#define SFP_PRESENCE_4 0x05 +#define SFP_PRESENCE_5 0x06 +#define SFP_PRESENCE_6 0x07 +#define QSFP_PRESENCE_1 0x0d +#define QSFP_LP_MODE_1 0x0c +#define QSFP_RESET_1 0x0e + +#define DEFAULT_DISABLE 0x00 +#define QSFP_DEFAULT_DISABLE 0x01 + +#define BUS3_DEV_NUM 4 +#define BUS8_DEV_NUM 48 +#define DEFAULT_NUM 1 +#define BUS3_BASE_NUM 20 +#define BUS8_BASE_NUM 30 + +#define ak7448_i2c_device_num(NUM){ \ + .name = "delta-ak7448-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ak7448_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/* Check cpld read results */ +#define VALIDATED_READ(_buf, _rv, _read, _invert) \ + do { \ + _rv = _read; \ + if (_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if (_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) \ + + +/*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, + BUS8, +}; + +long sfp_port_data = 0; + +static LIST_HEAD(cpld_client_list); + +struct cpld_client_node +{ + struct i2c_client *client; + struct list_head list; +}; + +int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + list_for_each(list_node, &cpld_client_list){ + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if ((cpld_node->client->adapter->nr == bus) && (cpld_node->client->addr == cpld_addr) ){ + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + return ret; +} +EXPORT_SYMBOL(i2c_cpld_read); + +int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + list_for_each(list_node, &cpld_client_list){ + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if ((cpld_node->client->adapter->nr == bus) && (cpld_node->client->addr == cpld_addr) ){ + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(i2c_cpld_write); + +/*---------------- 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; +}; + +static struct i2c_device_platform_data ak7448_i2c_device_platform_data[] = { + { + /* qsfp 1 (0x50) */ + .parent = 20, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 21, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 22, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 23, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 1 (0x50) */ + .parent = 30, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 2 (0x50) */ + .parent = 31, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 3 (0x50) */ + .parent = 32, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 4 (0x50) */ + .parent = 33, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 5 (0x50) */ + .parent = 34, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 6 (0x50) */ + .parent = 35, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 7 (0x50) */ + .parent = 36, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 8 (0x50) */ + .parent = 37, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 9 (0x50) */ + .parent = 38, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 10 (0x50) */ + .parent = 39, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 11 (0x50) */ + .parent = 40, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 12 (0x50) */ + .parent = 41, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 13 (0x50) */ + .parent = 42, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 14 (0x50) */ + .parent = 43, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 15 (0x50) */ + .parent = 44, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 16 (0x50) */ + .parent = 45, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 17 (0x50) */ + .parent = 46, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 18 (0x50) */ + .parent = 47, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 19 (0x50) */ + .parent = 48, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 20 (0x50) */ + .parent = 49, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 21 (0x50) */ + .parent = 50, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 22 (0x50) */ + .parent = 51, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 23 (0x50) */ + .parent = 52, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 24 (0x50) */ + .parent = 53, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 25 (0x50) */ + .parent = 54, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 26 (0x50) */ + .parent = 55, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 27 (0x50) */ + .parent = 56, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 28 (0x50) */ + .parent = 57, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 29 (0x50) */ + .parent = 58, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 30 (0x50) */ + .parent = 59, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 31 (0x50) */ + .parent = 60, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 32 (0x50) */ + .parent = 61, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 33 (0x50) */ + .parent = 62, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 34 (0x50) */ + .parent = 63, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 35 (0x50) */ + .parent = 64, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 36 (0x50) */ + .parent = 65, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 37 (0x50) */ + .parent = 66, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 38 (0x50) */ + .parent = 67, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 39 (0x50) */ + .parent = 68, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 40 (0x50) */ + .parent = 69, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 41 (0x50) */ + .parent = 70, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 42 (0x50) */ + .parent = 71, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 43 (0x50) */ + .parent = 72, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 44 (0x50) */ + .parent = 73, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 45 (0x50) */ + .parent = 74, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 46 (0x50) */ + .parent = 75, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 47 (0x50) */ + .parent = 76, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 48 (0x50) */ + .parent = 77, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, +}; + + +static struct platform_device ak7448_i2c_device[] = { + ak7448_i2c_device_num(0), + ak7448_i2c_device_num(1), + ak7448_i2c_device_num(2), + ak7448_i2c_device_num(3), + ak7448_i2c_device_num(4), + ak7448_i2c_device_num(5), + ak7448_i2c_device_num(6), + ak7448_i2c_device_num(7), + ak7448_i2c_device_num(8), + ak7448_i2c_device_num(9), + ak7448_i2c_device_num(10), + ak7448_i2c_device_num(11), + ak7448_i2c_device_num(12), + ak7448_i2c_device_num(13), + ak7448_i2c_device_num(14), + ak7448_i2c_device_num(15), + ak7448_i2c_device_num(16), + ak7448_i2c_device_num(17), + ak7448_i2c_device_num(18), + ak7448_i2c_device_num(19), + ak7448_i2c_device_num(20), + ak7448_i2c_device_num(21), + ak7448_i2c_device_num(22), + ak7448_i2c_device_num(23), + ak7448_i2c_device_num(24), + ak7448_i2c_device_num(25), + ak7448_i2c_device_num(26), + ak7448_i2c_device_num(27), + ak7448_i2c_device_num(28), + ak7448_i2c_device_num(29), + ak7448_i2c_device_num(30), + ak7448_i2c_device_num(31), + ak7448_i2c_device_num(32), + ak7448_i2c_device_num(33), + ak7448_i2c_device_num(34), + ak7448_i2c_device_num(35), + ak7448_i2c_device_num(36), + ak7448_i2c_device_num(37), + ak7448_i2c_device_num(38), + ak7448_i2c_device_num(39), + ak7448_i2c_device_num(40), + ak7448_i2c_device_num(41), + ak7448_i2c_device_num(42), + ak7448_i2c_device_num(43), + ak7448_i2c_device_num(44), + ak7448_i2c_device_num(45), + ak7448_i2c_device_num(46), + ak7448_i2c_device_num(47), + ak7448_i2c_device_num(48), + ak7448_i2c_device_num(49), + ak7448_i2c_device_num(50), + ak7448_i2c_device_num(51), +}; + +/*---------------- 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 = i2c_get_adapter(pdata->parent); + 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-ak7448-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + cpld_a, + cpld_b, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ak7448_cpld_platform_data[] = { + [cpld_a] = { + .reg_addr = CPLD_A_REG, + }, + [cpld_b] = { + .reg_addr = CPLD_B_REG, + }, +}; + +static struct platform_device ak7448_cpld = { + .name = "delta-ak7448-cpld", + .id = 0, + .dev = { + .platform_data = ak7448_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf); + +enum ak7448_sfp_sysfs_attributes +{ + SFP_SELECT_PORT, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_RESET, + ADDR, + DATA, +}; + +static struct kobject *kobj_swpld; + +static ssize_t set_w_port_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); + struct device *i2cdev = kobj_to_dev(kobj_swpld); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if(error) + return error; + + /* Disable SFP channel */ + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, BUS8_MUX_REG, (u8)DEFAULT_DISABLE) < 0) { + return -EIO; + } + + /* Disable QSFP channel */ + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, BUS3_MUX_REG, (u8)QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + + sfp_port_data = data; + return count; +} + +static ssize_t for_r_port_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + 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; + + if (sfp_port_data == DEFAULT_DISABLE) + { + /* Disable SFP channel */ + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, BUS8_MUX_REG, (u8)DEFAULT_DISABLE) < 0) { + return -EIO; + } + + /* Disable QSFP channel */ + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, BUS3_MUX_REG, (u8)QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + } + + return sprintf(buf, "%d\n", sfp_port_data); + +} + +static ssize_t set_w_lp_mode_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); + struct device *i2cdev = kobj_to_dev(kobj_swpld); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + port_t = sfp_port_data; + + if (port_t > 48 && port_t < 53) + { /* QSFP Port 48-53 */ + values = i2c_smbus_read_byte_data(pdata[cpld_b].client, QSFP_LP_MODE_1); + if (values < 0) + return -EIO; + + /* Indicate the module is in LP mode or not + * 0 = Disable + * 1 = Enable + */ + if (data == 0) + { + bit_t = ~(1 << ((port_t - 1) % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = 1 << ((port_t - 1) % 8); + values = values | bit_t; + } + else + { + return -EINVAL; + } + + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, QSFP_LP_MODE_1, (u8)values) < 0) + { + return -EIO; + } + } + + return count; +} + +static ssize_t set_w_reset_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); + struct device *i2cdev = kobj_to_dev(kobj_swpld); + struct cpld_platform_data *pdata = i2cdev->platform_data; + long data; + int error; + long port_t = 0; + int bit_t = 0x00; + int values = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + port_t = sfp_port_data; + + if (port_t > 48 && port_t < 53) + { /* QSFP Port 48-53 */ + values = i2c_smbus_read_byte_data(pdata[cpld_b].client, QSFP_RESET_1); + if (values < 0) + return -EIO; + + /* Indicate the module Reset or not + * 0 = Reset + * 1 = Normal + */ + if (data == 0) + { + bit_t = ~(1 << ((port_t - 1) % 8)); + values = values & bit_t; + } + else if (data == 1) + { + bit_t = 1 << ((port_t - 1) % 8); + values = values | bit_t; + } + else + { + return -EINVAL; + } + + if (i2c_smbus_write_byte_data(pdata[cpld_b].client, QSFP_RESET_1, (u8)values) < 0) + { + return -EIO; + } + } + + return count; +} + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf){ + 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; + long port_t = 0; + u8 reg_t = 0x00; + u8 cpld_addr_t = 0x00; + int values[7] = {'\0'}; + int bit_t = 0x00; + + switch (attr->index) { + case SFP_IS_PRESENT: + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_PRESENCE_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_PRESENCE_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_PRESENCE_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_PRESENCE_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_PRESENCE_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_PRESENCE_6; + } else if (port_t > 48 && port_t < 53) { /* QSFP Port 49-54 */ + reg_t = QSFP_PRESENCE_1; + } else { + values[0] = 1; /* return 1, module NOT present */ + return sprintf(buf, "%d\n", values[0]); + } + + if(port_t > 48 && port_t < 53){ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata[cpld_b].client, reg_t), 0); + } + else{ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata[cpld_a].client, reg_t), 0); + } + + /* SWPLD QSFP module respond */ + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_is_present value + * return 0 is module present + * return 1 is module NOT present*/ + return sprintf(buf, "%d\n", values[0]); + + case SFP_IS_PRESENT_ALL: + /* + * Report the SFP ALL PRESENCE status + * This data information form CPLD.*/ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_1), 0); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_2), 0); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_3), 0); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_4), 0); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_5), 0); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], + i2c_smbus_read_byte_data(pdata[cpld_a].client, SFP_PRESENCE_6), 0); + /* QSFP_PRESENT Ports 49-52 */ + VALIDATED_READ(buf, values[6], + i2c_smbus_read_byte_data(pdata[cpld_b].client, QSFP_PRESENCE_1), 0); + + + /* sfp_is_present_all value + * return 0 is module present + * return 1 is module NOT present + */ + return sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X \n",values[0], values[1], values[2],values[3], values[4], values[5],values[6]); + case SFP_LP_MODE: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 53) { + /* QSFP Port 49-52 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata[cpld_b].client, QSFP_LP_MODE_1), 0); + } else { + /* In AK7448 only QSFP support control LP MODE */ + values[0] = 0; + return sprintf(buf, "%d\n", values[0]); + } + + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_lp_mode value + * return 0 is module NOT in LP mode + * return 1 is module in LP mode + */ + + return sprintf(buf, "%d\n", values[0]); + + case SFP_RESET: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 53) { + /* QSFP Port 49-54 */ + VALIDATED_READ(buf, values[0], i2c_smbus_read_byte_data(pdata[cpld_b].client, QSFP_RESET_1), 0); + } else { + /* In AK7448 only QSFP support control RESET MODE */ + values[0] = 1; + return sprintf(buf, "%d\n", values[0]); + } + + /* SWPLD QSFP module respond */ + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_reset value + * return 0 is module Reset + * return 1 is module Normal*/ + return sprintf(buf, "%d\n", values[0]); + + default: + return sprintf(buf, "%d not found", attr->index); + } +} + +static unsigned char swpld_reg_addr; + +static ssize_t +get_cpld_data(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = sprintf(buf, "0x%x\n",i2c_smbus_read_byte_data(pdata[cpld_b].client, swpld_reg_addr)); + return ret; +} + +static ssize_t +set_cpld_data(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cpld_platform_data *pdata = dev->platform_data; + unsigned int val; + char *endp; + char ret = -1; + + val = simple_strtoul(buf, &endp, 16); + if (isspace(*endp)){ + endp++; + } + + if (endp - buf != count){ + return -1; + } + + if (val > 255){ + return -1; + } + + ret = i2c_smbus_write_byte_data(pdata[cpld_b].client, swpld_reg_addr, val); + + return count; +} + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int len; + len = sprintf(buf, "0x%x\n", swpld_reg_addr); + return len; +} + +static ssize_t +set_cpld_reg(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int val; + char *endp; + + val = simple_strtoul(buf, &endp, 16); + if (isspace(*endp)){ + endp++; + } + + if (endp - buf != count){ + return -1; + } + + if (val > 255) + { + return -1; + } + swpld_reg_addr = val; + return count; +} + + +static SENSOR_DEVICE_ATTR(sfp_select_port, S_IWUSR | S_IRUGO, for_r_port_data, set_w_port_data, SFP_SELECT_PORT); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, for_status, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, for_status, set_w_lp_mode_data, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, for_status, set_w_reset_data, SFP_RESET); +static SENSOR_DEVICE_ATTR(data, S_IWUSR | S_IRUGO, get_cpld_data, set_cpld_data, DATA); +static SENSOR_DEVICE_ATTR(addr, S_IWUSR | S_IRUGO, get_cpld_reg, set_cpld_reg, ADDR); + + +static struct attribute *ak7448_cpld_attrs[] = { + &sensor_dev_attr_sfp_select_port.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_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + &sensor_dev_attr_data.dev_attr.attr, + &sensor_dev_attr_addr.dev_attr.attr, + NULL, +}; + +static struct attribute_group ak7448_cpld_attr_grp = { + .attrs = ak7448_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(BUS5); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS5); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(ak7448_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; + } + } + + kobj_swpld = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &ak7448_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld); + 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, &ak7448_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + kobject_put(kobj_swpld); + for (i = 0; i < ARRAY_SIZE(ak7448_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-ak7448-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 ak7448_swpld_mux_platform_data[] = { + { + .parent = BUS3, + .base_nr = BUS3_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS3_MUX_REG , + }, + { + .parent = BUS8, + .base_nr = BUS8_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS8_MUX_REG , + }, +}; + + +static struct platform_device ak7448_swpld_mux[] = { + { + .name = "delta-ak7448-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ak7448_swpld_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-ak7448-swpld-mux", + .id = 1, + .dev = { + .platform_data = &ak7448_swpld_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 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 = QSFP_P0_VAL; + break; + case 1: + swpld_mux_val = QSFP_P1_VAL; + break; + case 2: + swpld_mux_val = QSFP_P2_VAL; + break; + case 3: + swpld_mux_val = QSFP_P3_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS8_BASE_NUM ){ + if (chan < 16){ + swpld_mux_val = (u8)(chan); + } + else if (15 < chan && chan < 32){ + swpld_mux_val = (u8)(chan - 16) + 0x10; + } + else if (31 < chan && chan < 48){ + swpld_mux_val = (u8)(chan - 32) + 0x20; + } + else{ + swpld_mux_val = 0x00; + } + } + 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)); +} + +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 BUS8: + dev_num = BUS8_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; +} + + +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 BUS8: + dev_num = BUS8_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; +} + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ak7448-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + + +/*---------------- module initialization ------------- */ +static void __init delta_ak7448_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; + + // 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(&ak7448_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ak7448_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ak7448_cpld.dev.platform_data; + + for (i = 0; i < ARRAY_SIZE(ak7448_swpld_mux); i++){ + swpld_pdata = ak7448_swpld_mux[i].dev.platform_data; + swpld_pdata->cpld = cpld_pdata[cpld_b].client; + ret = platform_device_register(&ak7448_swpld_mux[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ak7448_swpld_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ak7448_i2c_device); i++) + { + ret = platform_device_register(&ak7448_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ak7448_i2c_device; + } + } + + if (ret) + goto error_ak7448_swpld_mux; + + return 0; + +error_ak7448_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ak7448_i2c_device[i]); + } + i = ARRAY_SIZE(ak7448_swpld_mux); +error_ak7448_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ak7448_swpld_mux[i]); + } + platform_driver_unregister(&ak7448_cpld); +error_ak7448_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_ak7448_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ak7448_i2c_device); i++ ) { + platform_device_unregister(&ak7448_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ak7448_swpld_mux); i++) { + platform_device_unregister(&ak7448_swpld_mux[i]); + } + + platform_device_unregister(&ak7448_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + +} + +module_init(delta_ak7448_platform_init); +module_exit(delta_ak7448_platform_exit); + +MODULE_DESCRIPTION("DNI ak7448 Platform Support"); +MODULE_AUTHOR("Johnson Lu "); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_psu.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_psu.c index a01354e4..1960e9ff 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_psu.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_psu.c @@ -131,10 +131,9 @@ static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ return -EINVAL; /* Select SWPLD PSU offset */ - i2c_cpld_write(SWPLD_BUS, SWPLD_REG, - SWPLD_PSU_MUX_REG, SELECT_PSU2_EEPROM); mutex_lock(&data->update_lock); + i2c_cpld_write(SWPLD_BUS, SWPLD_REG,SWPLD_PSU_MUX_REG, SELECT_PSU2_EEPROM); data->fan_duty_cycle[nr] = speed; dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); mutex_unlock(&data->update_lock); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_sfp.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_sfp.c deleted file mode 100755 index 1c69ed28..00000000 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_sfp.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * An hwmon driver for agema ak7448 qsfp - * - * Copyright (C) 2017 Delta Networks, Inc. - * - * DNI - * - * 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 I2C_BUS_5 5 -#define SWPLD_U21 0x30 -#define SWPLD_A 0x33 -#define SWPLD_B 0x32 - -#define SFP_PRESENCE_1 0x02 -#define SFP_PRESENCE_2 0x03 -#define SFP_PRESENCE_3 0x04 -#define SFP_PRESENCE_4 0x05 -#define SFP_PRESENCE_5 0x06 -#define SFP_PRESENCE_6 0x07 -#define QSFP_PRESENCE_1 0x0d -#define QSFP_LP_MODE_1 0x0c -#define QSFP_RESET_1 0x0e - -#define DEFAULT_DISABLE 0x00 -#define QSFP_DEFAULT_DISABLE 0x01 -#define QSFP_SEL_I2C_MUX 0x11 -#define SFP_SEL_I2C_MUX 0x19 - - -/* Check cpld read results */ -#define VALIDATED_READ(_buf, _rv, _read, _invert) \ - do { \ - _rv = _read; \ - if (_rv < 0) { \ - return sprintf(_buf, "READ ERROR\n"); \ - } \ - if (_invert) { \ - _rv = ~_rv; \ - } \ - _rv &= 0xFF; \ - } while(0) \ - - -long sfp_port_data = 0; - -static const u8 cpld_to_port_table[] = { - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x04, 0x03, 0x02, 0x00}; - -/* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; - -/* Each client has this additional data */ -struct ak7448_sfp_data -{ - struct device *hwmon_dev; - struct mutex update_lock; - char valid; - unsigned long last_updated; - int port; - char eeprom[256]; -}; - -static ssize_t for_eeprom(struct device *dev, struct device_attribute *dev_attr,char *buf); -static int ak7448_sfp_read_block(struct i2c_client *client, u8 command,u8 *data, int data_len); -static struct ak7448_sfp_data *ak7448_sfp_update_device(struct device *dev); -static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf); -static ssize_t set_w_port_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); -static ssize_t for_r_port_data(struct device *dev, struct device_attribute *dev_attr, char *buf); -static ssize_t set_w_lp_mode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); -static ssize_t set_w_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); - -extern int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg); -extern int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value); - -enum ak7448_sfp_sysfs_attributes -{ - SFP_EEPROM, - SFP_SELECT_PORT, - SFP_IS_PRESENT, - SFP_IS_PRESENT_ALL, - SFP_LP_MODE, - SFP_RESET -}; - -static ssize_t set_w_port_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) -{ - long data; - int error; - long port_t = 0; - u8 reg_t = 0x00; - - error = kstrtol(buf, 10, &data); - if(error) - return error; - - port_t = data; - - if(port_t > 0 && port_t < 9) - { /* SFP Port 1-8 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 8 && port_t < 17) - { /* SFP Port 9-16 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 16 && port_t < 25) - { /* SFP Port 17-24 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 24 && port_t < 33) - { /* SFP Port 25-32 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 32 && port_t < 37) - { /* SFP Port 33-36 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 36 && port_t < 45) - { /* SFP Port 37-44 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 44 && port_t < 49) - { /* SFP Port 45-48 */ - reg_t = SFP_SEL_I2C_MUX; - } - else if (port_t > 48 && port_t < 53) - { /* QSFP Port 49-52 */ - reg_t = QSFP_SEL_I2C_MUX; - } - else - { - /* Disable SFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, SFP_SEL_I2C_MUX, - DEFAULT_DISABLE) < 0) { - return -EIO; - } - - /* Disable QSFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_SEL_I2C_MUX, - QSFP_DEFAULT_DISABLE) < 0) { - return -EIO; - } - - goto exit; - - } - - /* Disable SFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, SFP_SEL_I2C_MUX, - DEFAULT_DISABLE) < 0) { - return -EIO; - } - - /* Disable QSFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_SEL_I2C_MUX, - QSFP_DEFAULT_DISABLE) < 0) { - return -EIO; - } - - /* Select SFP or QSFP port channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, reg_t, - cpld_to_port_table[port_t]) < 0) { - return -EIO; - } - -exit: - sfp_port_data = data; - return count; -} - -static ssize_t for_r_port_data(struct device *dev, struct device_attribute *dev_attr, char *buf) -{ - if (sfp_port_data == DEFAULT_DISABLE) - { - /* Disable SFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, - SFP_SEL_I2C_MUX, DEFAULT_DISABLE) < 0) { - return -EIO; - } - - /* Disable QSFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, - QSFP_SEL_I2C_MUX, QSFP_DEFAULT_DISABLE) < 0) { - return -EIO; - } - } - - return sprintf(buf, "%d\n", sfp_port_data); - -} - -static ssize_t set_w_lp_mode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) -{ - long data; - int error; - long port_t = 0; - int bit_t = 0x00; - int values = 0x00; - - error = kstrtol(buf, 10, &data); - if (error) - return error; - - port_t = sfp_port_data; - - if (port_t > 48 && port_t < 53) - { /* QSFP Port 48-53 */ - values = i2c_cpld_read(I2C_BUS_5, SWPLD_B, QSFP_LP_MODE_1); - if (values < 0) - return -EIO; - - /* Indicate the module is in LP mode or not - * 0 = Disable - * 1 = Enable - */ - if (data == 0) - { - bit_t = ~(1 << ((port_t - 1) % 8)); - values = values & bit_t; - } - else if (data == 1) - { - bit_t = 1 << ((port_t - 1) % 8); - values = values | bit_t; - } - else - { - return -EINVAL; - } - - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_LP_MODE_1, - values) < 0) - { - return -EIO; - } - } - - return count; -} - -static ssize_t set_w_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) -{ - long data; - int error; - long port_t = 0; - int bit_t = 0x00; - int values = 0x00; - - error = kstrtol(buf, 10, &data); - if (error) - return error; - - port_t = sfp_port_data; - - if (port_t > 48 && port_t < 53) - { /* QSFP Port 48-53 */ - values = i2c_cpld_read(I2C_BUS_5, SWPLD_B, QSFP_RESET_1); - if (values < 0) - return -EIO; - - /* Indicate the module Reset or not - * 0 = Reset - * 1 = Normal - */ - if (data == 0) - { - bit_t = ~(1 << ((port_t - 1) % 8)); - values = values & bit_t; - } - else if (data == 1) - { - bit_t = 1 << ((port_t - 1) % 8); - values = values | bit_t; - } - else - { - return -EINVAL; - } - - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_RESET_1, - values) < 0) - { - return -EIO; - } - } - - return count; -} - -static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - long port_t = 0; - u8 reg_t = 0x00; - u8 cpld_addr_t = 0x00; - int values[7] = {'\0'}; - int bit_t = 0x00; - - switch (attr->index) - { - case SFP_IS_PRESENT: - port_t = sfp_port_data; - - if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_1; - } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_2; - } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_3; - } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_4; - } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_5; - } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ - cpld_addr_t = SWPLD_A; - reg_t = SFP_PRESENCE_6; - } else if (port_t > 48 && port_t < 53) { /* QSFP Port 49-54 */ - cpld_addr_t = SWPLD_B; - reg_t = QSFP_PRESENCE_1; - } else { - values[0] = 1; /* return 1, module NOT present */ - return sprintf(buf, "%d\n", values[0]); - } - - VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, - cpld_addr_t, reg_t), 0); - - - /* SWPLD QSFP module respond */ - bit_t = 1 << ((port_t - 1) % 8); - values[0] = values[0] & bit_t; - values[0] = values[0] / bit_t; - - /* sfp_is_present value - * return 0 is module present - * return 1 is module NOT present*/ - return sprintf(buf, "%d\n", values[0]); - - case SFP_IS_PRESENT_ALL: - /* - * Report the SFP ALL PRESENCE status - * This data information form CPLD. - */ - - /* SFP_PRESENT Ports 1-8 */ - VALIDATED_READ(buf, values[0], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_1), 0); - /* SFP_PRESENT Ports 9-16 */ - VALIDATED_READ(buf, values[1], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_2), 0); - /* SFP_PRESENT Ports 17-24 */ - VALIDATED_READ(buf, values[2], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_3), 0); - /* SFP_PRESENT Ports 25-32 */ - VALIDATED_READ(buf, values[3], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_4), 0); - /* SFP_PRESENT Ports 33-40 */ - VALIDATED_READ(buf, values[4], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_5), 0); - /* SFP_PRESENT Ports 41-48 */ - VALIDATED_READ(buf, values[5], - i2c_cpld_read(I2C_BUS_5, SWPLD_A, SFP_PRESENCE_6), 0); - /* QSFP_PRESENT Ports 49-52 */ - VALIDATED_READ(buf, values[6], - i2c_cpld_read(I2C_BUS_5, SWPLD_B, QSFP_PRESENCE_1), 0); - - - /* sfp_is_present_all value - * return 0 is module present - * return 1 is module NOT present - */ - return sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X \n",values[0], values[1], values[2],values[3], values[4], values[5],values[6]); - - case SFP_LP_MODE: - - port_t = sfp_port_data; - if (port_t > 48 && port_t < 53) { - /* QSFP Port 49-52 */ - VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, - SWPLD_B, QSFP_LP_MODE_1), 0); - } else { - /* In AK7448 only QSFP support control LP MODE */ - values[0] = 0; - return sprintf(buf, "%d\n", values[0]); - } - - bit_t = 1 << ((port_t - 1) % 8); - values[0] = values[0] & bit_t; - values[0] = values[0] / bit_t; - - /* sfp_lp_mode value - * return 0 is module NOT in LP mode - * return 1 is module in LP mode - */ - - return sprintf(buf, "%d\n", values[0]); - - case SFP_RESET: - port_t = sfp_port_data; - if (port_t > 48 && port_t < 53) { - /* QSFP Port 49-54 */ - VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, - SWPLD_B, QSFP_RESET_1), 0); - } else { - /* In AK7448 only QSFP support control RESET MODE */ - values[0] = 1; - return sprintf(buf, "%d\n", values[0]); - } - - /* SWPLD QSFP module respond */ - bit_t = 1 << ((port_t - 1) % 8); - values[0] = values[0] & bit_t; - values[0] = values[0] / bit_t; - - /* sfp_reset value - * return 0 is module Reset - * return 1 is module Normal*/ - return sprintf(buf, "%d\n", values[0]); - - default: - return (attr->index); - } -} - -static ssize_t for_eeprom(struct device *dev, struct device_attribute *dev_attr,char *buf) -{ - struct ak7448_sfp_data *data = ak7448_sfp_update_device(dev); - if (!data->valid) - { - return 0; - } - memcpy(buf, data->eeprom, sizeof(data->eeprom)); - return sizeof(data->eeprom); -} - -static int ak7448_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 ak7448_sfp_data *ak7448_sfp_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ak7448_sfp_data *data = i2c_get_clientdata(client); - long port_t = 0; - u8 reg_t = 0x00; - - port_t = sfp_port_data; - - - if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ - reg_t = SFP_SEL_I2C_MUX; - } else if (port_t > 48 && port_t < 53) { /* QSFP Port 49-52 */ - reg_t = QSFP_SEL_I2C_MUX; - } else { - memset(data->eeprom, 0, sizeof(data->eeprom)); - - /* Disable SFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, SFP_SEL_I2C_MUX, - DEFAULT_DISABLE) < 0) { - goto exit; - } - - /* Disable QSFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_SEL_I2C_MUX, - QSFP_DEFAULT_DISABLE) < 0) { - goto exit; - } - - goto exit; - } - - /* Disable SFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, SFP_SEL_I2C_MUX, - DEFAULT_DISABLE) < 0) { - memset(data->eeprom, 0, sizeof(data->eeprom)); - goto exit; - } - - /* Disable QSFP channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, QSFP_SEL_I2C_MUX, - QSFP_DEFAULT_DISABLE) < 0) { - memset(data->eeprom, 0, sizeof(data->eeprom)); - goto exit; - } - - /* Select SFP or QSFP port channel */ - if (i2c_cpld_write(I2C_BUS_5, SWPLD_B, reg_t, - cpld_to_port_table[port_t]) < 0) { - memset(data->eeprom, 0, sizeof(data->eeprom)); - goto exit; - } - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated) || !data->valid) - { - int status = -1; - int i = 0; - data->valid = 0; - memset(data->eeprom, 0, sizeof(data->eeprom)); - - for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) - { - status = ak7448_sfp_read_block(client,i * I2C_SMBUS_BLOCK_MAX,data->eeprom + (i * I2C_SMBUS_BLOCK_MAX),I2C_SMBUS_BLOCK_MAX); - if (status < 0) - { - printk(KERN_INFO "status = %d\n", status); - 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; -} - -/* sysfs attributes for hwmon */ -static SENSOR_DEVICE_ATTR(sfp_eeprom,S_IRUGO, for_eeprom, NULL,SFP_EEPROM); -static SENSOR_DEVICE_ATTR(sfp_select_port, S_IWUSR | S_IRUGO, for_r_port_data, set_w_port_data, SFP_SELECT_PORT); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, for_status, NULL, SFP_IS_PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_lp_mode,S_IWUSR | S_IRUGO, for_status, set_w_lp_mode_data, SFP_LP_MODE); -static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, for_status, set_w_reset_data, SFP_RESET); - -static struct attribute *ak7448_sfp_attributes[] = { - &sensor_dev_attr_sfp_eeprom.dev_attr.attr, - &sensor_dev_attr_sfp_select_port.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_lp_mode.dev_attr.attr, - &sensor_dev_attr_sfp_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group ak7448_sfp_group = { - .attrs = ak7448_sfp_attributes, -}; - -static int ak7448_sfp_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct ak7448_sfp_data *data; - int status; - - if (!i2c_check_functionality(client->adapter,I2C_FUNC_SMBUS_I2C_BLOCK)) - { - status = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct ak7448_sfp_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; - goto exit; - } - - mutex_init(&data->update_lock); - data->port = id->driver_data; - i2c_set_clientdata(client, data); - - dev_info(&client->dev, "chip found\n"); - - status = sysfs_create_group(&client->dev.kobj, &ak7448_sfp_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; - } - - dev_info(&client->dev, "%s: sfp '%s'\n", dev_name(data->hwmon_dev),client->name); - - return 0; - -exit_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, &ak7448_sfp_group); -exit_sysfs_create_group: - kfree(data); -exit: - return status; -} - -static int ak7448_sfp_remove(struct i2c_client *client) -{ - struct ak7448_sfp_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ak7448_sfp_group); - kfree(data); - return 0; -} - -enum id_name -{ - dni_ak7448_sfp -}; - -static const struct i2c_device_id ak7448_sfp_id[] = { - { "dni_ak7448_sfp", dni_ak7448_sfp }, - {} -}; -MODULE_DEVICE_TABLE(i2c, ak7448_sfp_id); - - -static struct i2c_driver ak7448_sfp_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "dni_ak7448_sfp", - }, - .probe = ak7448_sfp_probe, - .remove = ak7448_sfp_remove, - .id_table = ak7448_sfp_id, - .address_list = normal_i2c, -}; - -static int __init ak7448_sfp_init(void) -{ - return i2c_add_driver(&ak7448_sfp_driver); -} - -static void __exit ak7448_sfp_exit(void) -{ - i2c_del_driver(&ak7448_sfp_driver); -} - -MODULE_AUTHOR("Aries Lin "); -MODULE_DESCRIPTION("ak7448 SFP Driver"); -MODULE_LICENSE("GPL"); - -module_init(ak7448_sfp_init); -module_exit(ak7448_sfp_exit); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/fani.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/fani.c index dd670ef2..f484ce78 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/fani.c @@ -96,16 +96,13 @@ dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info) mux_info_t mux_info; dev_info_t dev_info; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = FAN_I2C_MUX_SEL_REG; mux_info.channel = FAN_I2C_SEL_FAN_CTRL; - mux_info.flags = DEFAULT_FLAG; dev_info.bus = I2C_BUS_7; dev_info.addr = FAN_IO_CTL; dev_info.offset = 0x00; - dev_info.flags = DEFAULT_FLAG; + dev_info.flags = ONLP_I2C_F_FORCE; sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); rpm = dni_i2c_lock_read_attribute(&mux_info, fullpath); @@ -160,11 +157,8 @@ dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) dev_info_t dev_info; mux_info_t mux_info; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = PSU_I2C_MUX_SEL_REG; mux_info.channel = PSU_I2C_SEL_PSU_EEPROM; - mux_info.flags = DEFAULT_FLAG; dev_info.bus = I2C_BUS_4; dev_info.addr = PSU_EEPROM; @@ -291,11 +285,8 @@ onlp_fani_rpm_set(onlp_oid_t id, int rpm) } sprintf(data, "%d", rpm); - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = FAN_I2C_MUX_SEL_REG; mux_info.channel = FAN_I2C_SEL_FAN_CTRL; - mux_info.flags = DEFAULT_FLAG; ret = dni_i2c_lock_write_attribute(&mux_info, data, fullpath); if(ret == -1){ @@ -321,10 +312,6 @@ onlp_fani_percentage_set(onlp_oid_t id, int percentage) char fullpath[70] = {0}; mux_info_t mux_info; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; - mux_info.flags = DEFAULT_FLAG; - VALIDATE(id); local_id = ONLP_OID_ID_GET(id); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/ledi.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/ledi.c index 8a5fbf7d..98d0c2cb 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/ledi.c @@ -101,13 +101,10 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) dev_info.offset = 0x00; dev_info.flags = DEFAULT_FLAG; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = FAN_I2C_MUX_SEL_REG; - mux_info.flags = DEFAULT_FLAG; /* Set front panel's mode of leds */ - r_data = dni_lock_cpld_read_attribute(CPLD_B_PATH,LED_REG); + r_data = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,LED_REG); if(r_data == -1){ AIM_LOG_ERROR("Unable to read front panel led status from reg\r\n"); return ONLP_STATUS_E_INTERNAL; @@ -149,7 +146,7 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) case LED_REAR_FAN_TRAY_1: dev_info.addr = FAN_TRAY; mux_info.channel = 0x02; - r_data = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + r_data = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(r_data == -1){ AIM_LOG_ERROR("Unable to read fan tray 1 led status from reg\r\n"); return ONLP_STATUS_E_INTERNAL; @@ -171,7 +168,7 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) case LED_REAR_FAN_TRAY_2: dev_info.addr = FAN_TRAY; mux_info.channel = 0x01; - r_data = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + r_data = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(r_data == -1){ AIM_LOG_ERROR("Unable to read fan tray 2 led status from reg\r\n"); return ONLP_STATUS_E_INTERNAL; @@ -194,7 +191,7 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) case LED_REAR_FAN_TRAY_3: dev_info.addr = FAN_TRAY; mux_info.channel = 0x00; - r_data = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + r_data = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(r_data == -1){ AIM_LOG_ERROR("Unable to read fan tray 3 led status from reg\r\n"); return ONLP_STATUS_E_INTERNAL; @@ -261,7 +258,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) switch(local_id) { case LED_FRONT_FAN: - front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,LED_REG); + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,LED_REG); if(front_panel_led_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -278,7 +275,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) front_panel_led_value = front_panel_led_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,LED_REG,front_panel_led_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,LED_REG,front_panel_led_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } @@ -286,7 +283,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) break; case LED_FRONT_SYS: - front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,LED_REG); + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,LED_REG); if(front_panel_led_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -306,7 +303,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) front_panel_led_value = front_panel_led_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,LED_REG,front_panel_led_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,LED_REG,front_panel_led_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } @@ -314,7 +311,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) break; case LED_FRONT_PWR: - front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,LED_REG); + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,LED_REG); if(front_panel_led_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -334,7 +331,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) front_panel_led_value = front_panel_led_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,LED_REG,front_panel_led_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,LED_REG,front_panel_led_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } @@ -342,7 +339,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) break; case LED_REAR_FAN_TRAY_1: - fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(fan_tray_led_reg_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -359,7 +356,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) fan_tray_led_reg_value = fan_tray_led_reg_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } @@ -367,7 +364,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) break; case LED_REAR_FAN_TRAY_2: - fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(fan_tray_led_reg_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -384,7 +381,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) fan_tray_led_reg_value = fan_tray_led_reg_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } @@ -392,7 +389,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) break; case LED_REAR_FAN_TRAY_3: - fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG); + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG); if(fan_tray_led_reg_value == -1 ){ AIM_LOG_ERROR("Unable to read led(%d) status from reg\r\n",local_id); return ONLP_STATUS_E_INTERNAL; @@ -409,7 +406,7 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) fan_tray_led_reg_value = fan_tray_led_reg_value; } - if(dni_lock_cpld_write_attribute(CPLD_B_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ + if(dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH,FAN_TRAY_LED_REG,fan_tray_led_reg_value) != 0){ AIM_LOG_ERROR("Unable to set led(%d) status\r\n",local_id); return ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.c index f2d663db..ac8e1bf0 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.c @@ -41,29 +41,24 @@ int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, in int fd; int len; - if ((buffer == NULL) || (buf_size < 0)) - { + if ((buffer == NULL) || (buf_size < 0)) { return -1; } - if ((fd = open(filename, O_RDONLY)) == -1) - { + if ((fd = open(filename, O_RDONLY)) == -1) { return -1; } - if ((len = read(fd, buffer, buf_size)) < 0) - { + if ((len = read(fd, buffer, buf_size)) < 0) { close(fd); return -1; } - if ((close(fd) == -1)) - { + if ((close(fd) == -1)) { return -1; } - if ((len > buf_size) || (data_len != 0 && len != data_len)) - { + if ((len > buf_size) || (data_len != 0 && len != data_len)) { return -1; } @@ -93,10 +88,9 @@ int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info) int r_data=0; pthread_mutex_lock(&mutex); - if(mux_info != NULL) - { + if(mux_info != NULL){ char cpld_path[100] = {0}; - sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + sprintf(cpld_path, "%s", CPLD_B_PLATFORM_PATH); dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); } if(dev_info->size == 1) @@ -111,19 +105,23 @@ int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info) int dni_i2c_lock_write( mux_info_t * mux_info, dev_info_t * dev_info) { pthread_mutex_lock(&mutex); - if(mux_info != NULL) - { + int ret; + if(mux_info != NULL){ char cpld_path[100] = {0}; - sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + sprintf(cpld_path, "%s", CPLD_B_PLATFORM_PATH); dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); } /* Write size */ if(dev_info->size == 1) - onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); + ret = onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); else - onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); + ret = onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); pthread_mutex_unlock(&mutex); + if (ret != 0) + { + return -1; + } return 0; } @@ -133,18 +131,15 @@ int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) char r_data[10] = {0}; pthread_mutex_lock(&mutex); - if(mux_info != NULL) - { + if(mux_info != NULL){ char cpld_path[100] = {0}; - sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + sprintf(cpld_path, "%s", CPLD_B_PLATFORM_PATH); dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); } - if ((fd = open(fullpath, O_RDONLY)) == -1) - { + if ((fd = open(fullpath, O_RDONLY)) == -1){ goto ERROR; } - if ((len = read(fd, r_data, nbytes)) <= 0) - { + if ((len = read(fd, r_data, nbytes)) <= 0){ goto ERROR; } close(fd); @@ -160,21 +155,18 @@ int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullp { int fd, len, nbytes = 10; pthread_mutex_lock(&mutex); - if(mux_info!=NULL) - { + if(mux_info!=NULL){ char cpld_path[100] = {0}; - sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + sprintf(cpld_path, "%s", CPLD_B_PLATFORM_PATH); dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); } /* Create output file descriptor */ fd = open(fullpath, O_WRONLY, 0644); - if (fd == -1) - { + if (fd == -1){ goto ERROR; } len = write (fd, data, (ssize_t) nbytes); - if (len != nbytes) - { + if (len != nbytes){ goto ERROR; } close(fd); @@ -201,26 +193,22 @@ int dni_lock_cpld_read_attribute(char *cpld_path, int addr) pthread_mutex_lock(&mutex1); /* Create output file descriptor */ - fd = open(cpld_addr_path, O_WRONLY, 0644); - if (fd == -1) - { + fd = open(cpld_addr_path, O_WRONLY, 0644); + if (fd == -1){ goto ERR_HANDLE; } len = write (fd, address, 2); - if (len <= 0) - { + if (len <= 0){ goto ERR_HANDLE; } close(fd); - if ((fd = open(cpld_data_path, O_RDONLY)) == -1) - { + if ((fd = open(cpld_data_path, O_RDONLY, 0644)) == -1){ goto ERR_HANDLE; } - if ((len = read(fd, r_data, nbytes)) <= 0) - { + if ((len = read(fd, r_data, nbytes)) <= 0){ goto ERR_HANDLE; } close(fd); @@ -229,7 +217,7 @@ int dni_lock_cpld_read_attribute(char *cpld_path, int addr) sscanf(r_data, "%x", &data); return data; - ERR_HANDLE: +ERR_HANDLE: close(fd); pthread_mutex_unlock(&mutex1); return -1; @@ -250,26 +238,22 @@ int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data) pthread_mutex_lock(&mutex1); /* Create output file descriptor */ fd = open(cpld_addr_path, O_WRONLY, 0644); - if (fd == -1) - { + if (fd == -1){ goto ERR_HANDLE; } len = write(fd, address, 2); - if(len <= 0) - { + if(len <= 0){ goto ERR_HANDLE; } close(fd); fd = open(cpld_data_path, O_WRONLY, 0644); - if (fd == -1) - { + if (fd == -1){ goto ERR_HANDLE; } sprintf(address, "%02x", data); len = write (fd, address, 2); - if(len <= 0) - { + if(len <= 0){ goto ERR_HANDLE; } close(fd); @@ -277,7 +261,7 @@ int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data) return 0; - ERR_HANDLE: +ERR_HANDLE: close(fd); pthread_mutex_unlock(&mutex1); return -1; @@ -288,11 +272,9 @@ int dni_fan_speed_good() { int rpm = 0, rpm1 = 0, speed_good = 0; mux_info_t mux_info; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; + mux_info.offset = FAN_I2C_MUX_SEL_REG; mux_info.channel = FAN_I2C_SEL_FAN_CTRL; - mux_info.flags = DEFAULT_FLAG; rpm = dni_i2c_lock_read_attribute(&mux_info, FAN1_FRONT); rpm1 = dni_i2c_lock_read_attribute(&mux_info, FAN1_REAR); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.h index cf0ef7a8..ddc08b92 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.h @@ -45,9 +45,6 @@ #define NUM_OF_PORT NUM_OF_SFP + NUM_OF_QSFP #define PREFIX_PATH "/sys/bus/i2c/devices" -#define SYS_CPLD_PATH PREFIX_PATH "/2-0031" -#define CPLD_A_PATH PREFIX_PATH "/5-0033" -#define CPLD_B_PATH PREFIX_PATH "/5-0032" #define PSU_AC_PMBUS_PREFIX PREFIX_PATH "/4-0058/" #define PSU_AC_PMBUS_NODE(node) PSU_AC_PMBUS_PREFIX#node @@ -60,16 +57,14 @@ #define FAN3_REAR PREFIX_PATH "/7-002d/fan1_input" #define IDPROM_PATH "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" -#define SFP_SELECT_PORT_PATH PREFIX_PATH "/8-0050/sfp_select_port" -#define SFP_IS_PRESENT_PATH PREFIX_PATH "/8-0050/sfp_is_present" -#define SFP_IS_PRESENT_ALL_PATH PREFIX_PATH "/8-0050/sfp_is_present_all" -#define SFP_EEPROM_PATH PREFIX_PATH "/8-0050/sfp_eeprom" +#define CPLD_B_PLATFORM_PATH "/sys/devices/platform/delta-ak7448-cpld.0" +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define SFP_SELECT_PORT_PATH "/sys/devices/platform/delta-ak7448-cpld.0/sfp_select_port" +#define SFP_IS_PRESENT_PATH "/sys/devices/platform/delta-ak7448-cpld.0/sfp_is_present" +#define SFP_IS_PRESENT_ALL_PATH "/sys/devices/platform/delta-ak7448-cpld.0/sfp_is_present_all" -#define QSFP_SELECT_PORT_PATH PREFIX_PATH "/3-0050/sfp_select_port" -#define QSFP_IS_PRESENT_PATH PREFIX_PATH "/3-0050/sfp_is_present" -#define QSFP_EEPROM_PATH PREFIX_PATH "/3-0050/sfp_eeprom" -#define QSFP_RESET_PATH PREFIX_PATH "/3-0050/sfp_reset" -#define QSFP_LP_MODE_PATH PREFIX_PATH "/3-0050/sfp_lp_mode" +#define QSFP_RESET_PATH "/sys/devices/platform/delta-ak7448-cpld.0/sfp_reset" +#define QSFP_LP_MODE_PATH "/sys/devices/platform/delta-ak7448-cpld.0/sfp_lp_mode" /* BUS define */ #define I2C_BUS_0 (0) @@ -96,7 +91,6 @@ #define QSFP_RESPOND_REG (0x0b) #define SYS_CPLD (0x31) #define CPLD_A (0x33) -#define CPLD_B (0x32) #define SYS_VERSION_REG (0x01) #define CPLD_A_VERSION_REG (0x00) #define CPLD_B_VERSION_REG (0x01) diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/psui.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/psui.c index ecae9b60..e894fafe 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/psui.c @@ -151,11 +151,8 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) memset(info, 0, sizeof(onlp_psu_info_t)); *info = pinfo[index]; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = PSU_I2C_MUX_SEL_REG; mux_info.channel = PSU_I2C_SEL_PSU_EEPROM; - mux_info.flags = DEFAULT_FLAG; dev_info.bus = I2C_BUS_4; dev_info.offset = 0x00; /* In EEPROM address 0x00 */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sfpi.c index 4c0a8dc1..cda73127 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sfpi.c @@ -30,10 +30,18 @@ #include #include #include +#include #include #include "platform_lib.h" /******************* Utility Function *****************************************/ +int sfp_map_bus[] ={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, 72, 73, 74, 75, 76, 77, 20, 21, + 22, 23}; + int ak7448_get_respond_val(int port){ int respond_default = 0xff; @@ -65,6 +73,14 @@ onlp_sfpi_init(void){ return ONLP_STATUS_OK; } +int +onlp_sfpi_map_bus_index(int port) +{ + if(port < 0 || port > 52) + return ONLP_STATUS_E_INTERNAL; + return sfp_map_bus[port-1]; +} + int onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap){ /*Ports {1, 52}*/ @@ -82,35 +98,20 @@ onlp_sfpi_is_present(int port){ char port_data[2]; int present, present_bit; - if(port > 0 && port < 49) - { - /* Select QSFP port */ + if(port > 0 && port < 53) + { + /* Select QSFP/SFP port */ sprintf(port_data, "%d", port ); if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ AIM_LOG_ERROR("Unable to select port(%d)\r\n", port); } - /* Read SFP MODULE is present or not */ + /* Read QSFP/SFP MODULE is present or not */ present_bit = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH); if(present_bit < 0){ AIM_LOG_ERROR("Unable to read present or not from port(%d)\r\n", port); } } - else if(port > 48 && port < 53) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_ERROR("Unable to select port(%d)\r\n", port); - } - - /* Read SFP MODULE is present or not */ - present_bit = dni_i2c_lock_read_attribute(NULL, QSFP_IS_PRESENT_PATH); - if(present_bit < 0){ - AIM_LOG_ERROR("Unable to read present or not from port(%d)\r\n", port); - } - - } /* From sfp_is_present value, * return 0 = The module is preset @@ -180,9 +181,9 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char port_data[2]; int sfp_respond_reg; int sfp_respond_val; + int size = 0; /* Get respond register if port have it */ @@ -190,49 +191,22 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) /* Set respond val */ sfp_respond_val = ak7448_get_respond_val(port); - dni_lock_cpld_write_attribute(CPLD_B_PATH, sfp_respond_reg, sfp_respond_val); + dni_lock_cpld_write_attribute(CPLD_B_PLATFORM_PATH, sfp_respond_reg, sfp_respond_val); - if(port > 0 && port < 49) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } + memset(data, 0, 256); + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; } - else if(port > 48 && port < 53) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0 ){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } - - memset(data, 0 ,256); - /* Read eeprom information into data[] */ - if(port > 0 && port < 49) - { - if(dni_i2c_read_attribute_binary(SFP_EEPROM_PATH, (char *)data, 256, 256) != 0) - { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } - else if(port > 48 && port < 53) - { - if(dni_i2c_read_attribute_binary(QSFP_EEPROM_PATH, (char *)data, 256, 256) != 0) - { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; } return ONLP_STATUS_OK; + } int onlp_sfpi_port_map(int port, int* rport) @@ -248,7 +222,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) int value_t; char port_data[2]; - if(port > 0 && port < 49) + if(port > 0 && port < 53) { /* Select QSFP port */ sprintf(port_data, "%d", port ); @@ -256,17 +230,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) AIM_LOG_INFO("Unable to select port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - - } - else if(port > 48 && port < 53) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } switch (control) { @@ -315,7 +278,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int value_t; char port_data[2]; - if(port > 0 && port < 49) + if(port > 0 && port < 53) { /* Select QSFP port */ sprintf(port_data, "%d", port ); @@ -323,19 +286,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_INFO("Unable to select port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - } - else if(port > 48 && port < 53) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - - } - switch (control) { case ONLP_SFP_CONTROL_RESET_STATE: @@ -370,186 +321,51 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) { - char port_data[2]; - int sfp_respond_reg, sfp_respond_val; - dev_info_t dev_info; - - /* Get respond register if port have it */ - sfp_respond_reg = ak7448_get_respond_reg(port); - - /* Set respond val */ - sfp_respond_val = ak7448_get_respond_val(port); - dni_lock_cpld_write_attribute(CPLD_B_PATH, sfp_respond_reg, sfp_respond_val); - - if(port > 0 && port < 49) - { - dev_info.bus = I2C_BUS_8; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - + int bus; + + bus = onlp_sfpi_map_bus_index(port); + if(devaddr == 0x51){ + addr += 256; } - else if(port > 48 && port < 53) - { - dev_info.bus = I2C_BUS_3; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - - } - - dev_info.addr = PORT_ADDR; - dev_info.offset = addr; - dev_info.flags = ONLP_I2C_F_FORCE; - dev_info.size = 1; /* Read 1 byte */ - - return dni_i2c_lock_read(NULL, &dev_info); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); } int onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) { - char port_data[2]; - int sfp_respond_reg, sfp_respond_val; - dev_info_t dev_info; + int bus; - /* Get respond register if port have it */ - sfp_respond_reg = ak7448_get_respond_reg(port); - - /* Set respond val */ - sfp_respond_val = ak7448_get_respond_val(port); - dni_lock_cpld_write_attribute(CPLD_B_PATH, sfp_respond_reg, sfp_respond_val); - - if(port > 0 && port < 49) - { - dev_info.bus = I2C_BUS_8; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } + bus = onlp_sfpi_map_bus_index(port); + if(devaddr == 0x51){ + addr += 256; } - else if(port > 48 && port < 53) - { - dev_info.bus = I2C_BUS_3; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } - - dev_info.addr = PORT_ADDR; - dev_info.offset = addr; - dev_info.flags = ONLP_I2C_F_FORCE; - dev_info.size = 1; /* Write 1 byte */ - dev_info.data_8 = value; - - return dni_i2c_lock_write(NULL, &dev_info); + + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); + } int onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) { - char port_data[2]; - int sfp_respond_reg, sfp_respond_val; - dev_info_t dev_info; - - /* Get respond register if port have it */ - sfp_respond_reg = ak7448_get_respond_reg(port); - - /* Set respond val */ - sfp_respond_val = ak7448_get_respond_val(port); - dni_lock_cpld_write_attribute(CPLD_B_PATH, sfp_respond_reg, sfp_respond_val); - - if(port > 0 && port < 49) - { - dev_info.bus = I2C_BUS_8; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } + int bus; + bus = onlp_sfpi_map_bus_index(port); + if(devaddr == 0x51){ + addr += 256; } - else if(port > 48 && port < 53) - { - dev_info.bus = I2C_BUS_3; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } - - dev_info.addr = PORT_ADDR; - dev_info.offset = addr; - dev_info.flags = ONLP_I2C_F_FORCE; - dev_info.size = 2; /* Read 1 byte */ - - return dni_i2c_lock_read(NULL, &dev_info); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); } int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) { - char port_data[2]; - int sfp_respond_reg, sfp_respond_val; - dev_info_t dev_info; - - /* Get respond register if port have it */ - sfp_respond_reg = ak7448_get_respond_reg(port); - - /* Set respond val */ - sfp_respond_val = ak7448_get_respond_val(port); - dni_lock_cpld_write_attribute(CPLD_B_PATH, sfp_respond_reg, sfp_respond_val); - - if(port > 0 && port < 49) - { - dev_info.bus = I2C_BUS_8; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } + int bus; + + bus = onlp_sfpi_map_bus_index(port); + if(devaddr == 0x51){ + addr += 256; } - else if(port > 48 && port < 53) - { - dev_info.bus = I2C_BUS_3; - - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } - - dev_info.addr = PORT_ADDR; - dev_info.offset = addr; - dev_info.flags = ONLP_I2C_F_FORCE; - dev_info.size = 2; /* Write 2 byte */ - dev_info.data_16 = value; - - return dni_i2c_lock_write(NULL, &dev_info); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); } int @@ -557,7 +373,7 @@ onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) { char port_data[2] ; - if(port > 0 && port < 49) + if(port > 0 && port < 53) { /* Select QSFP port */ sprintf(port_data, "%d", port ); @@ -566,15 +382,6 @@ onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) return ONLP_STATUS_E_INTERNAL; } } - else if(port > 48 && port < 53) - { - /* Select QSFP port */ - sprintf(port_data, "%d", port ); - if(dni_i2c_lock_write_attribute(NULL, port_data, QSFP_SELECT_PORT_PATH) < 0){ - AIM_LOG_INFO("Unable to select port(%d)\r\n", port); - return ONLP_STATUS_E_INTERNAL; - } - } switch (control) { case ONLP_SFP_CONTROL_RESET_STATE: @@ -605,8 +412,6 @@ onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) return ONLP_STATUS_OK; } - - int onlp_sfpi_denit(void) { @@ -622,7 +427,30 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - return ONLP_STATUS_E_UNSUPPORTED; + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sysi.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sysi.c index 22d687ba..a363554d 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sysi.c @@ -55,33 +55,27 @@ decide_percentage(int *percentage, int temper) { int level; - if(temper <= 50) - { + if(temper <= 50){ *percentage = 50; level = 1; } - else if(temper > 50 && temper <= 55) - { + else if(temper > 50 && temper <= 55){ *percentage = 58; level = 2; } - else if(temper > 55 && temper <= 60) - { + else if(temper > 55 && temper <= 60){ *percentage = 65; level = 3; } - else if(temper > 60 && temper <= 65) - { + else if(temper > 60 && temper <= 65){ *percentage = 80; level = 4; } - else if(temper > 65) - { + else if(temper > 65){ *percentage = 100; level = 5; } - else - { + else{ *percentage = 100; level = 6; } @@ -117,11 +111,24 @@ onlp_sysi_onie_data_free(uint8_t* data) int onlp_sysi_platform_info_get(onlp_platform_info_t* pi) { + dev_info_t dev_info; int sys_cpld_version = 0, cpld_a_version = 0, cpld_b_version = 0; - sys_cpld_version = dni_lock_cpld_read_attribute(SYS_CPLD_PATH,SYS_VERSION_REG); - cpld_a_version = dni_lock_cpld_read_attribute(CPLD_A_PATH,CPLD_A_VERSION_REG); - cpld_b_version = (dni_lock_cpld_read_attribute(CPLD_B_PATH,CPLD_B_VERSION_REG) & 0x7); + dev_info.bus = I2C_BUS_5; + dev_info.addr = CPLD_A; + dev_info.offset = CPLD_A_VERSION_REG; + dev_info.size = 1; + dev_info.flags = ONLP_I2C_F_FORCE; + cpld_a_version = dni_i2c_lock_read(NULL, &dev_info); + + dev_info.bus = I2C_BUS_2; + dev_info.addr = SYS_CPLD; + dev_info.offset = SYS_VERSION_REG; + dev_info.size = 1; + dev_info.flags = DEFAULT_FLAG; + sys_cpld_version = dni_i2c_lock_read(NULL, &dev_info); + + cpld_b_version = (dni_lock_cpld_read_attribute(CPLD_B_PLATFORM_PATH,CPLD_B_VERSION_REG) & 0x7); pi->cpld_versions = aim_fstrdup("SYSTEM-CPLD = %d, CPLD-A = %d, CPLD-B = %d", sys_cpld_version, cpld_a_version, cpld_b_version); @@ -245,10 +252,7 @@ onlp_sysi_platform_manage_leds(void) mux_info_t mux_info; dev_info_t dev_info; - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = FAN_I2C_MUX_SEL_REG; - mux_info.flags = DEFAULT_FLAG; dev_info.bus = I2C_BUS_7; dev_info.offset = 0x00; @@ -343,11 +347,8 @@ onlp_sysi_platform_manage_leds(void) } /* Set front light of PWR */ - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = PSU_I2C_MUX_SEL_REG; mux_info.channel = PSU_I2C_SEL_PSU_EEPROM; - mux_info.flags = DEFAULT_FLAG; dev_info.bus = I2C_BUS_4; dev_info.offset = 0x00; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/thermali.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/thermali.c index fdf24864..5e4494be 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/thermali.c @@ -154,11 +154,8 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) return ONLP_STATUS_E_INVALID; } - mux_info.bus = I2C_BUS_5; - mux_info.addr = CPLD_B; mux_info.offset = offset; mux_info.channel = channel; - mux_info.flags = DEFAULT_FLAG; sprintf(fullpath, "%s%s", PREFIX_PATH, last_path[local_id]); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/python/x86_64_delta_ak7448_r0/__init__.py b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/python/x86_64_delta_ak7448_r0/__init__.py index 82527b9d..ff2bdfb6 100755 --- a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/python/x86_64_delta_ak7448_r0/__init__.py +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/python/x86_64_delta_ak7448_r0/__init__.py @@ -11,25 +11,22 @@ class OnlPlatform_x86_64_delta_ak7448_r0(OnlPlatformDelta, #PCA9548 modulize self.new_i2c_device('pca9547', 0x71, 1) - #Insert cpld module - self.insmod('i2c_cpld') - self.new_i2c_device('cpld', 0x31, 2) - self.new_i2c_device('cpld', 0x33, 5) - self.new_i2c_device('cpld', 0x32, 5) + self.insmod('optoe') + self.insmod('delta_ak7448_platform') #IDEEPROM modulize self.new_i2c_device('24c02', 0x53, 2) #Insert psu module self.insmod('dni_ak7448_psu') - os.system("echo 0x04 > /sys/bus/i2c/devices/5-0032/addr") - os.system("echo 0x02 > /sys/bus/i2c/devices/5-0032/data") + os.system("echo 0x04 > /sys/devices/platform/delta-ak7448-cpld.0/addr") + os.system("echo 0x02 > /sys/devices/platform/delta-ak7448-cpld.0/data") self.new_i2c_device('dni_ak7448_psu', 0x58, 4) #Insert fan module self.insmod('dni_emc2305') - os.system("echo 0x0a > /sys/bus/i2c/devices/5-0032/addr") - os.system("echo 0x05 > /sys/bus/i2c/devices/5-0032/data") + os.system("echo 0x0a > /sys/devices/platform/delta-ak7448-cpld.0/addr") + os.system("echo 0x05 > /sys/devices/platform/delta-ak7448-cpld.0/data") self.new_i2c_device('emc2305', 0x2c, 7) self.new_i2c_device('emc2305', 0x2d, 7) @@ -38,23 +35,27 @@ class OnlPlatform_x86_64_delta_ak7448_r0(OnlPlatformDelta, self.new_i2c_device('tmp75', 0x4c, 6) self.new_i2c_device('tmp75', 0x4d, 6) self.new_i2c_device('tmp75', 0x4e, 6) - os.system("echo 0x0a > /sys/bus/i2c/devices/5-0032/addr") - os.system("echo 0x06 > /sys/bus/i2c/devices/5-0032/data") + os.system("echo 0x0a > /sys/devices/platform/delta-ak7448-cpld.0/addr") + os.system("echo 0x06 > /sys/devices/platform/delta-ak7448-cpld.0/data") self.new_i2c_device('tmp75', 0x4f, 7) - #Insert sfp module - self.insmod('dni_ak7448_sfp') - self.new_i2c_device('dni_ak7448_sfp', 0x50, 3) - self.new_i2c_device('dni_ak7448_sfp', 0x50, 8) - #Set front panel sys light - os.system("echo 0x09 > /sys/bus/i2c/devices/5-0032/addr") - os.system("echo 0x03 > /sys/bus/i2c/devices/5-0032/data") + os.system("echo 0x09 > /sys/devices/platform/delta-ak7448-cpld.0/addr") + os.system("echo 0x03 > /sys/devices/platform/delta-ak7448-cpld.0/data") #Set thermal Thigh & Tlow os.system("echo 80000 > /sys/class/hwmon/hwmon6/temp1_max") os.system("echo 75000 > /sys/class/hwmon/hwmon6/temp1_max_hyst") + #Set SFP port name + for port in range(1, 49): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+29), shell=True) + + #Set QSFP port name + for port in range(49, 53): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-29), shell=True) + + return True diff --git a/packages/platforms/ingrasys/x86-64/modules/builds/eeprom_mb.c b/packages/platforms/ingrasys/x86-64/modules/builds/eeprom_mb.c index ec4fe3d6..528864d9 100755 --- a/packages/platforms/ingrasys/x86-64/modules/builds/eeprom_mb.c +++ b/packages/platforms/ingrasys/x86-64/modules/builds/eeprom_mb.c @@ -16,6 +16,9 @@ * GNU General Public License for more details. */ +/* enable dev_dbg print out */ +//#define DEBUG + #include #include #include @@ -25,12 +28,11 @@ #include /* Addresses to scan */ -static const unsigned short normal_i2c[] = { /* 0x50, 0x51, 0x52, 0x53, 0x54, - 0x55, 0x56, 0x57, */ I2C_CLIENT_END }; - +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 EEPROM_SIZE 512 #define SLICE_BITS (6) #define SLICE_SIZE (1 << SLICE_BITS) @@ -60,7 +62,7 @@ static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) addr = slice << SLICE_BITS; - ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + 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"); @@ -119,13 +121,66 @@ static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, 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, + .mode = S_IRUGO | S_IWUSR, }, .size = EEPROM_SIZE, .read = mb_eeprom_read, + .write = mb_eeprom_write, }; /* Return 0 if detection is successful, -ENODEV otherwise */ @@ -134,9 +189,9 @@ static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *in 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) { + 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; } @@ -208,5 +263,5 @@ static struct i2c_driver mb_eeprom_driver = { module_i2c_driver(mb_eeprom_driver); MODULE_AUTHOR("Wade "); -MODULE_DESCRIPTION("Ingrasys S9100 Mother Borad EEPROM driver"); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); MODULE_LICENSE("GPL"); diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/platform_lib.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/platform_lib.h index e7bde010..60fb6c5b 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/platform_lib.h +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/platform_lib.h @@ -44,6 +44,7 @@ #define SYS_QSFP_NEAR_TEMP_PREFIX "/sys/class/hwmon/hwmon6/" #define SYS_FAN_PREFIX "/sys/class/hwmon/hwmon1/device/" #define SYS_EEPROM_PATH "/sys/bus/i2c/devices/0-0055/eeprom" +#define SYS_EEPROM_SIZE 512 #define PSU1_EEPROM_PATH "/sys/bus/i2c/devices/58-0050/eeprom" #define PSU2_EEPROM_PATH "/sys/bus/i2c/devices/57-0050/eeprom" #define PSU_STATUS_PRESENT 1 diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/sysi.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/sysi.c index 08a81c60..2416a533 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/sysi.c +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/onlp/builds/src/x86_64_ingrasys_s9180_32x/module/src/sysi.c @@ -51,9 +51,9 @@ onlp_sysi_init(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { - uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, SYS_EEPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { + uint8_t* rdata = aim_zmalloc(SYS_EEPROM_SIZE); + if(onlp_file_read(rdata, SYS_EEPROM_SIZE, size, SYS_EEPROM_PATH) == ONLP_STATUS_OK) { + if(*size == SYS_EEPROM_SIZE) { *data = rdata; return ONLP_STATUS_OK; } diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/platform-config/r0/src/python/x86_64_ingrasys_s9180_32x_r0/__init__.py b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/platform-config/r0/src/python/x86_64_ingrasys_s9180_32x_r0/__init__.py index 002c1774..966baa04 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/platform-config/r0/src/python/x86_64_ingrasys_s9180_32x_r0/__init__.py +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9180-32x/platform-config/r0/src/python/x86_64_ingrasys_s9180_32x_r0/__init__.py @@ -1,6 +1,14 @@ from onl.platform.base import * from onl.platform.ingrasys import * import os +import sys +import subprocess + +def msg(s, fatal=False): + sys.stderr.write(s) + sys.stderr.flush() + if fatal: + sys.exit(1) class OnlPlatform_x86_64_ingrasys_s9180_32x_r0(OnlPlatformIngrasys): PLATFORM='x86-64-ingrasys-s9180-32x-r0' @@ -9,6 +17,11 @@ class OnlPlatform_x86_64_ingrasys_s9180_32x_r0(OnlPlatformIngrasys): def baseconfig(self): + # vid to mac vdd value mapping + vdd_val_array=( 0.85, 0.82, 0.77, 0.87, 0.74, 0.84, 0.79, 0.89 ) + # vid to rov reg value mapping + rov_reg_array=( 0x24, 0x21, 0x1C, 0x26, 0x19, 0x23, 0x1E, 0x28 ) + self.insmod("eeprom_mb") # init SYS EEPROM devices self.new_i2c_device('mb_eeprom', 0x55, 0) @@ -275,6 +288,16 @@ class OnlPlatform_x86_64_ingrasys_s9180_32x_r0(OnlPlatformIngrasys): self.new_i2c_device('eeprom', 0x50, 57) self.new_i2c_device('eeprom', 0x50, 58) + # _mac_vdd_init + reg_val_str = subprocess.check_output("""i2cget -y 44 0x33 0x42 2>/dev/null""", shell=True) + reg_val = int(reg_val_str, 16) + vid = reg_val & 0x7 + mac_vdd_val = vdd_val_array[vid] + rov_reg = rov_reg_array[vid] + + msg("Setting mac vdd %1.2f with rov register value 0x%x\n" % (mac_vdd_val, rov_reg) ) + os.system("i2cset -y -r 55 0x22 0x21 0x%x w" % rov_reg) + # init SYS LED os.system("i2cset -y -r 50 0x75 2 0x01") os.system("i2cset -y -r 50 0x75 4 0x00") diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/onlpdump/.gitignore b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/.gitignore old mode 100644 new mode 100755 similarity index 100% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/onlpdump/.gitignore rename to packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/.gitignore diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/PKG.yml b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/PKG.yml new file mode 100755 index 00000000..82fa39a8 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml ARCH=amd64 VENDOR=ingrasys BASENAME=x86-64-ingrasys-s9230-64x KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/.gitignore b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/Makefile new file mode 100644 index 00000000..8d3e3edc --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := ingrasys +BASENAME := x86-64-ingrasys-s9230-64x +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_i2c_cpld.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_i2c_cpld.c new file mode 100644 index 00000000..c9872f6a --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_i2c_cpld.c @@ -0,0 +1,1461 @@ +/* + * 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 + +#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 + +#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/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_i2c_cpld.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_i2c_cpld.h new file mode 100644 index 00000000..e0e53174 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/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/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_platform.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_platform.h new file mode 100644 index 00000000..a14853fd --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/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/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_psu.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_psu.c new file mode 100644 index 00000000..452fd3c2 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/modules/builds/ingrasys_s9230_64x_psu.c @@ -0,0 +1,536 @@ +/* + * 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 + +#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 + +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/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/PKG.yml b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/PKG.yml new file mode 100755 index 00000000..af72636a --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-ingrasys-s9230-64x ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/Makefile new file mode 100755 index 00000000..ad00e339 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-ingrasys-s9230-64x +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_ingrasys_s9230_64x onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-ingrasys-s9230-64x.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/libonlp-x86-64-ingrasys-s9230-64x.mk b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/libonlp-x86-64-ingrasys-s9230-64x.mk new file mode 100644 index 00000000..a5c9b52e --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/lib/libonlp-x86-64-ingrasys-s9230-64x.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-ingrasys-s9230-64x module. +# +# Autogenerated 2018-08-10 02:00:54.722838 +# +############################################################################### +libonlp-x86-64-ingrasys-s9230-64x_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/onlpdump/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..e4f319cb --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/onlpdump/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_ingrasys_s9230_64x onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.gitignore b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.gitignore new file mode 100755 index 00000000..760be8d1 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.gitignore @@ -0,0 +1,2 @@ +/x86_64_ingrasys_s9230_64x.mk +/doc diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.module b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.module new file mode 100755 index 00000000..07bc03d0 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/.module @@ -0,0 +1 @@ +name: x86_64_ingrasys_s9230_64x diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/Makefile new file mode 100755 index 00000000..b75a4beb --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/Makefile @@ -0,0 +1,10 @@ +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.mk + +MODULE := x86_64_ingrasys_s9230_64x +AUTOMODULE := x86_64_ingrasys_s9230_64x +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/make.mk b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/make.mk new file mode 100755 index 00000000..cda8fa40 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/make.mk @@ -0,0 +1,7 @@ +# +# x86_64_ingrasys_s9230_64x Autogeneration +# +############################################################################### +x86-64-ingrasys-s9230-64x_AUTO_DEFS := module/auto/x86-64-ingrasys-s9230-64x.yml +x86-64-ingrasys-s9230-64x_AUTO_DIRS := module/inc/x86-64-ingrasys-s9230-64x module/src +include $(BUILDER)/auto.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/x86-64-ingrasys-s9230-64x.yml b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/x86-64-ingrasys-s9230-64x.yml new file mode 100755 index 00000000..eca6af03 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/auto/x86-64-ingrasys-s9230-64x.yml @@ -0,0 +1,47 @@ +############################################################################### +# +# X86_64_INGRASYS_S9230_64X Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_INGRASYS_S9230_64X_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_INGRASYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_INGRASYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_INGRASYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_INGRASYS_S9230_64X_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_INGRASYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_INGRASYS_S9230_64X_CONFIG_PORTING_STDLIB +- X86_64_INGRASYS_S9230_64X_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 + + +definitions: + cdefs: + X86_64_INGRASYS_S9230_64X_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_ingrasys_s9230_64x_config + + portingmacro: + X86_64_INGRASYS_S9230_64X: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x.x b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x.x new file mode 100755 index 00000000..e46a5c5c --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x.x @@ -0,0 +1,34 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_config.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_config.h new file mode 100755 index 00000000..dfafa00a --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_config.h @@ -0,0 +1,162 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +/**************************************************************************//** + * + * @file + * @brief x86_64_ingrasys_s9230_64x Configuration Header + * + * @addtogroup x86_64_ingrasys_s9230_64x-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_INGRAYSYS_S9230_64X_CONFIG_H__ +#define __X86_64_INGRAYSYS_S9230_64X_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT + * + * SFP Count. */ + + +#ifndef X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT +#define X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_ingrasys_s9230_64x_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_ingrasys_s9230_64x_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_ingrasys_s9230_64x_config_settings table. */ +extern x86_64_ingrasys_s9230_64x_config_settings_t x86_64_ingrasys_s9230_64x_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_ingrasys_s9230_64x_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_ingrasys_s9230_64x_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_ingrasys_s9230_64x_porting.h" + +#endif /* __X86_64_INGRAYSYS_S9230_64X_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_dox.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_dox.h new file mode 100755 index 00000000..fa93c32f --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_ingrasys_s9230_64x Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_ingrasys_s9230_64x_DOX_H__ +#define __x86_64_ingrasys_s9230_64x_DOX_H__ + +/** + * @defgroup x86_64_ingrasys_s9230_64x x86_64_ingrasys_s9230_64x - x86_64_ingrasys_s9230_64x Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_ingrasys_s9230_64x-x86_64_ingrasys_s9230_64x Public Interface + * @defgroup x86_64_ingrasys_s9230_64x-config Compile Time Configuration + * @defgroup x86_64_ingrasys_s9230_64x-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_ingrasys_s9230_64x_DOX_H__ */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_porting.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_porting.h new file mode 100755 index 00000000..5d93fafc --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/inc/x86_64_ingrasys_s9230_64x/x86_64_ingrasys_s9230_64x_porting.h @@ -0,0 +1,106 @@ +/********************************************************//** + * + * @file + * @brief x86_64_Ingrasys_s9230_64x Porting Macros. + * + * @addtogroup x86_64_Ingrasys_s9230_64x-porting + * @{ + * + ***********************************************************/ +#ifndef __X86_64_INGRAYSYS_S9230_64X_PORTING_H__ +#define __X86_64_INGRAYSYS_S9230_64X_PORTING_H__ + +/* */ +#if X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_INGRAYSYS_S9230_64X_MALLOC GLOBAL_MALLOC + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_MALLOC malloc + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_FREE + #if defined(GLOBAL_FREE) + #define X86_64_INGRAYSYS_S9230_64X_FREE GLOBAL_FREE + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_FREE free + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_INGRAYSYS_S9230_64X_MEMSET GLOBAL_MEMSET + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_MEMSET memset + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_INGRAYSYS_S9230_64X_MEMCPY GLOBAL_MEMCPY + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_MEMCPY memcpy + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_INGRAYSYS_S9230_64X_STRNCPY GLOBAL_STRNCPY + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_STRNCPY strncpy + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_INGRAYSYS_S9230_64X_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_VSNPRINTF vsnprintf + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_INGRAYSYS_S9230_64X_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_SNPRINTF snprintf + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_INGRAYSYS_S9230_64X_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_INGRAYSYS_S9230_64X_STRLEN GLOBAL_STRLEN + #elif X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_INGRAYSYS_S9230_64X_STRLEN strlen + #else + #error The macro X86_64_INGRAYSYS_S9230_64X_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_INGRAYSYS_S9230_64X_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/make.mk b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/make.mk new file mode 100755 index 00000000..2ec88321 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/make.mk @@ -0,0 +1,29 @@ +############################################################ +# +# +# Copyright 2014, 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_ingrasys_s9230_64x_INCLUDES := -I $(THIS_DIR)inc +x86_64_ingrasys_s9230_64x_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_ingrasys_s9230_64x_DEPENDMODULE_ENTRIES := init:x86_64_ingrasys_s9230_64x ucli:x86_64_ingrasys_s9230_64x + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/Makefile new file mode 100755 index 00000000..140dba65 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/Makefile @@ -0,0 +1,30 @@ +############################################################ +# +# +# Copyright 2014, 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# Local source generation targets. +# +############################################################ + +include ../../../../init.mk + +ucli: + $(SUBMODULE_BIGCODE)/tools/uclihandlers.py x86_64_ingrasys_s9230_64x_ucli.c + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/fani.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/fani.c new file mode 100755 index 00000000..b060d04e --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/fani.c @@ -0,0 +1,272 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include "x86_64_ingrasys_s9230_64x_int.h" +#include +#include +#include "platform_lib.h" + +onlp_fan_info_t fan_info[] = { + { }, /* Not used */ + { + { FAN_OID_FAN1, "FANTRAY 1", 0 }, + ONLP_FAN_STATUS_PRESENT, + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, + 0, + 0, + ONLP_FAN_MODE_INVALID, + }, + { + { FAN_OID_FAN2, "FANTRAY 2", 0 }, + ONLP_FAN_STATUS_PRESENT, + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, + 0, + 0, + ONLP_FAN_MODE_INVALID, + }, + { + { FAN_OID_FAN3, "FANTRAY 3", 0 }, + ONLP_FAN_STATUS_PRESENT, + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, + 0, + 0, + ONLP_FAN_MODE_INVALID, + }, + { + { FAN_OID_FAN4, "FANTRAY 4", 0 }, + ONLP_FAN_STATUS_PRESENT, + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, + 0, + 0, + ONLP_FAN_MODE_INVALID, + }, + { + { FAN_OID_PSU_FAN1, "PSU-1 FAN", 0 }, + ONLP_FAN_STATUS_PRESENT, + }, + { + { FAN_OID_PSU_FAN2, "PSU-2 FAN", 0 }, + ONLP_FAN_STATUS_PRESENT, + } +}; + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int sys_fan_present_get(onlp_fan_info_t* info, int id) +{ + int rv, fan_presence, i2c_bus, offset, fan_reg_mask; + + /* get fan presence*/ + i2c_bus = I2C_BUS_FANTRAY_LED; + switch (id) + { + case FAN_ID_FAN1: + offset = 0; + fan_reg_mask = FAN_1_PRESENT_MASK; + break; + case FAN_ID_FAN2: + offset = 0; + fan_reg_mask = FAN_2_PRESENT_MASK; + break; + case FAN_ID_FAN3: + offset = 1; + fan_reg_mask = FAN_3_PRESENT_MASK; + break; + case FAN_ID_FAN4: + offset = 1; + fan_reg_mask = FAN_4_PRESENT_MASK; + break; + default: + return ONLP_STATUS_E_INVALID; + } + + rv = onlp_i2c_readb(i2c_bus, FAN_GPIO_ADDR, offset, ONLP_I2C_F_FORCE); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + fan_presence = (rv & fan_reg_mask) ? 0 : 1; + + if (!fan_presence) { + info->status &= ~ONLP_FAN_STATUS_PRESENT; + + } else { + info->status |= ONLP_FAN_STATUS_PRESENT; + } + + return ONLP_STATUS_OK; +} + +int +sys_fan_info_get(onlp_fan_info_t* info, int id) +{ + int rv, fan_status, fan_rpm, perc_val, percentage; + int max_fan_speed = 10000; + fan_status = 0; + fan_rpm = 0; + + rv = sys_fan_present_get(info, id); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + rv = onlp_file_read_int(&fan_status, SYS_FAN_PREFIX "fan%d_alarm", 2 * id - 1); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + /* fan status > 1, means failure */ + if (fan_status > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + rv = onlp_file_read_int(&fan_rpm, SYS_FAN_PREFIX "fan%d_input", 2 * id - 1); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = fan_rpm; + + /* get speed percentage*/ + switch (id) + { + case FAN_ID_FAN1: + case FAN_ID_FAN2: + case FAN_ID_FAN3: + case FAN_ID_FAN4: + rv = onlp_file_read_int(&perc_val, SYS_FAN_PREFIX "pwm%d", + FAN_CTRL_SET2); + break; + default: + return ONLP_STATUS_E_INVALID; + } + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + percentage = (info->rpm*100)/max_fan_speed; + info->percentage = percentage; + + return ONLP_STATUS_OK; +} + +int +sys_fan_rpm_percent_set(int perc) +{ + int rc; + + rc = onlp_file_write_int(perc, SYS_FAN_PREFIX "pwm%d", FAN_CTRL_SET2); + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int percentage) +{ + int fid, perc_val, rc; + fid = ONLP_OID_ID_GET(id); + + /* + * Set fan speed + * Driver accept value in range between 128 and 255. + * Value 128 is 50%. + * Value 200 is 80%. + * Value 255 is 100%. + */ + if (percentage == 100) { + perc_val = 255; + } else if (percentage == 80) { + perc_val = 200; + } else if (percentage == 50) { + perc_val = 128; + } else { + return ONLP_STATUS_E_INVALID; + } + + switch (fid) + { + case FAN_ID_FAN1: + case FAN_ID_FAN2: + case FAN_ID_FAN3: + case FAN_ID_FAN4: + rc = sys_fan_rpm_percent_set(perc_val); + break; + default: + return ONLP_STATUS_E_INVALID; + } + return rc; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* rv) +{ + int fan_id ,rc; + + fan_id = ONLP_OID_ID_GET(id); + *rv = fan_info[fan_id]; + rv->caps |= ONLP_FAN_CAPS_GET_RPM; + + switch (fan_id) { + case FAN_ID_FAN1: + case FAN_ID_FAN2: + case FAN_ID_FAN3: + case FAN_ID_FAN4: + rc = sys_fan_info_get(rv, fan_id); + break; + case FAN_ID_PSU_FAN1: + case FAN_ID_PSU_FAN2: + rc = psu_fan_info_get(rv, fan_id); + break; + default: + return ONLP_STATUS_E_INTERNAL; + break; + } + + return rc; +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/ledi.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/ledi.c new file mode 100755 index 00000000..36f7612a --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/ledi.c @@ -0,0 +1,223 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t led_info[] = +{ + { }, /* Not used */ + { + { LED_OID_SYSTEM, "Chassis LED 1 (SYS LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN, + }, + { + { LED_OID_FAN, "Chassis LED 2 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_PSU1, "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_PSU2, "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_FAN_TRAY1, "Rear LED 1 (FAN TRAY1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_FAN_TRAY2, "Rear LED 2 (FAN TRAY2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_FAN_TRAY3, "Rear LED 3 (FAN TRAY3 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { LED_OID_FAN_TRAY4, "Rear LED 4 (FAN TRAY4 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + } +}; + +extern int sys_fan_info_get(onlp_fan_info_t* info, int id); + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int led_id, pw_exist, pw_good, rc, fan_id; + onlp_fan_info_t fan_info; + char *sys_psu_prefix = NULL; + + memset(&fan_info, 0, sizeof(onlp_fan_info_t)); + led_id = ONLP_OID_ID_GET(id); + + *info = led_info[led_id]; + + if (id == LED_OID_PSU1 || id == LED_OID_PSU2) { + + if (id == LED_OID_PSU1) { + sys_psu_prefix = SYS_PSU1_PREFIX; + + } else { + sys_psu_prefix = SYS_PSU2_PREFIX; + } + /* check psu status */ + if ((rc = psu_present_get(&pw_exist, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + if ((rc = psu_pwgood_get(&pw_good, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + /* psu not present */ + if (pw_exist != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_LED_STATUS_ON; + info->mode = ONLP_LED_MODE_OFF; + } else if (pw_good != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_ORANGE; + } else { + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_GREEN; + } + } else if (id == LED_OID_FAN) { + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_GREEN; + for (fan_id=FAN_ID_FAN1; fan_id<=FAN_ID_FAN4; ++fan_id) { + rc = sys_fan_info_get(&fan_info, fan_id); + if (rc != ONLP_STATUS_OK || fan_info.status & ONLP_FAN_STATUS_FAILED) { + info->mode &= ~ONLP_LED_MODE_GREEN; + info->mode |= ONLP_LED_MODE_ORANGE; + break; + } + } + } else if (id == LED_OID_SYSTEM) { + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_GREEN; + } else { + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_ON; + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int led_id, rc; + + led_id = ONLP_OID_ID_GET(id); + switch (led_id) { + case LED_SYSTEM_LED: + rc = system_led_set(mode); + break; + case LED_FAN_LED: + rc = fan_led_set(mode); + break; + case LED_PSU1_LED: + rc = psu1_led_set(mode); + break; + case LED_PSU2_LED: + rc = psu2_led_set(mode); + break; + case LED_FAN_TRAY1: + case LED_FAN_TRAY2: + case LED_FAN_TRAY3: + case LED_FAN_TRAY4: + rc = fan_tray_led_set(id, mode); + break; + default: + return ONLP_STATUS_E_INTERNAL; + break; + } + + return rc; +} + +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/make.mk b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/make.mk new file mode 100755 index 00000000..a1b7ffae --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/make.mk @@ -0,0 +1,29 @@ +############################################################ +# +# +# Copyright 2014, 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ + +LIBRARY := x86_64_ingrasys_s9230_64x +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +#$(LIBRARY)_LAST := 1 +include $(BUILDER)/lib.mk diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.c new file mode 100755 index 00000000..8e91b7d1 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.c @@ -0,0 +1,583 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +int +psu_thermal_get(onlp_thermal_info_t* info, int thermal_id) +{ + int pw_exist, pw_good; + int offset, i2c_bus, rc; + int value, buf; + unsigned int y_value = 0; + unsigned char n_value = 0; + unsigned int temp = 0; + char result[32]; + char *sys_psu_prefix = NULL; + + if (thermal_id == THERMAL_ID_PSU1_1) { + i2c_bus = I2C_BUS_PSU1; + offset = PSU_THERMAL1_OFFSET; + sys_psu_prefix = SYS_PSU1_PREFIX; + } else if (thermal_id == THERMAL_ID_PSU1_2) { + i2c_bus = I2C_BUS_PSU1; + offset = PSU_THERMAL2_OFFSET; + sys_psu_prefix = SYS_PSU1_PREFIX; + } else if (thermal_id == THERMAL_ID_PSU2_1) { + i2c_bus = I2C_BUS_PSU2; + offset = PSU_THERMAL1_OFFSET; + sys_psu_prefix = SYS_PSU2_PREFIX; + } else if (thermal_id == THERMAL_ID_PSU2_2) { + i2c_bus = I2C_BUS_PSU2; + offset = PSU_THERMAL2_OFFSET; + sys_psu_prefix = SYS_PSU2_PREFIX; + } + + /* check psu status */ + if ((rc = psu_present_get(&pw_exist, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_exist != PSU_STATUS_PRESENT) { + info->mcelsius = 0; + info->status &= ~ONLP_THERMAL_STATUS_PRESENT; + return ONLP_STATUS_OK; + } else { + info->status |= ONLP_THERMAL_STATUS_PRESENT; + } + + if ((rc = psu_pwgood_get(&pw_good, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_good != PSU_STATUS_POWER_GOOD) { + info->mcelsius = 0; + return ONLP_STATUS_OK; + } + + value = onlp_i2c_readw(i2c_bus, PSU_REG, offset, ONLP_I2C_F_FORCE); + + y_value = (value & 0x07FF); + if ((value & 0x8000)&&(y_value)) { + n_value = 0xF0 + (((value) >> 11) & 0x0F); + n_value = (~n_value) +1; + temp = (unsigned int)(1<> 11) & 0x0F); + snprintf(result, sizeof(result), "%d", (y_value*(1<mcelsius = (int)(buf * 1000); + + return ONLP_STATUS_OK; +} + +int +psu_fan_info_get(onlp_fan_info_t* info, int id) +{ + int pw_exist, pw_good; + int i2c_bus, rc; + unsigned int tmp_fan_rpm, fan_rpm; + char *sys_psu_prefix = NULL; + + if (id == FAN_ID_PSU_FAN1) { + i2c_bus = I2C_BUS_PSU1; + sys_psu_prefix = SYS_PSU1_PREFIX; + } else if (id == FAN_ID_PSU_FAN2) { + i2c_bus = I2C_BUS_PSU2; + sys_psu_prefix = SYS_PSU2_PREFIX; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + /* check psu status */ + if ((rc = psu_present_get(&pw_exist, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_exist != PSU_STATUS_PRESENT) { + info->rpm = 0; + info->status &= ~ONLP_FAN_STATUS_PRESENT; + return ONLP_STATUS_OK; + } else { + info->status |= ONLP_FAN_STATUS_PRESENT; + } + + if ((rc = psu_pwgood_get(&pw_good, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_good != PSU_STATUS_POWER_GOOD) { + info->rpm = 0; + return ONLP_STATUS_OK; + } + + tmp_fan_rpm = onlp_i2c_readw(i2c_bus, PSU_REG, PSU_FAN_RPM_OFFSET, ONLP_I2C_F_FORCE); + + fan_rpm = (unsigned int)tmp_fan_rpm; + fan_rpm = (fan_rpm & 0x07FF) * (1 << ((fan_rpm >> 11) & 0x1F)); + info->rpm = (int)fan_rpm; + + return ONLP_STATUS_OK; +} + +int +psu_vout_get(onlp_psu_info_t* info, int i2c_bus) +{ + int v_value = 0; + int n_value = 0; + unsigned int temp = 0; + char result[32]; + double dvalue; + memset(result, 0, sizeof(result)); + + n_value = onlp_i2c_readb(i2c_bus, PSU_REG, PSU_VOUT_OFFSET1, ONLP_I2C_F_FORCE); + if (n_value < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + v_value = onlp_i2c_readw(i2c_bus, PSU_REG, PSU_VOUT_OFFSET2, ONLP_I2C_F_FORCE); + if (v_value < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + if (n_value & 0x10) { + n_value = 0xF0 + (n_value & 0x0F); + n_value = (~n_value) +1; + temp = (unsigned int)(1< 0.0) { + info->caps |= ONLP_PSU_CAPS_VOUT; + info->mvout = (int)(dvalue * 1000); + } + + return ONLP_STATUS_OK; +} + +int +psu_iout_get(onlp_psu_info_t* info, int i2c_bus) +{ + int value; + unsigned int y_value = 0; + unsigned char n_value = 0; + unsigned int temp = 0; + char result[32]; + memset(result, 0, sizeof(result)); + double dvalue; + + value = onlp_i2c_readw(i2c_bus, PSU_REG, PSU_IOUT_OFFSET, ONLP_I2C_F_FORCE); + if (value < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + y_value = (value & 0x07FF); + if ((value & 0x8000)&&(y_value)) + { + n_value = 0xF0 + (((value) >> 11) & 0x0F); + n_value = (~n_value) +1; + temp = (unsigned int)(1<> 11) & 0x0F); + snprintf(result, sizeof(result), "%d", (y_value*(1< 0.0) { + info->caps |= ONLP_PSU_CAPS_IOUT; + info->miout = (int)(dvalue * 1000); + } + + return ONLP_STATUS_OK; +} + +int +psu_pout_get(onlp_psu_info_t* info, int i2c_bus) +{ + int value; + unsigned int y_value = 0; + unsigned char n_value = 0; + unsigned int temp = 0; + char result[32]; + memset(result, 0, sizeof(result)); + double dvalue; + + value = onlp_i2c_readw(i2c_bus, PSU_REG, PSU_POUT_OFFSET, ONLP_I2C_F_FORCE); + if (value < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + y_value = (value & 0x07FF); + if ((value & 0x8000)&&(y_value)) + { + n_value = 0xF0 + (((value) >> 11) & 0x0F); + n_value = (~n_value) +1; + temp = (unsigned int)(1<> 11) & 0x0F); + snprintf(result, sizeof(result), "%d", (y_value*(1< 0.0) { + info->caps |= ONLP_PSU_CAPS_POUT; + info->mpout = (int)(dvalue * 1000); + } + + return ONLP_STATUS_OK; +} + +int +psu_pin_get(onlp_psu_info_t* info, int i2c_bus) +{ + int value; + unsigned int y_value = 0; + unsigned char n_value = 0; + unsigned int temp = 0; + char result[32]; + memset(result, 0, sizeof(result)); + double dvalue; + + value = onlp_i2c_readw(i2c_bus, PSU_REG, PSU_PIN_OFFSET, ONLP_I2C_F_FORCE); + if (value < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + y_value = (value & 0x07FF); + if ((value & 0x8000)&&(y_value)) + { + n_value = 0xF0 + (((value) >> 11) & 0x0F); + n_value = (~n_value) +1; + temp = (unsigned int)(1<> 11) & 0x0F); + snprintf(result, sizeof(result), "%d", (y_value*(1< 0.0) { + info->caps |= ONLP_PSU_CAPS_PIN; + info->mpin = (int)(dvalue * 1000); + } + + return ONLP_STATUS_OK; +} + +int +psu_eeprom_get(onlp_psu_info_t* info, int id) +{ + uint8_t data[256]; + char eeprom_path[128]; + int data_len, i, rc; + memset(data, 0, sizeof(data)); + memset(eeprom_path, 0, sizeof(eeprom_path)); + + if (id == PSU_ID_PSU1) { + rc = onlp_file_read(data, sizeof(data), &data_len, PSU1_EEPROM_PATH); + } else { + rc = onlp_file_read(data, sizeof(data), &data_len, PSU2_EEPROM_PATH); + } + + if (rc == ONLP_STATUS_OK) + { + i = 11; + + /* Manufacturer Name */ + data_len = (data[i]&0x0f); + i++; + i += data_len; + + /* Product Name */ + data_len = (data[i]&0x0f); + i++; + memcpy(info->model, (char *) &(data[i]), data_len); + i += data_len; + + /* Product part,model number */ + data_len = (data[i]&0x0f); + i++; + i += data_len; + + /* Product Version */ + data_len = (data[i]&0x0f); + i++; + i += data_len; + + /* Product Serial Number */ + data_len = (data[i]&0x0f); + i++; + memcpy(info->serial, (char *) &(data[i]), data_len); + } else { + strcpy(info->model, "Missing"); + strcpy(info->serial, "Missing"); + } + + return ONLP_STATUS_OK; +} + + +int +psu_present_get(int *pw_exist, char *sys_psu_prefix) +{ + int rv, psu_pres; + + rv = onlp_file_read_int(&psu_pres, "%spsu_abs", sys_psu_prefix); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + *pw_exist = (psu_pres ? 0 : 1); + return ONLP_STATUS_OK; +} + +int +psu_pwgood_get(int *pw_good, char *sys_psu_prefix) +{ + int rv, psu_pwgood; + + rv = onlp_file_read_int(&psu_pwgood, "%spsu_pg", sys_psu_prefix); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + *pw_good = (psu_pwgood ? 1 : 0); + return ONLP_STATUS_OK; +} + +int +system_led_set(onlp_led_mode_t mode) +{ + int rc; + if(mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, LED_SYS_AND_MASK, + LED_SYS_GMASK, ONLP_I2C_F_FORCE); + } + else if(mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, LED_SYS_AND_MASK, + LED_SYS_YMASK, ONLP_I2C_F_FORCE); + } else { + return ONLP_STATUS_E_INTERNAL; + } + + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +fan_led_set(onlp_led_mode_t mode) +{ + int rc; + + if(mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, LED_FAN_AND_MASK, + LED_FAN_GMASK, ONLP_I2C_F_FORCE); + } + else if(mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, LED_FAN_AND_MASK, + LED_FAN_YMASK, ONLP_I2C_F_FORCE); + } + else if(mode == ONLP_LED_MODE_OFF) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, LED_FAN_AND_MASK, + LED_FAN_OFFMASK, ONLP_I2C_F_FORCE); + } else { + return ONLP_STATUS_E_INTERNAL; + } + + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +psu1_led_set(onlp_led_mode_t mode) +{ + int rc; + if(mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU1_AND_MASK, LED_PSU1_GMASK, + ONLP_I2C_F_FORCE); + } else if(mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU1_AND_MASK, LED_PSU1_YMASK, + ONLP_I2C_F_FORCE); + } else if(mode == ONLP_LED_MODE_OFF) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU1_AND_MASK, LED_PSU1_OFFMASK, + ONLP_I2C_F_FORCE); + } else { + return ONLP_STATUS_E_INTERNAL; + } + + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +psu2_led_set(onlp_led_mode_t mode) +{ + int rc; + if(mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU2_AND_MASK, LED_PSU2_GMASK, + ONLP_I2C_F_FORCE); + } else if(mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU2_AND_MASK, LED_PSU2_YMASK, + ONLP_I2C_F_FORCE); + } else if(mode == ONLP_LED_MODE_OFF) { + rc = onlp_i2c_modifyb(I2C_BUS_SYS_LED, LED_REG, LED_OFFSET, + LED_PSU2_AND_MASK, LED_PSU2_OFFMASK, + ONLP_I2C_F_FORCE); + } else { + return ONLP_STATUS_E_INTERNAL; + } + + + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +fan_tray_led_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int rc, temp_id; + int fan_tray_id, offset; + + temp_id = ONLP_OID_ID_GET(id); + switch (temp_id) { + case LED_FAN_TRAY1: + fan_tray_id = 1; + offset = 2; + break; + case LED_FAN_TRAY2: + fan_tray_id = 2; + offset = 2; + break; + case LED_FAN_TRAY3: + fan_tray_id = 3; + offset = 3; + break; + case LED_FAN_TRAY4: + fan_tray_id = 4; + offset = 3; + break; + default: + return ONLP_STATUS_E_INTERNAL; + break; + } + if (fan_tray_id == 1 || fan_tray_id == 3) { + if (mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_FANTRAY_LED, FAN_GPIO_ADDR, offset, 0xFC, + 0x01, ONLP_I2C_F_FORCE); + } else if (mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_FANTRAY_LED, FAN_GPIO_ADDR, offset, 0xFC, + 0x02, ONLP_I2C_F_FORCE); + } + } else if (fan_tray_id == 2 || fan_tray_id == 4) { + if (mode == ONLP_LED_MODE_GREEN) { + rc = onlp_i2c_modifyb(I2C_BUS_FANTRAY_LED, FAN_GPIO_ADDR, offset, 0xCF, + 0x10, ONLP_I2C_F_FORCE); + } else if (mode == ONLP_LED_MODE_ORANGE) { + rc = onlp_i2c_modifyb(I2C_BUS_FANTRAY_LED, FAN_GPIO_ADDR, offset, 0xCF, + 0x20, ONLP_I2C_F_FORCE); + } + } + if (rc < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int cpld_version, cpld_rev; + int bus_i; + char line[64] = "", output[512] = ""; + + for(bus_i=I2C_BUS_CPLD1; bus_i <= I2C_BUS_CPLD5; ++bus_i) { + + int rv; + rv = onlp_file_read_int(&cpld_rev, CPLD_REG_PATH, bus_i, CPLD_REG, CPLD_VERSION_KEY); + if (rv < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + if (cpld_rev < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + cpld_version = (((cpld_rev) & 0x3F)); + + snprintf(line, sizeof(line), "CPLD%d:0x%x, ", bus_i, cpld_version); + strcat(output, line); + } + + pi->cpld_versions = aim_fstrdup("%s", output); + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.h new file mode 100755 index 00000000..29384cf5 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/platform_lib.h @@ -0,0 +1,309 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include +#include +#include +#include +#include +#include "x86_64_ingrasys_s9230_64x_int.h" +#include "x86_64_ingrasys_s9230_64x_log.h" +#include + +#define SYS_CPU_TEMP_PREFIX "/sys/class/hwmon/hwmon0/" +#define SYS_REAR_PANEL_TEMP_PREFIX "/sys/class/hwmon/hwmon1/" +#define SYS_REAR_MAC_TEMP_PREFIX "/sys/class/hwmon/hwmon2/" +#define SYS_FRONT_PANEL_PREFIX "/sys/class/hwmon/hwmon3/" +#define SYS_FRONT_MAC_PREFIX "/sys/class/hwmon/hwmon4/" +#define SYS_BMC_BOARD_PREFIX "/sys/class/hwmon/hwmon5/" +#define SYS_CPU_BOARD_PREFIX "/sys/class/hwmon/hwmon6/" +#define SYS_FAN_PREFIX "/sys/class/hwmon/hwmon7/device/" +#define SYS_PSU1_PREFIX "/sys/bus/i2c/devices/i2c-18/18-0050/" +#define SYS_PSU2_PREFIX "/sys/bus/i2c/devices/i2c-17/17-0050/" +#define SYS_EEPROM_PATH "/sys/bus/i2c/devices/0-0051/eeprom" +#define SYS_EEPROM_SIZE 512 +#define PSU1_EEPROM_PATH "/sys/bus/i2c/devices/18-0050/psu_eeprom" +#define PSU2_EEPROM_PATH "/sys/bus/i2c/devices/17-0050/psu_eeprom" +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 +#define FAN_PRESENT 0 +#define FAN_CTRL_SET1 1 +#define FAN_CTRL_SET2 2 +#define BOARD_THERMAL_NUM 6 +#define SYS_FAN_NUM 4 +#define PORT_NUM 66 + +#define THERMAL_NUM 14 +#define LED_NUM 4 +#define FAN_NUM 6 + + + +#define THERMAL_SHUTDOWN_DEFAULT 105000 + +#define THERMAL_ERROR_DEFAULT 95000 +#define THERMAL_ERROR_FAN_PERC 100 + +#define THERMAL_WARNING_DEFAULT 77000 +#define THERMAL_WARNING_FAN_PERC 80 + +#define THERMAL_NORMAL_DEFAULT 72000 +#define THERMAL_NORMAL_FAN_PERC 50 + +/* I2C bus */ +#define I2C_BUS_0 0 +#define I2C_BUS_1 1 +#define I2C_BUS_2 2 +#define I2C_BUS_3 3 +#define I2C_BUS_4 4 +#define I2C_BUS_5 5 +#define I2C_BUS_10 10 /* SYS_LED */ +#define I2C_BUS_17 (17) /* PSU2 */ +#define I2C_BUS_18 (18) /* PSU1 */ + +#define I2C_BUS_PSU1 I2C_BUS_18 /* PSU1 */ +#define I2C_BUS_PSU2 I2C_BUS_17 /* PSU2 */ +#define I2C_BUS_SYS_LED I2C_BUS_10 /* SYS LED */ +#define I2C_BUS_FANTRAY_LED I2C_BUS_0 /* FANTRAY LED */ +#define I2C_BUS_CPLD1 I2C_BUS_1 /* CPLD 1 */ +#define I2C_BUS_CPLD2 I2C_BUS_2 /* CPLD 2 */ +#define I2C_BUS_CPLD3 I2C_BUS_3 /* CPLD 3 */ +#define I2C_BUS_CPLD4 I2C_BUS_4 /* CPLD 4 */ +#define I2C_BUS_CPLD5 I2C_BUS_5 /* CPLD 5 */ + +/* PSU */ +#define PSU_MUX_MASK 0x01 + +#define PSU_THERMAL1_OFFSET 0x8D +#define PSU_THERMAL2_OFFSET 0x8E +#define PSU_THERMAL_REG 0x58 +#define PSU_FAN_RPM_REG 0x58 +#define PSU_FAN_RPM_OFFSET 0x90 +#define PSU_REG 0x58 +#define PSU_VOUT_OFFSET1 0x20 +#define PSU_VOUT_OFFSET2 0x8B +#define PSU_IOUT_OFFSET 0x8C +#define PSU_POUT_OFFSET 0x96 +#define PSU_PIN_OFFSET 0x97 + +#define PSU_STATE_REG 0x25 +#define PSU1_PRESENT_OFFSET 0x04 +#define PSU2_PRESENT_OFFSET 0x01 +#define PSU1_PWGOOD_OFFSET 0x03 +#define PSU2_PWGOOD_OFFSET 0x00 + +/* LED */ +#define LED_REG 0x76 +#define LED_OFFSET 0x02 +#define LED_PWOK_OFFSET 0x03 + +#define LED_SYS_AND_MASK 0x7F +#define LED_SYS_GMASK 0x80 +#define LED_SYS_YMASK 0x00 + +#define LED_FAN_AND_MASK 0x9F +#define LED_FAN_GMASK 0x40 +#define LED_FAN_YMASK 0x60 +#define LED_FAN_OFFMASK 0x00 + +#define LED_PSU2_AND_MASK 0xF9 +#define LED_PSU2_GMASK 0x04 +#define LED_PSU2_YMASK 0x06 +#define LED_PSU2_OFFMASK 0x00 + +#define LED_PSU1_AND_MASK 0xE7 +#define LED_PSU1_GMASK 0x10 +#define LED_PSU1_YMASK 0x18 +#define LED_PSU1_OFFMASK 0x00 + +#define LED_SYS_ON_MASK 0x00 +#define LED_SYS_OFF_MASK 0x33 + +/* SYS */ +#define CPLD_REG 0x33 +#define CPLD_VER_OFFSET 0x01 + +/* QSFP */ +#define QSFP_PRES_REG1 0x20 +#define QSFP_PRES_REG2 0x21 +#define QSFP_PRES_OFFSET1 0x00 +#define QSFP_PRES_OFFSET2 0x01 + +/* FANTRAY */ +#define FAN_GPIO_ADDR 0x20 +#define FAN_1_PRESENT_MASK 0x04 +#define FAN_2_PRESENT_MASK 0x40 +#define FAN_3_PRESENT_MASK 0x04 +#define FAN_4_PRESENT_MASK 0x40 + +/* CPLD */ +//#define CPLDx_I2C_ADDR 0x21 +#define QSFP_EEPROM_I2C_ADDR 0x50 +#define CPLD1_PORTS 12 +#define CPLDx_PORTS 13 +#define CPLD_OFFSET 1 +#define CPLD_QSFP_PRES_BIT 1 +#define CPLD_SFP_PRES_BIT 0 +#define CPLD_QSFP_REG_PATH "/sys/bus/i2c/devices/%d-00%02x/%s_%d" +#define CPLD_SFP_REG_PATH "/sys/bus/i2c/devices/%d-00%02x/%s" +#define CPLD_REG_PATH "/sys/bus/i2c/devices/%d-00%02x/%s" +#define CPLD_QSFP_PORT_STATUS_KEY "cpld_qsfp_port_status" +#define CPLD_SFP_PORT_STATUS_KEY "cpld_sfp_port_status" +#define CPLD_VERSION_KEY "cpld_version" + + + +/** led_oid */ +typedef enum led_oid_e { + LED_OID_SYSTEM = ONLP_LED_ID_CREATE(1), + LED_OID_FAN = ONLP_LED_ID_CREATE(2), + LED_OID_PSU1 = ONLP_LED_ID_CREATE(3), + LED_OID_PSU2 = ONLP_LED_ID_CREATE(4), + LED_OID_FAN_TRAY1 = ONLP_LED_ID_CREATE(5), + LED_OID_FAN_TRAY2 = ONLP_LED_ID_CREATE(6), + LED_OID_FAN_TRAY3 = ONLP_LED_ID_CREATE(7), + LED_OID_FAN_TRAY4 = ONLP_LED_ID_CREATE(8), +} led_oid_t; + +/** led_id */ +typedef enum led_id_e { + LED_SYSTEM_LED = 1, + LED_FAN_LED = 2, + LED_PSU1_LED = 3, + LED_PSU2_LED = 4, + LED_FAN_TRAY1 = 5, + LED_FAN_TRAY2 = 6, + LED_FAN_TRAY3 = 7, + LED_FAN_TRAY4 = 8, +} led_id_t; + +/** Thermal_oid */ +typedef enum thermal_oid_e { + THERMAL_OID_CPU1 = ONLP_THERMAL_ID_CREATE(1), + THERMAL_OID_CPU2 = ONLP_THERMAL_ID_CREATE(2), + THERMAL_OID_CPU3 = ONLP_THERMAL_ID_CREATE(3), + THERMAL_OID_CPU4 = ONLP_THERMAL_ID_CREATE(4), + THERMAL_OID_REAR_PANEL = ONLP_THERMAL_ID_CREATE(5), + THERMAL_OID_REAR_MAC = ONLP_THERMAL_ID_CREATE(6), + THERMAL_OID_FRONT_PANEL = ONLP_THERMAL_ID_CREATE(7), + THERMAL_OID_FRONT_MAC = ONLP_THERMAL_ID_CREATE(8), + THERMAL_OID_BMC_BOARD = ONLP_THERMAL_ID_CREATE(9), + THERMAL_OID_CPU_BOARD = ONLP_THERMAL_ID_CREATE(10), + THERMAL_OID_PSU1_1 = ONLP_THERMAL_ID_CREATE(11), + THERMAL_OID_PSU1_2 = ONLP_THERMAL_ID_CREATE(12), + THERMAL_OID_PSU2_1 = ONLP_THERMAL_ID_CREATE(13), + THERMAL_OID_PSU2_2 = ONLP_THERMAL_ID_CREATE(14), +} thermal_oid_t; + +/** thermal_id */ +typedef enum thermal_id_e { + THERMAL_ID_CPU1 = 1, + THERMAL_ID_CPU2 = 2, + THERMAL_ID_CPU3 = 3, + THERMAL_ID_CPU4 = 4, + THERMAL_ID_REAR_PANEL = 5, + THERMAL_ID_REAR_MAC = 6, + THERMAL_ID_FRONT_PANEL = 7, + THERMAL_ID_FRONT_MAC = 8, + THERMAL_ID_BMC_BOARD = 9, + THERMAL_ID_CPU_BOARD = 10, + THERMAL_ID_PSU1_1 = 11, + THERMAL_ID_PSU1_2 = 12, + THERMAL_ID_PSU2_1 = 13, + THERMAL_ID_PSU2_2 = 14, +} thermal_id_t; + +/* Shortcut for CPU thermal threshold value. */ +#define THERMAL_THRESHOLD_INIT_DEFAULTS \ + { THERMAL_WARNING_DEFAULT, \ + THERMAL_ERROR_DEFAULT, \ + THERMAL_SHUTDOWN_DEFAULT } + +/** Fan_oid */ +typedef enum fan_oid_e { + FAN_OID_FAN1 = ONLP_FAN_ID_CREATE(1), + FAN_OID_FAN2 = ONLP_FAN_ID_CREATE(2), + FAN_OID_FAN3 = ONLP_FAN_ID_CREATE(3), + FAN_OID_FAN4 = ONLP_FAN_ID_CREATE(4), + FAN_OID_PSU_FAN1 = ONLP_FAN_ID_CREATE(5), + FAN_OID_PSU_FAN2 = ONLP_FAN_ID_CREATE(6) +} fan_oid_t; + +/** fan_id */ +typedef enum fan_id_e { + FAN_ID_FAN1 = 1, + FAN_ID_FAN2 = 2, + FAN_ID_FAN3 = 3, + FAN_ID_FAN4 = 4, + FAN_ID_PSU_FAN1 = 5, + FAN_ID_PSU_FAN2 = 6 +} fan_id_t; + +/** led_oid */ +typedef enum psu_oid_e { + PSU_OID_PSU1 = ONLP_PSU_ID_CREATE(1), + PSU_OID_PSU2 = ONLP_PSU_ID_CREATE(2) +} psu_oid_t; + +/** fan_id */ +typedef enum psu_id_e { + PSU_ID_PSU1 = 1, + PSU_ID_PSU2 = 2 +} psu_id_t; + +int psu_thermal_get(onlp_thermal_info_t* info, int id); + +int psu_fan_info_get(onlp_fan_info_t* info, int id); + +int psu_vout_get(onlp_psu_info_t* info, int i2c_bus); + +int psu_iout_get(onlp_psu_info_t* info, int i2c_bus); + +int psu_pout_get(onlp_psu_info_t* info, int i2c_bus); + +int psu_pin_get(onlp_psu_info_t* info, int i2c_bus); + +int psu_eeprom_get(onlp_psu_info_t* info, int id); + +int psu_present_get(int *pw_exist, char *sys_psu_prefix); + +int psu_pwgood_get(int *pw_good, char *sys_psu_prefix); + +int psu2_led_set(onlp_led_mode_t mode); + +int psu1_led_set(onlp_led_mode_t mode); + +int fan_led_set(onlp_led_mode_t mode); + +int system_led_set(onlp_led_mode_t mode); + +int fan_tray_led_set(onlp_oid_t id, onlp_led_mode_t mode); + +int sysi_platform_info_get(onlp_platform_info_t* pi); + +#endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/psui.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/psui.c new file mode 100755 index 00000000..a8f385fb --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/psui.c @@ -0,0 +1,156 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include "platform_lib.h" + +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { + PSU_OID_PSU1, + "PSU-1", + 0, + { + FAN_OID_PSU_FAN1, + }, + } + }, + { + { + PSU_OID_PSU2, + "PSU-2", + 0, + { + FAN_OID_PSU_FAN2, + }, + } + } +}; + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +int +psu_status_info_get(int id, onlp_psu_info_t *info) +{ + int pw_exist, pw_good; + int rc, i2c_bus; + char *sys_psu_prefix = NULL; + + if (id == PSU_ID_PSU1) { + i2c_bus = I2C_BUS_PSU1; + sys_psu_prefix = SYS_PSU1_PREFIX; + } else if (id == PSU_ID_PSU2) { + i2c_bus = I2C_BUS_PSU2; + sys_psu_prefix = SYS_PSU2_PREFIX; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + /* Get power present status */ + if ((rc = psu_present_get(&pw_exist, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_exist != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + /* Get power good status */ + if ((rc = psu_pwgood_get(&pw_good, sys_psu_prefix)) + != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + if (pw_good != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + return ONLP_STATUS_OK; + } else { + info->status &= ~ONLP_PSU_STATUS_UNPLUGGED; + } + + /* Get power eeprom status */ + if ((rc = psu_eeprom_get(info, id)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + /* Get power iout status */ + if ((rc = psu_iout_get(info, i2c_bus)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + /* Get power pout status */ + if ((rc = psu_pout_get(info, i2c_bus)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + /* Get power pin status */ + if ((rc = psu_pin_get(info, i2c_bus)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + /* Get power vout status */ + if ((rc = psu_vout_get(info, i2c_bus)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int pid; + + pid = ONLP_OID_ID_GET(id); + memset(info, 0, sizeof(onlp_psu_info_t)); + + /* Set the onlp_oid_hdr_t */ + *info = pinfo[pid]; + + switch (pid) { + case PSU_ID_PSU1: + case PSU_ID_PSU2: + return psu_status_info_get(pid, info); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ONLP_STATUS_OK; + + +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sfpi.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sfpi.c new file mode 100755 index 00000000..2b65896d --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sfpi.c @@ -0,0 +1,182 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "x86_64_ingrasys_s9230_64x_log.h" +#include "platform_lib.h" + +static int _fp2phy_port_mapping[64] = { + 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30, + 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62, + 3, 4, 7, 8, 11, 12, 15, 16, 19, 20, 23, 24, 27, 28, 31, 32, + 35, 36, 39, 40, 43, 44, 47, 48, 51, 52, 55, 56, 59, 60, 63, 64}; + +static void +qsfp_to_cpld_index(int phy_port, int *cpld_id, int *cpld_port_index) +{ + phy_port = phy_port - 1; + if (phy_port < CPLD1_PORTS) { + *cpld_id = 0; + *cpld_port_index = phy_port + 1; + } else { + *cpld_id = 1 + (phy_port - CPLD1_PORTS) / CPLDx_PORTS; + *cpld_port_index = ((phy_port - CPLD1_PORTS) % CPLDx_PORTS) + 1; + } + return; +} + + +int +onlp_sfpi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + for(p = 1; p <= PORT_NUM; p++) { + AIM_BITMAP_SET(bmap, p); + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + int status, phy_port; + int i2c_id, cpld_id, cpld_port_index; + char reg_path[128]; + int value, mask; + uint8_t data[8]; + int data_len; + + if (port >= 1 && port <=64) { + phy_port = _fp2phy_port_mapping[port-1]; + qsfp_to_cpld_index(phy_port, &cpld_id, &cpld_port_index); + + i2c_id = CPLD_OFFSET + cpld_id; + mask = 1 << CPLD_QSFP_PRES_BIT; + + snprintf(reg_path, 128, CPLD_QSFP_REG_PATH, i2c_id, CPLD_REG, CPLD_QSFP_PORT_STATUS_KEY, cpld_port_index); + } else if (port>= 65 && port <= 66) { + cpld_port_index = 0; + mask = 1 << CPLD_SFP_PRES_BIT; + + if (port == 65) { + i2c_id = CPLD_OFFSET; + } else { + i2c_id = CPLD_OFFSET + 1; + } + + snprintf(reg_path, 128, CPLD_SFP_REG_PATH, i2c_id, CPLD_REG, CPLD_SFP_PORT_STATUS_KEY); + } else { + return ONLP_STATUS_E_INTERNAL; + } + + if (onlp_file_read(data, sizeof(data), &data_len, reg_path) == ONLP_STATUS_OK) { + //convert hex string to integer + value = (int) strtol ((char *) data, NULL, 16); + + if ( (value & mask) == 0) { + status = 1; + } else { + status = 0; + } + } else { + return ONLP_STATUS_E_INTERNAL; + } + + return status; +} + + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + int p = 1; + int rc = 0; + + for (p = 1; p <= PORT_NUM; p++) { + rc = onlp_sfpi_is_present(p); + AIM_BITMAP_MOD(dst, p, (1 == rc) ? 1 : 0); + } + + return ONLP_STATUS_OK; +} + +/* + * This function reads the SFPs idrom and returns in + * in the data buffer provided. + */ +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + int eeprombus=0, eeprombusbase=0, phy_port=0, port_group=0, eeprombusshift=0; + char eeprom_path[512], eeprom_addr[32]; + memset(eeprom_path, 0, sizeof(eeprom_path)); + memset(eeprom_addr, 0, sizeof(eeprom_addr)); + strncpy(eeprom_addr, "0050", sizeof(eeprom_addr)); + + memset(data, 0, 256); + + if (port >=1 && port <= 64) { + phy_port = _fp2phy_port_mapping[port-1]; + port_group = (phy_port-1)/8; + eeprombusbase = 33 + (port_group * 8); + eeprombusshift = (phy_port-1)%8; + eeprombus = eeprombusbase + eeprombusshift; + } else if (port == 65 ){ + eeprombus = 21; + } else if (port == 66 ){ + eeprombus = 22; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + snprintf(eeprom_path, sizeof(eeprom_path), + "/sys/bus/i2c/devices/%d-%s/eeprom", eeprombus, eeprom_addr); + + if (onlplib_sfp_eeprom_read_file(eeprom_path, data) != 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +/* + * De-initialize the SFPI subsystem. + */ +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sysi.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sysi.c new file mode 100755 index 00000000..1e6567a2 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/sysi.c @@ -0,0 +1,339 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-ingrasys-s9230-64x-r0"; +} + +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(SYS_EEPROM_SIZE); + if(onlp_file_read(rdata, SYS_EEPROM_SIZE, size, SYS_EEPROM_PATH) == ONLP_STATUS_OK) { + if(*size == SYS_EEPROM_SIZE) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + AIM_LOG_INFO("Unable to get data from eeprom \n"); + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + int i; + + /* 2 PSUs */ + *e++ = ONLP_PSU_ID_CREATE(1); + *e++ = ONLP_PSU_ID_CREATE(2); + + /* LEDs Item */ + for (i=1; i<=LED_NUM; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* THERMALs Item */ + for (i=1; i<=THERMAL_NUM; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* Fans Item */ + for (i=1; i<=FAN_NUM; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return ONLP_STATUS_OK; +} + +int +decide_fan_percentage(int is_up, int new_temp) +{ + int new_perc; + if (is_up) { + if (new_temp >= THERMAL_ERROR_DEFAULT) { + new_perc = THERMAL_ERROR_FAN_PERC; + } else if (new_temp >= THERMAL_WARNING_DEFAULT) { + new_perc = THERMAL_WARNING_FAN_PERC; + } else { + new_perc = THERMAL_NORMAL_FAN_PERC; + } + } else { + if (new_temp <= THERMAL_NORMAL_DEFAULT) { + new_perc = THERMAL_NORMAL_FAN_PERC; + } else if (new_temp <= THERMAL_WARNING_DEFAULT) { + new_perc = THERMAL_WARNING_FAN_PERC; + } else { + new_perc = THERMAL_ERROR_FAN_PERC; + } + } + + return new_perc; +} + +int +platform_thermal_temp_get(int *thermal_temp) +{ + int i, temp, max_temp, rc; + onlp_thermal_info_t thermal_info; + memset(&thermal_info, 0, sizeof(thermal_info)); + uint32_t thermal_arr[] = { THERMAL_OID_FRONT_MAC, + THERMAL_OID_REAR_MAC, + THERMAL_OID_CPU1, + THERMAL_OID_CPU2, + THERMAL_OID_CPU3, + THERMAL_OID_CPU4 }; + max_temp = 0; + + for (i=0; i max_temp) { + max_temp = temp; + } + } + *thermal_temp = max_temp; + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_fans(void) +{ + int rc, is_up ,new_temp, thermal_temp, diff; + static int new_perc = 0, ori_perc = 0; + static int ori_temp = 0; + onlp_thermal_info_t thermal_info; + memset(&thermal_info, 0, sizeof(thermal_info)); + + /* get new temperature */ + if ((rc = platform_thermal_temp_get(&thermal_temp)) != ONLP_STATUS_OK) { + goto _EXIT; + } + + new_temp = thermal_temp; + diff = new_temp - ori_temp; + + if (diff == 0) { + goto _EXIT; + } else { + is_up = (diff > 0 ? 1 : 0); + } + + new_perc = decide_fan_percentage(is_up, new_temp); + + if (ori_perc == new_perc) { + goto _EXIT; + } + + + AIM_LOG_INFO("The Fan Speeds Percent are now at %d%%", new_perc); + + if ((rc = onlp_fani_percentage_set(THERMAL_OID_REAR_MAC, new_perc)) != ONLP_STATUS_OK) { + goto _EXIT; + } + + /* update */ + ori_perc = new_perc; + ori_temp = new_temp; + +_EXIT : + return rc; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + int psu1_status, psu2_status, rc, i; + static int pre_psu1_status = 0, pre_psu2_status = 0, pre_fan_status = 0; + + //------------------------------- + static int pre_fan_tray_status[4] = {0}; + int fan_tray_id, sum, total = 0; + onlp_led_status_t fan_tray_status[SYS_FAN_NUM]; + //------------------------------- + + onlp_psu_info_t psu_info; + onlp_fan_info_t fan_info; + + //-------- ----------------------- + memset(&fan_tray_status, 0, sizeof(fan_tray_status)); + //------------------------------- + + memset(&psu_info, 0, sizeof(onlp_psu_info_t)); + memset(&fan_info, 0, sizeof(onlp_fan_info_t)); + uint32_t fan_arr[] = { FAN_OID_FAN1, + FAN_OID_FAN2, + FAN_OID_FAN3, + FAN_OID_FAN4, }; + + /* PSU LED CTRL */ + if ((rc = onlp_psui_info_get(PSU_OID_PSU1, &psu_info)) != ONLP_STATUS_OK) { + goto _EXIT; + } + + psu1_status = psu_info.status; + if (psu1_status != pre_psu1_status) { + if((psu1_status & ONLP_PSU_STATUS_PRESENT) == 0) { + rc = onlp_ledi_mode_set(LED_OID_PSU1, ONLP_LED_MODE_OFF); + } + else if(psu1_status != ONLP_PSU_STATUS_PRESENT) { + rc = onlp_ledi_mode_set(LED_OID_PSU1, ONLP_LED_MODE_ORANGE); + } else { + rc = onlp_ledi_mode_set(LED_OID_PSU1, ONLP_LED_MODE_GREEN); + } + + if (rc != ONLP_STATUS_OK) { + goto _EXIT; + } + pre_psu1_status = psu1_status; + } + + if ((rc = onlp_psui_info_get(PSU_OID_PSU2, &psu_info)) != ONLP_STATUS_OK) { + goto _EXIT; + } + + psu2_status = psu_info.status; + if( psu2_status != pre_psu2_status) { + if((psu2_status & ONLP_PSU_STATUS_PRESENT) == 0) { + rc = onlp_ledi_mode_set(LED_OID_PSU2, ONLP_LED_MODE_OFF); + } + else if(psu2_status != ONLP_PSU_STATUS_PRESENT) { + rc = onlp_ledi_mode_set(LED_OID_PSU2, ONLP_LED_MODE_ORANGE); + } else { + rc = onlp_ledi_mode_set(LED_OID_PSU2, ONLP_LED_MODE_GREEN); + } + + if (rc != ONLP_STATUS_OK) { + goto _EXIT; + } + pre_psu2_status = psu2_status; + } + + /* FAN LED CTRL */ + for (i=0; i ONLP_LED_STATUS_FAILED) { + rc = onlp_ledi_mode_set(fan_tray_id, ONLP_LED_MODE_ORANGE); + } else { + rc = onlp_ledi_mode_set(fan_tray_id, ONLP_LED_MODE_GREEN); + } + + if (rc != ONLP_STATUS_OK) { + goto _EXIT; + } + + pre_fan_tray_status[fan_tray_id - 5] = sum; + } + } + + if (total != pre_fan_status) { + if (total == (ONLP_LED_STATUS_PRESENT * 4)) { + rc = onlp_ledi_mode_set(LED_OID_FAN, ONLP_LED_MODE_GREEN); + } else { + rc = onlp_ledi_mode_set(LED_OID_FAN, ONLP_LED_MODE_ORANGE); + } + + if (rc != ONLP_STATUS_OK) { + goto _EXIT; + } + + pre_fan_status = total; + } + +_EXIT : + return rc; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int rc; + if ((rc = sysi_platform_info_get(pi)) != ONLP_STATUS_OK) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/thermali.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/thermali.c new file mode 100755 index 00000000..b4b4a196 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/thermali.c @@ -0,0 +1,221 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include "x86_64_ingrasys_s9230_64x_log.h" +#include "platform_lib.h" + +static onlp_thermal_info_t thermal_info[] = { + { }, /* Not used */ + { { THERMAL_OID_CPU1, "CPU Thermal 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_CPU2, "CPU Thermal 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_CPU3, "CPU Thermal 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_CPU4, "CPU Thermal 4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_REAR_PANEL, "Rear Panel", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_REAR_MAC, "Rear MAC", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_FRONT_PANEL, "Front Panel", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_FRONT_MAC, "FRONT MAC", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { THERMAL_OID_BMC_BOARD, "BMC Board", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + }, + { { THERMAL_OID_CPU_BOARD, "CPU Board", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + }, + { { THERMAL_OID_PSU1_1, "PSU-1 Thermal 1", PSU_OID_PSU1}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + }, + { { THERMAL_OID_PSU1_2, "PSU-1 Thermal 2", PSU_OID_PSU1}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + }, + { { THERMAL_OID_PSU2_1, "PSU-2 Thermal 1", PSU_OID_PSU2}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + }, + { { THERMAL_OID_PSU2_2, "PSU-2 Thermal 2", PSU_OID_PSU2}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0 + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +lm_thermal_info_get(onlp_thermal_info_t* info, int id) +{ + int rv; + char sysfs_path[64]; + + switch (id) { + case THERMAL_ID_REAR_PANEL: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_REAR_PANEL_TEMP_PREFIX "temp%d_input", 1); + break; + case THERMAL_ID_REAR_MAC: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_REAR_MAC_TEMP_PREFIX "temp%d_input", 1); + break; + case THERMAL_ID_FRONT_PANEL: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_FRONT_PANEL_PREFIX "temp%d_input", 1); + break; + case THERMAL_ID_FRONT_MAC: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_FRONT_MAC_PREFIX "temp%d_input", 1); + break; + case THERMAL_ID_BMC_BOARD: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_BMC_BOARD_PREFIX "temp%d_input", 1); + break; + case THERMAL_ID_CPU_BOARD: + snprintf(sysfs_path, sizeof(sysfs_path), SYS_CPU_BOARD_PREFIX "temp%d_input", 1); + break; + } + + rv = onlp_file_read_int(&info->mcelsius, sysfs_path); + + if(rv == ONLP_STATUS_E_INTERNAL) { + return rv; + } + + if(rv == ONLP_STATUS_E_MISSING) { + info->status &= ~1; + return 0; + } + + return ONLP_STATUS_OK; +} + +static int +cpu_thermal_info_get(onlp_thermal_info_t* info, int id) +{ + int rv; + int offset; + + offset = 1; + id = id + offset; + rv = onlp_file_read_int(&info->mcelsius, + SYS_CPU_TEMP_PREFIX "temp%d_input", id); + + if(rv == ONLP_STATUS_E_INTERNAL) { + return rv; + } + + if(rv == ONLP_STATUS_E_MISSING) { + info->status &= ~1; + return 0; + } + + return ONLP_STATUS_OK; +} + +int +psu_thermal_info_get(onlp_thermal_info_t* info, int id) +{ + int rv; + + rv = psu_thermal_get(info, id); + if(rv == ONLP_STATUS_E_INTERNAL) { + return rv; + } + + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int sensor_id, rc; + sensor_id = ONLP_OID_ID_GET(id); + + *info = thermal_info[sensor_id]; + info->caps |= ONLP_THERMAL_CAPS_GET_TEMPERATURE; + + switch (sensor_id) { + case THERMAL_ID_CPU1: + case THERMAL_ID_CPU2: + case THERMAL_ID_CPU3: + case THERMAL_ID_CPU4: + rc = cpu_thermal_info_get(info, sensor_id); + break; + case THERMAL_ID_REAR_PANEL: + case THERMAL_ID_REAR_MAC: + case THERMAL_ID_FRONT_PANEL: + case THERMAL_ID_FRONT_MAC: + case THERMAL_ID_BMC_BOARD: + case THERMAL_ID_CPU_BOARD: + rc = lm_thermal_info_get(info, sensor_id); + break; + case THERMAL_ID_PSU1_1: + case THERMAL_ID_PSU1_2: + case THERMAL_ID_PSU2_1: + case THERMAL_ID_PSU2_2: + rc = psu_thermal_info_get(info, sensor_id); + break; + default: + return ONLP_STATUS_E_INTERNAL; + break; + } + return rc; +} diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_config.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_config.c new file mode 100755 index 00000000..5c6086e0 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_config.c @@ -0,0 +1,101 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +/* */ +#define __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(_x) __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(_x) +x86_64_ingrasys_s9230_64x_config_settings_t x86_64_ingrasys_s9230_64x_config_settings[] = +{ +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_LOGGING(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_STDLIB(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_INCLUDE_UCLI(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT + { __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME(X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT), __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE(X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT) }, +#else +{ X86_64_INGRAYSYS_S9230_64X_CONFIG_SFP_COUNT(__x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_ingrasys_s9230_64x_config_STRINGIFY_VALUE +#undef __x86_64_ingrasys_s9230_64x_config_STRINGIFY_NAME + +const char* +x86_64_ingrasys_s9230_64x_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_ingrasys_s9230_64x_config_settings[i].name; i++) { + if(strcmp(x86_64_ingrasys_s9230_64x_config_settings[i].name, setting)) { + return x86_64_ingrasys_s9230_64x_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_ingrasys_s9230_64x_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_ingrasys_s9230_64x_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_ingrasys_s9230_64x_config_settings[i].name, x86_64_ingrasys_s9230_64x_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_enums.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_enums.c new file mode 100755 index 00000000..1c21cea7 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_enums.c @@ -0,0 +1,30 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_int.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_int.h new file mode 100755 index 00000000..d89e5297 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_int.h @@ -0,0 +1,29 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#ifndef __x86_64_ingrasys_s9230_64x_INT_H__ +#define __x86_64_ingrasys_s9230_64x_INT_H__ + +#endif /* __x86_64_ingrasys_s9230_64x_INT_H__ */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.c new file mode 100755 index 00000000..77c97dc6 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.c @@ -0,0 +1,38 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +#include "x86_64_ingrasys_s9230_64x_log.h" +/* + * x86_64_ingrasys_s9230_64x log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_INGRAYSYS_S9230_64X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.h new file mode 100755 index 00000000..67815d0b --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_log.h @@ -0,0 +1,32 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#ifndef __x86_64_ingrasys_s9230_64x_LOG_H__ +#define __x86_64_ingrasys_s9230_64x_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_ingrasys_s9230_64x +#include + +#endif /* __x86_64_ingrasys_s9230_64x_LOG_H__ */ diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_module.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_module.c new file mode 100755 index 00000000..e5b420e7 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_module.c @@ -0,0 +1,44 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +#include "x86_64_ingrasys_s9230_64x_log.h" + +static int +datatypes_init__(void) +{ +#define INGRAYSYS_S9230_64X_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_ingrasys_s9230_64x_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_ucli.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_ucli.c new file mode 100755 index 00000000..af8fb88a --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/onlp/builds/src/x86_64_ingrasys_s9230_64x/module/src/x86_64_ingrasys_s9230_64x_ucli.c @@ -0,0 +1,82 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include + +#if ONLPSIM_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_ingrasys_s9230_64x_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_ingrasys_s9230_64x) +} + +/* */ +/****************************************************************************** + * + * These handler table(s) were autogenerated from the symbols in this + * source file. + * + *****************************************************************************/ +static ucli_command_handler_f x86_64_ingrasys_s9230_64x_ucli_ucli_handlers__[] = +{ + x86_64_ingrasys_s9230_64x_ucli_ucli__config__, + NULL +}; +/******************************************************************************/ +/* */ + +static ucli_module_t +x86_64_ingrasys_s9230_64x_ucli_module__ = + { + "x86_64_ingrasys_s9230_64x_ucli", + NULL, + x86_64_ingrasys_s9230_64x_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_ingrasys_s9230_64x_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_ingrasys_s9230_64x_ucli_module__); + n = ucli_node_create("x86_64_ingrasys_s9230_64x", NULL, &x86_64_ingrasys_s9230_64x_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_ingrasys_s9230_64x")); + return n; +} + +#else +void* +x86_64_ingrasys_s9230_64x_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/Makefile b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/PKG.yml b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/PKG.yml new file mode 100755 index 00000000..42dd7cc4 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=ingrasys BASENAME=x86-64-ingrasys-s9230-64x REVISION=r0 diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/lib/x86-64-ingrasys-s9230-64x-r0.yml b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/lib/x86-64-ingrasys-s9230-64x-r0.yml new file mode 100755 index 00000000..10749fc5 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/lib/x86-64-ingrasys-s9230-64x-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for x86-64-ingrasys-s9230-64x +# +###################################################################### + +x86-64-ingrasys-s9230-64x-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:03.0 diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/python/x86_64_ingrasys_s9230_64x_r0/__init__.py b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/python/x86_64_ingrasys_s9230_64x_r0/__init__.py new file mode 100755 index 00000000..92513cf5 --- /dev/null +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9230-64x/platform-config/r0/src/python/x86_64_ingrasys_s9230_64x_r0/__init__.py @@ -0,0 +1,198 @@ +from onl.platform.base import * +from onl.platform.ingrasys import * +import os + +class OnlPlatform_x86_64_ingrasys_s9230_64x_r0(OnlPlatformIngrasys): + PLATFORM='x86-64-ingrasys-s9230-64x-r0' + MODEL="S9230-64X" + SYS_OBJECT_ID=".9230.64" + + def baseconfig(self): + + # fp port to phy port mapping + fp2phy_array=( 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30, + 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62, + 3, 4, 7, 8, 11, 12, 15, 16, 19, 20, 23, 24, 27, 28, 31, 32, + 35, 36, 39, 40, 43, 44, 47, 48, 51, 52, 55, 56, 59, 60, 63, 64) + + self.insmod("eeprom_mb") + # init SYS EEPROM devices + self.new_i2c_devices( + [ + # _i2c_mb_eeprom_init + ('mb_eeprom', 0x55, 0), + + # _i2c_cb_eeprom_init + ('mb_eeprom', 0x51, 0), + ] + ) + + os.system("modprobe w83795") + os.system("modprobe eeprom") + + ########### initialize I2C bus 0 ########### + # init PCA9548 + self.new_i2c_devices( + [ + ('pca9548', 0x70, 0), #pca9548_0 + ('pca9548', 0x73, 0), #pca9548_1 + ('pca9546', 0x72, 0), #pca9546_0 + ('pca9546', 0x71, 20), #pca9546_1 + ('pca9548', 0x71, 19), #pca9548_2 + ('pca9548', 0x74, 25), #pca9548_3 + ('pca9548', 0x74, 26), #pca9548_4 + ('pca9548', 0x74, 27), #pca9548_5 + ('pca9548', 0x74, 28), #pca9548_6 + ('pca9548', 0x74, 29), #pca9548_7 + ('pca9548', 0x74, 30), #pca9548_8 + ('pca9548', 0x74, 31), #pca9548_9 + ('pca9548', 0x74, 32), #pca9548_10 + ] + ) + # _i2c_hwm_init + os.system("i2cset -y -r 16 0x2f 0x00 0x80") + os.system("i2cset -y -r 16 0x2f 0x01 0x9C") + os.system("i2cset -y -r 16 0x2f 0x04 0x00") + os.system("i2cset -y -r 16 0x2f 0x06 0xFF") + os.system("i2cset -y -r 16 0x2f 0x07 0x00") + os.system("i2cset -y -r 16 0x2f 0x01 0x1C") + os.system("i2cset -y -r 16 0x2f 0x00 0x82") + os.system("i2cset -y -r 16 0x2f 0x0F 0x00") + os.system("i2cset -y -r 16 0x2f 0x18 0x84") + os.system("i2cset -y -r 16 0x2f 0x19 0x84") + + # _i2c_io_exp_init + # need to init BMC io expander first due to some io expander are reset default + # Init BMC INT & HW ID IO Expander + os.system("i2cset -y -r 0 0x24 6 0xFF") + os.system("i2cset -y -r 0 0x24 7 0xFF") + os.system("i2cset -y -r 0 0x24 4 0x00") + os.system("i2cset -y -r 0 0x24 5 0x00") + + # Init BMC PSU status IO Expander + os.system("i2cset -y -r 0 0x25 2 0x00") + os.system("i2cset -y -r 0 0x25 3 0x00") + os.system("i2cset -y -r 0 0x25 6 0xDB") + os.system("i2cset -y -r 0 0x25 7 0xE3") + os.system("i2cset -y -r 0 0x25 4 0x00") + os.system("i2cset -y -r 0 0x25 5 0x00") + + # Init BMC RST and SEL IO Expander + os.system("i2cset -y -r 0 0x26 2 0x3F") + os.system("i2cset -y -r 0 0x26 3 0x1F") + os.system("i2cset -y -r 0 0x26 6 0xC0") + os.system("i2cset -y -r 0 0x26 7 0x00") + os.system("i2cset -y -r 0 0x26 4 0x00") + os.system("i2cset -y -r 0 0x26 5 0x00") + + # Init System LED & HW ID IO Expander + os.system("i2cset -y -r 10 0x76 2 0x00") + os.system("i2cset -y -r 10 0x76 6 0x00") + os.system("i2cset -y -r 10 0x76 7 0xFF") + os.system("i2cset -y -r 10 0x76 4 0x00") + os.system("i2cset -y -r 10 0x76 5 0x00") + + # Init FAN Board Status IO Expander + os.system("i2cset -y -r 0 0x20 2 0x11") + os.system("i2cset -y -r 0 0x20 3 0x11") + os.system("i2cset -y -r 0 0x20 6 0xCC") + os.system("i2cset -y -r 0 0x20 7 0xCC") + os.system("i2cset -y -r 0 0x20 4 0x00") + os.system("i2cset -y -r 0 0x20 5 0x00") + + # Init System SEL and RST IO Expander + os.system("i2cset -y -r 11 0x76 2 0x0F") + os.system("i2cset -y -r 11 0x76 3 0xDF") + os.system("i2cset -y -r 11 0x76 6 0x09") + os.system("i2cset -y -r 11 0x76 7 0x1F") + os.system("i2cset -y -r 11 0x76 4 0x00") + os.system("i2cset -y -r 11 0x76 5 0x00") + + # Init CPU CPLD IO Expander + os.system("i2cset -y -r 0 0x77 6 0xFF") + os.system("i2cset -y -r 0 0x77 7 0xFF") + os.system("i2cset -y -r 0 0x77 4 0x00") + os.system("i2cset -y -r 0 0x77 5 0x00") + + # _i2c_sensors_init + + self.new_i2c_devices( + [ + # lm75_1 Rear Panel, hwmon1 + ('lm75', 0x4D, 6), + + # lm75_2 Rear MAC, hwmon2 + ('lm75', 0x4E, 6), + + # lm75_3 Front Panel, hwmon3 + ('lm75', 0x4D, 7), + + # lm75_4 Front MAC, hwmon4 + ('lm75', 0x4E, 7), + + # tmp75 BMC board thermal, hwmon5 + ('tmp75', 0x4A, 16), + + # tmp75 CPU board thermal, hwmon6 + ('tmp75', 0x4F, 0), + + # w83795, hwmon7 + ('w83795adg', 0x2F, 16), + + ] + ) + + # _i2c_cpld_init + self.insmod("ingrasys_s9230_64x_i2c_cpld") + + # add cpld 1~5 to sysfs + for i in range(1, 6): + self.new_i2c_device('ingrasys_cpld%d' % i, 0x33, i) + + # _i2c_psu_init + + self.insmod("ingrasys_s9230_64x_psu") + + # add psu 1~2 to sysfs + for i in range(1, 3): + self.new_i2c_device('psu%d' % i, 0x50, 19-i) + + # _i2c_qsfp_eeprom_init + for i in range(1, 65): + phy_port = fp2phy_array[i-1] + port_group = (phy_port-1)/8 + eeprom_busbase = 33 + (port_group * 8) + eeprom_busshift = (phy_port-1)%8 + eeprom_bus = eeprom_busbase + eeprom_busshift + self.new_i2c_device('sff8436', 0x50, eeprom_bus) + + # _i2c_sfp_eeprom_init + for i in range(1, 3): + self.new_i2c_device('sff8436', 0x50, 20+i) + + # _i2c_fan_speed_init + os.system("echo 120 > /sys/class/hwmon/hwmon7/device/pwm2") + + # set 10gmux to cpu + os.system("i2cset -m 0xff -y -r 13 0x67 0x06 0x18") + os.system("i2cset -m 0xff -y -r 13 0x67 0x2c 0x00") + os.system("i2cset -m 0xff -y -r 13 0x67 0x35 0x80") + os.system("i2cset -m 0xff -y -r 13 0x67 0x34 0xab") + os.system("i2cset -m 0xff -y -r 13 0x67 0x16 0x01") + os.system("i2cset -m 0xff -y -r 13 0x67 0x18 0x80") + os.system("i2cset -m 0xff -y -r 13 0x67 0x17 0xab") + os.system("i2cset -m 0xff -y -r 13 0x67 0x3a 0x00") + os.system("i2cset -m 0xff -y -r 13 0x67 0x41 0x00") + os.system("i2cset -m 0xff -y -r 13 0x67 0x43 0x80") + os.system("i2cset -m 0xff -y -r 13 0x67 0x42 0xab") + os.system("i2cset -m 0xff -y -r 13 0x67 0x24 0x01") + os.system("i2cset -m 0xff -y -r 13 0x67 0x26 0x80") + os.system("i2cset -m 0xff -y -r 13 0x67 0x25 0xab") + os.system("echo 0xf3 > /sys/class/i2c-dev/i2c-1/device/1-0033/cpld_10gmux_config") + + # turn on sys led + os.system("i2cset -m 0x80 -y -r 10 0x76 2 0x80") + + return True + + diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.c index 588e9473..5a487c5b 100644 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.c +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.c @@ -112,6 +112,7 @@ enum LED_GREEN { #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 { @@ -453,6 +454,7 @@ enum s9280_64x_cpld_sysfs_attributes { CPLD_QSFP_LED_16, CPLD_QSFP_LED_BLINK, CPLD_RTMR_RESET, + CPLD_ROV_STATUS, }; @@ -527,6 +529,8 @@ 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 */ @@ -695,6 +699,8 @@ 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 */ @@ -742,6 +748,7 @@ static struct attribute *s9280_64x_cpld1_attributes[] = { &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 }; @@ -1576,6 +1583,27 @@ static ssize_t write_rtmr_reset(struct device *dev, 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) { diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.h index 08db7138..c118f0a7 100644 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.h +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/modules/builds/ingrasys_s9280_64x_i2c_cpld.h @@ -79,6 +79,7 @@ enum LED_GREEN { #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 { diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/platform_lib.h b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/platform_lib.h index ed129e09..cc61a924 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/platform_lib.h +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/platform_lib.h @@ -47,6 +47,7 @@ #define SYS_PSU1_PREFIX "/sys/bus/i2c/devices/i2c-18/18-0050/" #define SYS_PSU2_PREFIX "/sys/bus/i2c/devices/i2c-17/17-0050/" #define SYS_EEPROM_PATH "/sys/bus/i2c/devices/0-0051/eeprom" +#define SYS_EEPROM_SIZE 512 #define PSU1_EEPROM_PATH "/sys/bus/i2c/devices/18-0050/psu_eeprom" #define PSU2_EEPROM_PATH "/sys/bus/i2c/devices/17-0050/psu_eeprom" #define PSU_STATUS_PRESENT 1 diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/sysi.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/sysi.c index 0cd67513..a3ed3790 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/sysi.c +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/sysi.c @@ -51,9 +51,9 @@ onlp_sysi_init(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { - uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, SYS_EEPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { + uint8_t* rdata = aim_zmalloc(SYS_EEPROM_SIZE); + if(onlp_file_read(rdata, SYS_EEPROM_SIZE, size, SYS_EEPROM_PATH) == ONLP_STATUS_OK) { + if(*size == SYS_EEPROM_SIZE) { *data = rdata; return ONLP_STATUS_OK; } diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/x86_64_ingrasys_s9280_64x_module.c b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/x86_64_ingrasys_s9280_64x_module.c index f5f9b814..33b294f2 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/x86_64_ingrasys_s9280_64x_module.c +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/onlp/builds/src/x86_64_ingrasys_s9280_64x/module/src/x86_64_ingrasys_s9280_64x_module.c @@ -30,7 +30,7 @@ static int datatypes_init__(void) { -#define INGRAYSYS_S9180_32X_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#define INGRAYSYS_S9280_64X_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); #include return 0; } diff --git a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/platform-config/r0/src/python/x86_64_ingrasys_s9280_64x_r0/__init__.py b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/platform-config/r0/src/python/x86_64_ingrasys_s9280_64x_r0/__init__.py index 345fcbbd..6451e192 100755 --- a/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/platform-config/r0/src/python/x86_64_ingrasys_s9280_64x_r0/__init__.py +++ b/packages/platforms/ingrasys/x86-64/x86-64-ingrasys-s9280-64x/platform-config/r0/src/python/x86_64_ingrasys_s9280_64x_r0/__init__.py @@ -1,6 +1,13 @@ from onl.platform.base import * from onl.platform.ingrasys import * import os +import sys + +def msg(s, fatal=False): + sys.stderr.write(s) + sys.stderr.flush() + if fatal: + sys.exit(1) class OnlPlatform_x86_64_ingrasys_s9280_64x_r0(OnlPlatformIngrasys): PLATFORM='x86-64-ingrasys-s9280-64x-r0' @@ -20,6 +27,11 @@ class OnlPlatform_x86_64_ingrasys_s9280_64x_r0(OnlPlatformIngrasys): 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) + # vid to mac vdd value mapping + vdd_val_array=( 0.85, 0.82, 0.77, 0.87, 0.74, 0.84, 0.79, 0.89 ) + # vid to rov reg value mapping + rov_reg_array=( 0x79, 0x73, 0x69, 0x7D, 0x63, 0x77, 0x6D, 0x81 ) + self.insmod("eeprom_mb") # init SYS EEPROM devices self.new_i2c_devices( @@ -176,6 +188,19 @@ class OnlPlatform_x86_64_ingrasys_s9280_64x_r0(OnlPlatformIngrasys): for i in range(1, 3): self.new_i2c_device('sff8436', 0x50, 28+i) + # _mac_vdd_init + rov_status_file = open("/sys/bus/i2c/devices/1-0033/cpld_rov_status", "r") + reg_val_str = rov_status_file.read() + rov_status_file.close() + + reg_val = int(reg_val_str, 16) + vid = reg_val & 0x7 + mac_vdd_val = vdd_val_array[vid] + rov_reg = rov_reg_array[vid] + + msg("Setting mac vdd %1.2f with rov register value 0x%x\n" % (mac_vdd_val, rov_reg) ) + os.system("i2cset -y -r 15 0x76 0x21 0x%x w" % rov_reg) + # _i2c_fan_speed_init os.system("echo 120 > /sys/class/hwmon/hwmon1/device/pwm2") diff --git a/packages/platforms/inventec/x86-64/modules/PKG.yml b/packages/platforms/inventec/x86-64/modules/PKG.yml index 3690f5a9..ac147153 100644 --- a/packages/platforms/inventec/x86-64/modules/PKG.yml +++ b/packages/platforms/inventec/x86-64/modules/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/no-arch-vendor-modules.yml ARCH=amd64 VENDOR=inventec +!include $ONL_TEMPLATES/arch-vendor-modules.yml ARCH=amd64 VENDOR=inventec KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/modules/builds/.gitignore b/packages/platforms/inventec/x86-64/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/inventec/x86-64/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/inventec/x86-64/modules/builds/Makefile b/packages/platforms/inventec/x86-64/modules/builds/Makefile new file mode 100644 index 00000000..ef8762fd --- /dev/null +++ b/packages/platforms/inventec/x86-64/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := inventec +BASENAME := common +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/modules/builds/src/Makefile new file mode 100644 index 00000000..63b9ea34 --- /dev/null +++ b/packages/platforms/inventec/x86-64/modules/builds/src/Makefile @@ -0,0 +1 @@ +obj-m += inv_eeprom.o diff --git a/packages/platforms/inventec/x86-64/modules/builds/src/inv_eeprom.c b/packages/platforms/inventec/x86-64/modules/builds/src/inv_eeprom.c new file mode 100644 index 00000000..f03c3cb1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/modules/builds/src/inv_eeprom.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x53, 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 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, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int inv_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 != 0x53) { + 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 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, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = inv_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec Switch Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/PKG.yml new file mode 100644 index 00000000..894973ab --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d5254 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/Makefile new file mode 100644 index 00000000..6fc93144 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := inventec +BASENAME := x86-64-inventec-d5254 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/Makefile new file mode 100644 index 00000000..7f1c699e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/Makefile @@ -0,0 +1,11 @@ +obj-m += gpio-ich.o +obj-m += i2c-gpio.o +obj-m += inv_cpld.o +obj-m += inv_mux.o +obj-m += inv_platform.o +obj-m += inv_psoc.o +obj-m += inv_swps.o +obj-m += inv_vpd.o +obj-m += io_expander.o +obj-m += onie_tlvinfo.o +obj-m += transceiver.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/gpio-ich.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/gpio-ich.c new file mode 100644 index 00000000..70304220 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/gpio-ich.c @@ -0,0 +1,548 @@ +/* + * 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 +#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))); +} + +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; + chip->dev = &ichx_priv.dev->dev; + + /* 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, +}; + +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; + 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; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/i2c-gpio.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/i2c-gpio.c new file mode 100644 index 00000000..34cfc0eb --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/i2c-gpio.c @@ -0,0 +1,290 @@ +/* + * Bitbanging I2C bus driver using the GPIO API + * + * Copyright (C) 2007 Atmel Corporation + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; + +/* Toggle SDA by changing the direction of the pin */ +static void i2c_gpio_setsda_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->sda_pin); + else + gpio_direction_output(pdata->sda_pin, 0); +} + +/* + * Toggle SDA by changing the output value of the pin. This is only + * valid for pins configured as open drain (i.e. setting the value + * high effectively turns off the output driver.) + */ +static void i2c_gpio_setsda_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->sda_pin, state); +} + +/* Toggle SCL by changing the direction of the pin. */ +static void i2c_gpio_setscl_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->scl_pin); + else + gpio_direction_output(pdata->scl_pin, 0); +} + +/* + * Toggle SCL by changing the output value of the pin. This is used + * for pins that are configured as open drain and for output-only + * pins. The latter case will break the i2c protocol, but it will + * often work in practice. + */ +static void i2c_gpio_setscl_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->scl_pin, state); +} + +static int i2c_gpio_getsda(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->sda_pin); +} + +static int i2c_gpio_getscl(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->scl_pin); +} + +static int of_i2c_gpio_get_pins(struct device_node *np, + unsigned int *sda_pin, unsigned int *scl_pin) +{ + if (of_gpio_count(np) < 2) + return -ENODEV; + + *sda_pin = of_get_gpio(np, 0); + *scl_pin = of_get_gpio(np, 1); + + if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, *sda_pin, *scl_pin); + return -ENODEV; + } + + return 0; +} + +static void of_i2c_gpio_get_props(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); +} + +static int i2c_gpio_probe(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_gpio_platform_data *pdata; + struct i2c_algo_bit_data *bit_data; + struct i2c_adapter *adap; + unsigned int sda_pin, scl_pin; + int ret; + + /* First get the GPIO pins; if it fails, we'll defer the probe. */ + if (pdev->dev.of_node) { + ret = of_i2c_gpio_get_pins(pdev->dev.of_node, + &sda_pin, &scl_pin); + if (ret) + return ret; + } else { + if (!dev_get_platdata(&pdev->dev)) + return -ENXIO; + pdata = dev_get_platdata(&pdev->dev); + sda_pin = pdata->sda_pin; + scl_pin = pdata->scl_pin; + } + + ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + pdata->sda_pin = sda_pin; + pdata->scl_pin = scl_pin; + of_i2c_gpio_get_props(pdev->dev.of_node, pdata); + } else { + memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); + } + + if (pdata->sda_is_open_drain) { + gpio_direction_output(pdata->sda_pin, 1); + bit_data->setsda = i2c_gpio_setsda_val; + } else { + gpio_direction_input(pdata->sda_pin); + bit_data->setsda = i2c_gpio_setsda_dir; + } + + if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { + gpio_direction_output(pdata->scl_pin, 1); + bit_data->setscl = i2c_gpio_setscl_val; + } else { + gpio_direction_input(pdata->scl_pin); + bit_data->setscl = i2c_gpio_setscl_dir; + } + + if (!pdata->scl_is_output_only) + bit_data->getscl = i2c_gpio_getscl; + bit_data->getsda = i2c_gpio_getsda; + + if (pdata->udelay) + bit_data->udelay = pdata->udelay; + else if (pdata->scl_is_output_only) + bit_data->udelay = 50; /* 10 kHz */ + else + bit_data->udelay = 5; /* 100 kHz */ + + if (pdata->timeout) + bit_data->timeout = pdata->timeout; + else + bit_data->timeout = HZ / 10; /* 100 ms */ + + bit_data->data = pdata; + + adap->owner = THIS_MODULE; + if (pdev->dev.of_node) + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + else + snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); + + adap->algo_data = bit_data; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + adap->nr = pdev->id; + ret = i2c_bit_add_numbered_bus(adap); + if (ret) + return ret; + + platform_set_drvdata(pdev, priv); + + dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", + pdata->sda_pin, pdata->scl_pin, + pdata->scl_is_output_only + ? ", no clock stretching" : ""); + + return 0; +} + +static int i2c_gpio_remove(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_adapter *adap; + + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + + i2c_del_adapter(adap); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + +static struct platform_driver i2c_gpio_driver = { + .driver = { + .name = "i2c-gpio", + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), + }, + .probe = i2c_gpio_probe, + .remove = i2c_gpio_remove, +}; + +static int __init i2c_gpio_init(void) +{ + int ret; + + ret = platform_driver_register(&i2c_gpio_driver); + if (ret) + printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); + + return ret; +} +subsys_initcall(i2c_gpio_init); + +static void __exit i2c_gpio_exit(void) +{ + platform_driver_unregister(&i2c_gpio_driver); +} +module_exit(i2c_gpio_exit); + +MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); +MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:i2c-gpio"); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_cpld.c new file mode 100644 index 00000000..57791f62 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_cpld.c @@ -0,0 +1,463 @@ +/* + * This program is free software; you can 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 + "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 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, +}; + +/*-----------------------------------------------------------------------*/ + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..482a8cb1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.c @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +/* For build single module using (Ex: ONL platform) */ +#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__); +} +EXPORT_SYMBOL(clean_mux_gpio); + + +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; +} +EXPORT_SYMBOL(reset_mux_gpio); + + +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; +} +EXPORT_SYMBOL(init_mux_gpio); + +/* For single ko module + * => You need to declare MODULE_LICENSE If you want to build single module along. + * => Ex: For ONL platform + */ +MODULE_LICENSE("GPL"); + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..f316de4c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_mux.h @@ -0,0 +1,41 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_platform.c new file mode 100644 index 00000000..b3650b15 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_platform.c @@ -0,0 +1,219 @@ +#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),}, +}; + +//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, 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 = 494, //494,//58, + .sda_pin = 511, //511,//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, +}; + +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__); + + //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); + } + + 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 5 +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..70bc8c78 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.c @@ -0,0 +1,3045 @@ +#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_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: + case PLATFORM_TYPE_GULMOHAR_GA: + 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_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 +#ifdef SWPS_GULMOHAR + case PLATFORM_TYPE_GULMOHAR_GA: + gpio_rest_mux = gulmohar_gpio_rest_mux; + ioexp_layout = gulmohar_ioexp_layout; + port_layout = gulmohar_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_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: + case IOEXP_TYPE_GULMOHAR_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: + case IOEXP_TYPE_GULMOHAR_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_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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..55b46076 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_swps.h @@ -0,0 +1,1161 @@ +#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.10" +#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_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) +#define PLATFORM_TYPE_GULMOHAR_GA (202) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_GULMOHAR_GA + +/* 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_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) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_GA) + #define SWPS_GULMOHAR (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_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" }, + {PLATFORM_TYPE_GULMOHAR_GA, "Gulmohar_GA" }, +}; + + +/* ========================================== + * 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 + + +/* ========================================== + * 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, CHIP_TYPE_D5254, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 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 = MUX_RST_GPIO_505_PCA9548; + +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 + + +/* ========================================== + * Gulmohar Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR +unsigned gulmohar_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* 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_GULMOHAR_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_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, CHIP_TYPE_D5254, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_D5254, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5254, {109,110,111,112} }, +}; +#endif + + +#endif /* INV_SWPS_H */ + + + + + + + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..b6d755e1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +static int +__swp_match(struct device *dev, +#ifdef VPD_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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..58c7fe33 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/inv_vpd.h @@ -0,0 +1,46 @@ +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_ENTRY_SIZE (17) +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.c new file mode 100644 index 00000000..792896d4 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.c @@ -0,0 +1,2165 @@ +#include +#include +/* For build single module using (Ex: ONL platform) */ +#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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_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, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* 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, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* 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, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* 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, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* 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, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* 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, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* 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_gulmohar_7abc = { + + .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) */ + }, + .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) */ + }, + .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) */ + }, + .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) */ + }, +}; + + +/* ========== 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; + case IOEXP_TYPE_GULMOHAR_NABC: + return &ioexp_map_gulmohar_nabc; + case IOEXP_TYPE_GULMOHAR_7ABC: + return &ioexp_map_gulmohar_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_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: + case IOEXP_TYPE_GULMOHAR_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: + case IOEXP_TYPE_GULMOHAR_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->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: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + 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; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +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; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +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__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +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; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + +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; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +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; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.h new file mode 100644 index 00000000..2f241d03 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/io_expander.h @@ -0,0 +1,183 @@ +#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) +#define IOEXP_TYPE_GULMOHAR_NABC (10105) + +/* 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) +#define IOEXP_TYPE_GULMOHAR_7ABC (10213) + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..303ffde7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,820 @@ +#include +#include +#include +#include +//#include +#include + +//#include +//#include +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +#if 0 +static unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} +#else +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} +#endif + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %d\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %d\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} +EXPORT_SYMBOL(read_eeprom); + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} +EXPORT_SYMBOL(prog_eeprom); + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} +EXPORT_SYMBOL(tlvinfo_decode_tlv); + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} +EXPORT_SYMBOL(tlvinfo_delete_tlv); + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} +EXPORT_SYMBOL(tlvinfo_add_tlv); + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} +#if 0 +int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf) +{ + int tlv_end; + int curr_tlv; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int iFind = 0; + + if( !is_valid_tlvinfo_header(eeprom_hdr) ) { + printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n"); + return -1; + } + + curr_tlv = sizeof(tlvinfo_header_t); + tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while(curr_tlv < tlv_end){ + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv]; + if (!is_valid_tlv(eeprom_tlv)) { + printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n", + curr_tlv); + return -1; + } + + decode_tlv_value(eeprom_tlv, c_buf); + if( eeprom_tlv->type == i_offset){ + iFind = 1; + break; + } + curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + if( iFind == 0 ) + return -1; + else + return 0; +} +#endif diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..74f3c960 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); +//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.c new file mode 100644 index 00000000..57abf132 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.c @@ -0,0 +1,8393 @@ +#include +#include +#include +#include +/* For build single module using (Ex: ONL platform) */ +#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); +} +EXPORT_SYMBOL(alarm_msg_2_user); + +/* ========== 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; +} +EXPORT_SYMBOL(lock_transvr_obj); + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + + +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_d5254_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to d5254 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 CHIP_TYPE_D5254: + return _sfp_set_d5254_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_d5254_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to d5254 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 CHIP_TYPE_D5254: + return _qsfp_set_d5254_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; +} +EXPORT_SYMBOL(create_transvr_obj); + + +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; +} +EXPORT_SYMBOL(isolate_transvr_obj); + + +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; +} +EXPORT_SYMBOL(resync_channel_tier_2); + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + +/* ----------------------------------------- + * 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.h new file mode 100644 index 00000000..df35c3fc --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/modules/builds/src/transceiver.h @@ -0,0 +1,809 @@ +#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 CHIP_TYPE_D5254 (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/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/PKG.yml new file mode 100644 index 00000000..28b62020 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d5254 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/lib/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/lib/.gitignore similarity index 100% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/lib/.gitignore rename to packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/lib/.gitignore diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/lib/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/lib/Makefile new file mode 100644 index 00000000..4ad633a3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-inventec-d5254 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_inventec_d5254 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-inventec-d5254.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/onlpdump/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/onlpdump/.gitignore similarity index 100% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/onlpdump/.gitignore rename to packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/onlpdump/.gitignore diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/onlpdump/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..0f252b11 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_inventec_d5254 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/.gitignore similarity index 100% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/.gitignore rename to packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/.gitignore diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/.module b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/.module new file mode 100644 index 00000000..1a270897 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_inventec_d5254 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/Makefile new file mode 100644 index 00000000..52dce600 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_inventec_d5254 +AUTOMODULE := x86_64_inventec_d5254 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..61b30fb7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_inventec_d5254 Autogeneration +# +############################################################################### +x86_64_inventec_d5254_AUTO_DEFS := module/auto/x86_64_inventec_d5254.yml +x86_64_inventec_d5254_AUTO_DIRS := module/inc/x86_64_inventec_d5254 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/x86_64_inventec_d5254.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/x86_64_inventec_d5254.yml new file mode 100644 index 00000000..7d8bcc54 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/auto/x86_64_inventec_d5254.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_inventec_d5254 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_inventec_d5254_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_inventec_d5254_CONFIG_PORTING_STDLIB +- x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_inventec_d5254_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_inventec_d5254_config + + portingmacro: + x86_64_inventec_d5254: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254.x b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254.x new file mode 100644 index 00000000..830f6b31 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_config.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_config.h new file mode 100644 index 00000000..a1d81794 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d5254 Configuration Header + * + * @addtogroup x86_64_inventec_d5254-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5254_CONFIG_H__ +#define __x86_64_inventec_d5254_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_inventec_d5254_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING +#define x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT +#define x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_inventec_d5254_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_PORTING_STDLIB +#define x86_64_inventec_d5254_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d5254_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI +#define x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_inventec_d5254_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_inventec_d5254_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_inventec_d5254_config_settings table. */ +extern x86_64_inventec_d5254_config_settings_t x86_64_inventec_d5254_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_inventec_d5254_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_inventec_d5254_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_inventec_d5254_porting.h" + +#endif /* __x86_64_inventec_d5254_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_dox.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_dox.h new file mode 100644 index 00000000..c9828536 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_inventec_d5254 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5254_DOX_H__ +#define __x86_64_inventec_d5254_DOX_H__ + +/** + * @defgroup x86_64_inventec_d5254 x86_64_inventec_d5254 - x86_64_inventec_d5254 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_inventec_d5254-x86_64_inventec_d5254 Public Interface + * @defgroup x86_64_inventec_d5254-config Compile Time Configuration + * @defgroup x86_64_inventec_d5254-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_inventec_d5254_DOX_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_porting.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_porting.h new file mode 100644 index 00000000..ad6146b7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/inc/x86_64_inventec_d5254/x86_64_inventec_d5254_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d5254 Porting Macros. + * + * @addtogroup x86_64_inventec_d5254-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5254_PORTING_H__ +#define __x86_64_inventec_d5254_PORTING_H__ + + +/* */ +#if x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_inventec_d5254_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_inventec_d5254_MALLOC GLOBAL_MALLOC + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_MALLOC malloc + #else + #error The macro x86_64_inventec_d5254_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_FREE + #if defined(GLOBAL_FREE) + #define x86_64_inventec_d5254_FREE GLOBAL_FREE + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_FREE free + #else + #error The macro x86_64_inventec_d5254_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_inventec_d5254_MEMSET GLOBAL_MEMSET + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_MEMSET memset + #else + #error The macro x86_64_inventec_d5254_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_inventec_d5254_MEMCPY GLOBAL_MEMCPY + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_MEMCPY memcpy + #else + #error The macro x86_64_inventec_d5254_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_inventec_d5254_STRNCPY GLOBAL_STRNCPY + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_STRNCPY strncpy + #else + #error The macro x86_64_inventec_d5254_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_inventec_d5254_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_VSNPRINTF vsnprintf + #else + #error The macro x86_64_inventec_d5254_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_inventec_d5254_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_SNPRINTF snprintf + #else + #error The macro x86_64_inventec_d5254_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5254_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_inventec_d5254_STRLEN GLOBAL_STRLEN + #elif x86_64_inventec_d5254_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5254_STRLEN strlen + #else + #error The macro x86_64_inventec_d5254_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_inventec_d5254_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..dd211f97 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_inventec_d5254_INCLUDES := -I $(THIS_DIR)inc +x86_64_inventec_d5254_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_inventec_d5254_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d5254 ucli:x86_64_inventec_d5254 + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..5096c739 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_inventec_d5254_ucli.c + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/debug.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..9664a4fe --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_inventec_d5254_int.h" + +#if x86_64_inventec_d5254_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_inventec_d5254_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..e2b1c221 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/fani.c @@ -0,0 +1,368 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + + + +typedef struct fani_info_s { + int slow_pwm; + int normal_pwm; + int max_pwm; + int step_size; + char input_file[ONLP_CONFIG_INFO_STR_MAX]; + char pwm_file[ONLP_CONFIG_INFO_STR_MAX]; +} fani_info_t; + + +static fani_info_t __info_list[ONLP_FAN_COUNT] = { + {}, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan1_input", + "/sys/class/hwmon/hwmon1/device/pwm1" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan3_input", + "/sys/class/hwmon/hwmon1/device/pwm2" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan5_input", + "/sys/class/hwmon/hwmon1/device/pwm3" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan7_input", + "/sys/class/hwmon/hwmon1/device/pwm4" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan9_input", + "/sys/class/hwmon/hwmon1/device/pwm5" /*sync with pwm1*/ + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan2_input", + "/sys/class/hwmon/hwmon1/device/pwm1" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan4_input", + "/sys/class/hwmon/hwmon1/device/pwm2" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan6_input", + "/sys/class/hwmon/hwmon1/device/pwm3" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan8_input", + "/sys/class/hwmon/hwmon1/device/pwm4" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/fan10_input", + "/sys/class/hwmon/hwmon1/device/pwm5" /*sync with pwm1*/ + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/rpm_psu1", + "/sys/class/hwmon/hwmon1/device/pwm_psu1" + }, + { + 100,175,255,100, + "/sys/class/hwmon/hwmon1/device/rpm_psu2", + "/sys/class/hwmon/hwmon1/device/pwm_psu2" + } +}; + +/* Static values */ +static onlp_fan_info_t __onlp_fan_info[ONLP_FAN_COUNT] = { + { }, /* Not used */ + { { + ONLP_FAN_ID_CREATE(ONLP_FAN_1), "Fan 1", 0, + { + ONLP_FAN_ID_CREATE(ONLP_FAN_1_WEAK), + ONLP_LED_ID_CREATE(ONLP_LED_FAN1_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_FAN1_RED) + } + }, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { + ONLP_FAN_ID_CREATE(ONLP_FAN_2), "Fan 2", 0, + { + ONLP_FAN_ID_CREATE(ONLP_FAN_2_WEAK), + ONLP_LED_ID_CREATE(ONLP_LED_FAN2_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_FAN2_RED) + } + }, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { + ONLP_FAN_ID_CREATE(ONLP_FAN_3), "Fan 3", 0, + { + ONLP_FAN_ID_CREATE(ONLP_FAN_3_WEAK), + ONLP_LED_ID_CREATE(ONLP_LED_FAN3_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_FAN3_RED) + } + }, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { + ONLP_FAN_ID_CREATE(ONLP_FAN_4), "Fan 4", 0, + { + ONLP_FAN_ID_CREATE(ONLP_FAN_4_WEAK), + ONLP_LED_ID_CREATE(ONLP_LED_FAN4_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_FAN4_RED) + } + }, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { + ONLP_FAN_ID_CREATE(ONLP_FAN_5), "Fan 5", 0, + { + ONLP_FAN_ID_CREATE(ONLP_FAN_5_WEAK), + ONLP_LED_ID_CREATE(ONLP_LED_FAN5_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_FAN5_RED) + } + }, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_1_WEAK), "Fan 1 WEAK", ONLP_FAN_ID_CREATE(ONLP_FAN_1)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + + { { ONLP_FAN_ID_CREATE(ONLP_FAN_2_WEAK), "Fan 2 WEAK", ONLP_FAN_ID_CREATE(ONLP_FAN_2)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_3_WEAK), "Fan 3 WEAK", ONLP_FAN_ID_CREATE(ONLP_FAN_3)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_4_WEAK), "Fan 4 WEAK", ONLP_FAN_ID_CREATE(ONLP_FAN_4)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_5_WEAK), "Fan 5 WEAK", ONLP_FAN_ID_CREATE(ONLP_FAN_5)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_1), "PSU-1 Fan", ONLP_PSU_ID_CREATE(ONLP_PSU_1)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + }, + { { ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_2), "PSU-2 Fan", ONLP_PSU_ID_CREATE(ONLP_PSU_2)}, + ONLP_FAN_STATUS_PRESENT|ONLP_FAN_STATUS_F2B, + ONLP_FAN_CAPS_F2B|ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + } +}; + + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rv = ONLP_STATUS_OK; + int local_id; + int pwm; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + rv = ONLP_STATUS_E_INVALID; + } + + if( ONLP_STATUS_OK == rv) { + *info = __onlp_fan_info[local_id]; + rv = onlp_file_read_int(&info->rpm, __info_list[local_id].input_file); + } + + if(ONLP_STATUS_OK == rv) { + rv = onlp_file_read_int(&pwm, __info_list[local_id].pwm_file); + } + + if( ONLP_STATUS_OK == rv) { + if(0 == info->rpm) { + info->mode = ONLP_FAN_MODE_OFF; + } else if(pwm < __info_list[local_id].slow_pwm) { + info->mode = ONLP_FAN_MODE_SLOW; + } else if(pwm < __info_list[local_id].normal_pwm) { + info->mode = ONLP_FAN_MODE_NORMAL; + } else if(pwm < __info_list[local_id].max_pwm) { + info->mode = ONLP_FAN_MODE_FAST; + } else { + info->mode = ONLP_FAN_MODE_MAX; + } + + info->percentage = (pwm*100)/__info_list[local_id].max_pwm; + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + } + return rv; +} + +/** + * @brief Retrieve the fan's operational status. + * @param id The fan OID. + * @param rv [out] Receives the fan's operations status flags. + * @notes Only operational state needs to be returned - + * PRESENT/FAILED + */ +int onlp_fani_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_fan_info_t* info; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_fan_info[local_id]; + *rv = info->status; + } + return result; +} + +/** + * @brief Retrieve the fan's OID hdr. + * @param id The fan OID. + * @param rv [out] Receives the OID header. + */ +int onlp_fani_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* hdr) +{ + int result = ONLP_STATUS_OK; + onlp_fan_info_t* info; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_fan_info[local_id]; + *hdr = info->hdr; + } + return result; +} + + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..4781ca37 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,549 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ + +/* CAPS*/ +#define CPLD_LED_GREEN_CAPS ONLP_LED_CAPS_ON_OFF|ONLP_LED_CAPS_GREEN|ONLP_LED_CAPS_GREEN_BLINKING +#define CPLD_LED_RED_CAPS ONLP_LED_CAPS_ON_OFF|ONLP_LED_CAPS_RED|ONLP_LED_CAPS_RED_BLINKING +#define PSOC_LED_GREEN_CAPS ONLP_LED_CAPS_ON_OFF|ONLP_LED_CAPS_GREEN +#define PSOC_LED_RED_CAPS ONLP_LED_CAPS_ON_OFF|ONLP_LED_CAPS_RED + + +typedef enum platform_led_color_e { + PLATFORM_LED_COLOR_NONE, + PLATFORM_LED_COLOR_RED, + PLATFORM_LED_COLOR_GREEN, + PLATFORM_LED_COLOR_ANY, + PLATFORM_LED_COLOR_MAX +} platform_led_color_t; + +typedef enum cpld_led_mode_e { + CPLD_LED_MODE_OFF = 0, + CPLD_LED_MODE_0_5_HZ = 1, + CPLD_LED_MODE_1_HZ = 2, + CPLD_LED_MODE_2_HZ = 3, + CPLD_LED_MODE_ON = 7 +} cpld_led_mode_t; + +typedef enum led_driver_mode_e { + LED_DRIVER_MODE_NONE, + LED_DRIVER_MODE_CPLD, + LED_DRIVER_MODE_PSOC +} led_driver_mode_t; + + +typedef struct ledi_info_s { + platform_led_color_t color; + led_driver_mode_t driver; + char file[ONLP_CONFIG_INFO_STR_MAX]; +} ledi_info_t; + +/* function declarations*/ +static onlp_led_mode_t _cpld_onlp_led_mode_convert(platform_led_color_t color, cpld_led_mode_t mode); +static int _onlp_cpld_led_mode_convert(onlp_led_mode_t onlp_led_mode, platform_led_color_t *pcolor, cpld_led_mode_t *pmode); +static int _cpld_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info); +static int _psoc_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info); +static int _cpld_onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t onlp_mode); +static int _psoc_onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t onlp_mode); + +static ledi_info_t __info_list[ONLP_LED_COUNT] = { + {}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_CPLD, "/sys/bus/i2c/devices/0-0055*grn_led"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_CPLD, "/sys/bus/i2c/devices/0-0055*red_led"}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_grn1"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_red1"}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_grn2"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_red2"}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_grn3"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_red3"}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_grn4"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_red4"}, + {PLATFORM_LED_COLOR_GREEN, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_grn5"}, + {PLATFORM_LED_COLOR_RED, LED_DRIVER_MODE_PSOC,"/sys/bus/i2c/devices/0-0066*fan_led_red5"}, +}; + + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t __onlp_led_info[ONLP_LED_COUNT] = { + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(ONLP_LED_MGMT_GREEN), "MGMT LED GREEN", 0 }, + ONLP_LED_STATUS_PRESENT, + CPLD_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_MGMT_RED), "MGMT LED RED", 0 }, + ONLP_LED_STATUS_PRESENT, + CPLD_LED_RED_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN1_GREEN), "FAN LED 1 GREEN", ONLP_FAN_ID_CREATE(ONLP_FAN_1) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN1_RED), "FAN LED 1 RED", ONLP_FAN_ID_CREATE(ONLP_FAN_1) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_RED_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN2_GREEN), "FAN LED 2 GREEN", ONLP_FAN_ID_CREATE(ONLP_FAN_2) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN2_RED), "FAN LED 2 RED", ONLP_FAN_ID_CREATE(ONLP_FAN_2) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_RED_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN3_GREEN), "FAN LED 3 GREEN", ONLP_FAN_ID_CREATE(ONLP_FAN_3) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN3_RED), "FAN LED 3 RED", ONLP_FAN_ID_CREATE(ONLP_FAN_3) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_RED_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN4_GREEN), "FAN LED 4 GREEN", ONLP_FAN_ID_CREATE(ONLP_FAN_4) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN4_RED), "FAN LED 4 RED", ONLP_FAN_ID_CREATE(ONLP_FAN_4) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_RED_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN5_GREEN), "FAN LED 5 GREEN", ONLP_FAN_ID_CREATE(ONLP_FAN_5) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_GREEN_CAPS, + }, + { + { ONLP_LED_ID_CREATE(ONLP_LED_FAN5_RED), "FAN LED 5 RED", ONLP_FAN_ID_CREATE(ONLP_FAN_5) }, + ONLP_LED_STATUS_PRESENT, + PSOC_LED_RED_CAPS, + }, +}; + + +/* convert platform led type to onlp_led_mode type*/ +static onlp_led_mode_t _cpld_onlp_led_mode_convert(platform_led_color_t color, cpld_led_mode_t mode) +{ + onlp_led_mode_t ret = ONLP_LED_MODE_OFF; + + /* First select the basic state */ + switch(mode) { + case CPLD_LED_MODE_0_5_HZ: + case CPLD_LED_MODE_1_HZ: + case CPLD_LED_MODE_2_HZ: + ret = ONLP_LED_MODE_BLINKING; + break; + case CPLD_LED_MODE_ON: + ret = ONLP_LED_MODE_ON; + break; + case CPLD_LED_MODE_OFF: + default: + ret = ONLP_LED_MODE_OFF; + break; + } + if (ret != ONLP_LED_MODE_OFF) { + /* Add shift to color */ + switch(color) { + case PLATFORM_LED_COLOR_RED: + ret += (ONLP_LED_MODE_RED - ONLP_LED_MODE_ON); + break; + case PLATFORM_LED_COLOR_GREEN: + ret += (ONLP_LED_MODE_GREEN - ONLP_LED_MODE_ON); + break; + default: + break; + } + } + return ret; +} + +static int _onlp_cpld_led_mode_convert(onlp_led_mode_t onlp_led_mode, platform_led_color_t *pcolor, cpld_led_mode_t *pmode) +{ + int rv = ONLP_STATUS_OK; + switch(onlp_led_mode) { + case ONLP_LED_MODE_OFF: + *pcolor = PLATFORM_LED_COLOR_ANY; + *pmode = CPLD_LED_MODE_OFF; + break; + case ONLP_LED_MODE_ON: + *pcolor = PLATFORM_LED_COLOR_ANY; + *pmode = CPLD_LED_MODE_ON; + break; + case ONLP_LED_MODE_BLINKING: + *pcolor = PLATFORM_LED_COLOR_ANY; + *pmode = CPLD_LED_MODE_1_HZ; + break; + case ONLP_LED_MODE_RED: + *pcolor = PLATFORM_LED_COLOR_RED; + *pmode = CPLD_LED_MODE_ON; + break; + case ONLP_LED_MODE_RED_BLINKING: + /* cannot determine the blink level currently, just choose 1Hz*/ + *pcolor = PLATFORM_LED_COLOR_RED; + *pmode = CPLD_LED_MODE_1_HZ; + break; + case ONLP_LED_MODE_GREEN: + *pcolor = PLATFORM_LED_COLOR_GREEN; + *pmode = CPLD_LED_MODE_ON; + break; + case ONLP_LED_MODE_GREEN_BLINKING: + /* cannot determine the blink level currently, just choose 1Hz*/ + *pcolor = PLATFORM_LED_COLOR_GREEN; + *pmode = CPLD_LED_MODE_1_HZ; + break; + + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + return rv; +} + + +static int _cpld_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + platform_led_color_t color; + cpld_led_mode_t mode; + + local_id = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_led_info[local_id]; + + color = __info_list[local_id].color; + + rv = onlp_file_read_int((int*)&mode, __info_list[local_id].file); + + if( ONLP_STATUS_OK == rv ) { + info->mode = _cpld_onlp_led_mode_convert(color, mode); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } else { + info->status &= (~ONLP_LED_STATUS_ON); + } + } + + return rv; +} + +static int _psoc_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + int mode; + platform_led_color_t color; + + + local_id = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_led_info[local_id]; + color = __info_list[local_id].color; + + rv = onlp_file_read_int((int*)&mode, __info_list[local_id].file); + + if( ONLP_STATUS_OK == rv ) { + + if(!mode) { + info->mode = ONLP_LED_MODE_OFF; + } else { + info->mode = ONLP_LED_MODE_ON; + } + + if(info->mode != ONLP_LED_MODE_OFF) { + switch(color) { + case PLATFORM_LED_COLOR_RED: + info->mode += (ONLP_LED_MODE_RED - ONLP_LED_MODE_ON); + break; + case PLATFORM_LED_COLOR_GREEN: + info->mode += (ONLP_LED_MODE_GREEN - ONLP_LED_MODE_ON); + break; + default: + break; + } + } + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } else { + info->status &= (~ONLP_LED_STATUS_ON); + } + } + + return rv; +} + +static int _cpld_onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t onlp_mode) +{ + int local_id; + int rv = ONLP_STATUS_OK; + platform_led_color_t color; + cpld_led_mode_t cpld_mode; + + local_id = ONLP_OID_ID_GET(id); + + + /*convert onlp_led_mode to platform mod*/ + rv = _onlp_cpld_led_mode_convert(onlp_mode, &color, &cpld_mode); + + if( ONLP_STATUS_OK == rv) { + if((color != __info_list[local_id].color)&&(color != PLATFORM_LED_COLOR_ANY)) { + rv = ONLP_STATUS_E_INVALID; + } else { + rv = onlp_file_write_int(cpld_mode, __info_list[local_id].file); + } + } + + return rv; +} + +static int _psoc_onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t onlp_mode) +{ + int local_id; + int rv = ONLP_STATUS_OK; + platform_led_color_t color; + int psoc_mode; + int psoc_diag; + + local_id = ONLP_OID_ID_GET(id); + + rv = platform_psoc_diag_enable_read(&psoc_diag); + + if( ONLP_STATUS_OK == rv ) { + if(!psoc_diag) { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + } + + switch(onlp_mode) { + case ONLP_LED_MODE_OFF: + psoc_mode = 0; + color = PLATFORM_LED_COLOR_ANY; + break; + case ONLP_LED_MODE_ON: + psoc_mode = 1; + color = PLATFORM_LED_COLOR_ANY; + break; + case ONLP_LED_MODE_RED: + color = PLATFORM_LED_COLOR_RED; + psoc_mode = 1; + break; + case ONLP_LED_MODE_GREEN: + color = PLATFORM_LED_COLOR_GREEN; + psoc_mode = 1; + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + + if( ONLP_STATUS_OK == rv) { + if((psoc_mode)&&(color != __info_list[local_id].color)&&(color != PLATFORM_LED_COLOR_ANY)) { + rv = ONLP_STATUS_E_INVALID; + } else { + rv = onlp_file_write_int(psoc_mode, __info_list[local_id].file); + } + } + return rv; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int rv = ONLP_STATUS_OK; + VALIDATE(id); + + if(ONLP_OID_ID_GET(id) >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + + switch(__info_list[ONLP_OID_ID_GET(id)].driver) { + case LED_DRIVER_MODE_NONE: + *info = __onlp_led_info[ONLP_OID_ID_GET(id)]; + break; + case LED_DRIVER_MODE_CPLD: + rv = _cpld_onlp_ledi_info_get(id, info); + break; + case LED_DRIVER_MODE_PSOC: + rv = _psoc_onlp_ledi_info_get(id, info); + break; + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +/** + * @brief Get the LED operational status. + * @param id The LED OID + * @param rv [out] Receives the operational status. + */ +int onlp_ledi_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_led_info_t* info; + + VALIDATE(id); + + if(ONLP_OID_ID_GET(id) >= ONLP_LED_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_led_info[ONLP_OID_ID_GET(id)]; + *rv = info->status; + } + return result; +} + +/** + * @brief Get the LED header. + * @param id The LED OID + * @param rv [out] Receives the header. + */ +int onlp_ledi_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_led_info_t* info; + + VALIDATE(id); + + if(ONLP_OID_ID_GET(id) >= ONLP_LED_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_led_info[ONLP_OID_ID_GET(id)]; + *rv = info->hdr; + } + return result; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + onlp_led_mode_t mode; + VALIDATE(id); + + if(ONLP_OID_ID_GET(id) >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + + + if (__onlp_led_info[ONLP_OID_ID_GET(id)].caps & ONLP_LED_CAPS_ON_OFF) { + mode = on_or_off?ONLP_LED_MODE_ON:ONLP_LED_MODE_OFF; + return onlp_ledi_mode_set(id, mode); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int rv = ONLP_STATUS_OK; + VALIDATE(id); + + if(ONLP_OID_ID_GET(id) >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + + switch(__info_list[ONLP_OID_ID_GET(id)].driver) { + case LED_DRIVER_MODE_CPLD: + rv = _cpld_onlp_ledi_mode_set(id, mode); + break; + case LED_DRIVER_MODE_PSOC: + rv = _psoc_onlp_ledi_mode_set(id, mode); + break; + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..1239e4ae --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_inventec_d5254 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..8bd82691 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,50 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + + +int platform_psoc_diag_enable_read(int *enable) +{ + int rv = ONLP_STATUS_OK; + rv = onlp_file_read_int((int*)enable, PLATFORM_PSOC_DIAG_PATH); + return rv; +} + + +int platform_psoc_diag_enable_write(int enable) +{ + int rv = ONLP_STATUS_OK; + rv = onlp_file_write_int(enable, PLATFORM_PSOC_DIAG_PATH); + return rv; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..eb598bdd --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,160 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_inventec_d5254_log.h" + +/* This is definitions for x86-64-inventec-d5254*/ +/* OID map*/ +/* + * SYS---------ONLP_THERMAL_CPU_PHY + * |----ONLP_THERMAL_CPU_CORE0 + * |----ONLP_THERMAL_CPU_CORE1 + * |----ONLP_THERMAL_CPU_CORE2 + * |----ONLP_THERMAL_CPU_CORE3 + * |----ONLP_THERMAL_1_ON_MAIN_BROAD + * |----ONLP_THERMAL_2_ON_MAIN_BROAD + * |----ONLP_THERMAL_3_ON_MAIN_BROAD + * |----ONLP_THERMAL_4_ON_MAIN_BROAD + * |----ONLP_THERMAL_5_ON_MAIN_BROAD + * |----ONLP_FAN_1--------ONLP_FAN_1_WEAK + * | |--ONLP_LED_FAN1_GREEN + * | |--ONLP_LED_FAN1_RED + * | + * |----ONLP_FAN_2--------ONLP_FAN_2_WEAK + * | |--ONLP_LED_FAN2_GREEN + * | |--ONLP_LED_FAN2_RED + * | + * |----ONLP_FAN_3--------ONLP_FAN_3_WEAK + * | |--ONLP_LED_FAN3_GREEN + * | |--ONLP_LED_FAN3_RED + * | + * |----ONLP_FAN_4--------ONLP_FAN_4_WEAK + * | |--ONLP_LED_FAN4_GREEN + * | |--ONLP_LED_FAN4_RED + * | + * |----ONLP_FAN_5--------ONLP_FAN_5_WEAK + * | |--ONLP_LED_FAN5_GREEN + * | |--ONLP_LED_FAN5_RED + * | + * |----ONLP_PSU_1--------ONLP_THERMAL_1_ON_PSU1 + * | |--ONLP_THERMAL_2_ON_PSU1 + * | |--ONLP_FAN_PSU_1 + * | + * |----ONLP_PSU_2--------ONLP_THERMAL_1_ON_PSU2 + * | |--ONLP_THERMAL_2_ON_PSU2 + * | |--ONLP_FAN_PSU_2 + * | + * |----ONLP_LED_MGMT_GREEN + * |----ONLP_LED_MGMT_RED + */ + +/* Thermal definitions*/ +enum onlp_thermal_id { + ONLP_THERMAL_RESERVED = 0, + ONLP_THERMAL_CPU_PHY, + ONLP_THERMAL_CPU_CORE0, + ONLP_THERMAL_CPU_CORE1, + ONLP_THERMAL_CPU_CORE2, + ONLP_THERMAL_CPU_CORE3, + ONLP_THERMAL_1_ON_MAIN_BROAD, + ONLP_THERMAL_2_ON_MAIN_BROAD, + ONLP_THERMAL_3_ON_MAIN_BROAD, + ONLP_THERMAL_4_ON_MAIN_BROAD, + ONLP_THERMAL_5_ON_MAIN_BROAD, + ONLP_THERMAL_1_ON_PSU1, + ONLP_THERMAL_2_ON_PSU1, + ONLP_THERMAL_1_ON_PSU2, + ONLP_THERMAL_2_ON_PSU2, + ONLP_THERMAL_MAX +}; + +#define ONLP_THERMAL_COUNT 15 /*include "reserved"*/ + +/* Fan definitions*/ +enum onlp_fan_id { + ONLP_FAN_RESERVED = 0, + ONLP_FAN_1, + ONLP_FAN_2, + ONLP_FAN_3, + ONLP_FAN_4, + ONLP_FAN_5, + ONLP_FAN_1_WEAK, + ONLP_FAN_2_WEAK, + ONLP_FAN_3_WEAK, + ONLP_FAN_4_WEAK, + ONLP_FAN_5_WEAK, + ONLP_FAN_PSU_1, + ONLP_FAN_PSU_2, + ONLP_FAN_MAX +}; + +#define ONLP_FAN_COUNT 13 /*include "reserved"*/ + +/* PSU definitions*/ +enum onlp_psu_id { + ONLP_PSU_RESERVED, + ONLP_PSU_1, + ONLP_PSU_2, + ONLP_PSU_MAX +}; + +#define ONLP_PSU_COUNT 3 /*include "reserved"*/ + +/* LED definitions*/ +enum onlp_led_id { + ONLP_LED_RESERVED = 0, + ONLP_LED_MGMT_GREEN, + ONLP_LED_MGMT_RED, + ONLP_LED_FAN1_GREEN, + ONLP_LED_FAN1_RED, + ONLP_LED_FAN2_GREEN, + ONLP_LED_FAN2_RED, + ONLP_LED_FAN3_GREEN, + ONLP_LED_FAN3_RED, + ONLP_LED_FAN4_GREEN, + ONLP_LED_FAN4_RED, + ONLP_LED_FAN5_GREEN, + ONLP_LED_FAN5_RED, + ONLP_LED_MAX +}; + +#define ONLP_LED_COUNT 13 /*include "reserved"*/ + + +/* platform functions*/ +#define PLATFORM_PSOC_DIAG_PATH "/sys/class/hwmon/hwmon1/device/diag" +#define PLATFORM_PSOC_DIAG_LOCK platform_psoc_diag_enable_write(0) +#define PLATFORM_PSOC_DIAG_UNLOCK platform_psoc_diag_enable_write(1) +int platform_psoc_diag_enable_read(int *enable); +int platform_psoc_diag_enable_write(int enable); + + + + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..b97c87ee --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/psui.c @@ -0,0 +1,251 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" +#include +#include + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define PSUI_PLATFORM_PSU_MODEL "DPS-800AB-37D" + + +typedef enum psoc_psu_state_e { + PSOC_PSU_NORMAL = 0, + PSOC_PSU_NA_1, //001 + PSOC_PSU_UNPOWERED, //010 + PSOC_PSU_NA_3, //011 + PSOC_PSU_FAULT, //100 + PSOC_PSU_NA_5, //101 + PSOC_PSU_NA_6, //110 + PSOC_PSU_NOT_INSTALLED //111 +} psoc_psu_state_t; + + +typedef struct psui_info_s { + char vendor[ONLP_CONFIG_INFO_STR_MAX]; + char serial[ONLP_CONFIG_INFO_STR_MAX]; + char state[ONLP_CONFIG_INFO_STR_MAX]; + char vin[ONLP_CONFIG_INFO_STR_MAX]; + char vout[ONLP_CONFIG_INFO_STR_MAX]; + char iin[ONLP_CONFIG_INFO_STR_MAX]; + char iout[ONLP_CONFIG_INFO_STR_MAX]; + char pin[ONLP_CONFIG_INFO_STR_MAX]; + char pout[ONLP_CONFIG_INFO_STR_MAX]; +} psui_info_t; + + +static psui_info_t __info_list[ONLP_PSU_COUNT] = { + {}, + { + "/sys/class/hwmon/hwmon1/device/psoc_psu1_vendor", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_serial", + "/sys/class/hwmon/hwmon1/device/psu1", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_vin", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_vout", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_iin", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_iout", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_pin", + "/sys/class/hwmon/hwmon1/device/psoc_psu1_pout" + }, + { + "/sys/class/hwmon/hwmon1/device/psoc_psu2_vendor", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_serial", + "/sys/class/hwmon/hwmon1/device/psu2", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_vin", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_vout", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_iin", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_iout", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_pin", + "/sys/class/hwmon/hwmon1/device/psoc_psu2_pout" + } +}; + + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t __onlp_psu_info[ONLP_PSU_COUNT] = { + { }, /* Not used */ + { + { + ONLP_PSU_ID_CREATE(ONLP_PSU_1), "PSU-1", 0, + { + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_PSU1), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_PSU1), + ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_1) + } + }, + "","",ONLP_PSU_STATUS_PRESENT, + ONLP_PSU_CAPS_DC12|ONLP_PSU_CAPS_VIN|ONLP_PSU_CAPS_VOUT|ONLP_PSU_CAPS_IIN|ONLP_PSU_CAPS_IOUT|ONLP_PSU_CAPS_PIN|ONLP_PSU_CAPS_POUT + }, + { + { + ONLP_PSU_ID_CREATE(ONLP_PSU_2), "PSU-2", 0, + { + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_PSU2), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_PSU2), + ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_2) + } + }, + "","",ONLP_PSU_STATUS_PRESENT, + ONLP_PSU_CAPS_DC12|ONLP_PSU_CAPS_VIN|ONLP_PSU_CAPS_VOUT|ONLP_PSU_CAPS_IIN|ONLP_PSU_CAPS_IOUT|ONLP_PSU_CAPS_PIN|ONLP_PSU_CAPS_POUT + } +}; + + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int ret = ONLP_STATUS_OK; + int len; + int local_id = ONLP_OID_ID_GET(id); + uint8_t temp[ONLP_CONFIG_INFO_STR_MAX] = {0}; + psoc_psu_state_t psoc_state; + + VALIDATE(id); + + if(local_id >= ONLP_PSU_MAX) { + return ONLP_STATUS_E_INVALID; + } + + + *info = __onlp_psu_info[local_id]; /* Set the onlp_oid_hdr_t */ + + ret = onlp_file_read(temp, ONLP_CONFIG_INFO_STR_MAX, &len, __info_list[local_id].vendor); + /*remove the '\n'*/ + temp[strlen((char*)temp)-1] = 0; + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "%s", temp); + + + memset(temp, 0, ONLP_CONFIG_INFO_STR_MAX); + ret = onlp_file_read(temp, ONLP_CONFIG_INFO_STR_MAX, &len,__info_list[local_id].serial); + /*remove the '\n'*/ + temp[strlen((char*)temp)-1] = 0; + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "%s", temp); + + + ret = onlp_file_read_int((int*)&psoc_state, __info_list[local_id].state); + + if( PSOC_PSU_UNPOWERED == psoc_state) { + info->status = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_UNPLUGGED; + } else if ( PSOC_PSU_NORMAL == psoc_state) { + info->status = ONLP_PSU_STATUS_PRESENT; + } else if( PSOC_PSU_FAULT == psoc_state) { + info->status = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_FAILED; + } else { + info->status = 0; + } + + /*millivolts*/ + ret = onlp_file_read_int(&info->mvin, __info_list[local_id].vin); + ret = onlp_file_read_int(&info->mvout, __info_list[local_id].vout); + + /* milliamps */ + ret = onlp_file_read_int(&info->miin, __info_list[local_id].iin); + ret = onlp_file_read_int(&info->miout, __info_list[local_id].iout); + + /* milliwatts */ + ret = onlp_file_read_int(&info->mpin, __info_list[local_id].pin); + ret = onlp_file_read_int(&info->mpout, __info_list[local_id].pout); + + return ret; +} + + +/** + * @brief Get the PSU's operational status. + * @param id The PSU OID. + * @param rv [out] Receives the operational status. + */ +int onlp_psui_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + psoc_psu_state_t psoc_state; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_PSU_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + result = onlp_file_read_int((int*)&psoc_state, __info_list[local_id].state); + + if( PSOC_PSU_UNPOWERED == psoc_state) { + *rv = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_UNPLUGGED; + } else if ( PSOC_PSU_NORMAL == psoc_state) { + *rv = ONLP_PSU_STATUS_PRESENT; + } else if( PSOC_PSU_FAULT == psoc_state) { + *rv = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_FAILED; + } else { + *rv = 0; + } + } + return result; +} + +/** + * @brief Get the PSU's oid header. + * @param id The PSU OID. + * @param rv [out] Receives the header. + */ +int onlp_psui_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_psu_info_t* info; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_PSU_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_psu_info[local_id]; + *rv = info->hdr; + } + return result; +} + + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..696d384f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,400 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include + +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include + +#define MAX_SFP_PATH 128 +//static char sfp_node_path[MAX_SFP_PATH] = {0}; + +#define MUX_START_INDEX 1 +#define NUM_OF_SFP_PORT 48 +#define NUM_OF_QSFP_PORT 6 +#define NUM_OF_ALL_PORT (NUM_OF_SFP_PORT+NUM_OF_QSFP_PORT) +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_port_is_valid(int port){ + if(port > NUM_OF_ALL_PORT || port < 1) + return 0; + return 1; +} + +int +onlp_sfpi_get_file_byte(int port, char* attr){ + if(!onlp_sfpi_port_is_valid(port)){ + return -1; + } + char path[128]={0}; + int err = snprintf(path, sizeof(path), "/sys/class/swps/port%d/%s", (port-1), attr); + if( err < 0){ + return err; + } + FILE* pFile = fopen(path, "r"); + if(pFile == NULL){ + return ONLP_STATUS_E_UNSUPPORTED; + } + char buf[8] = {0}; + fread( buf, sizeof(buf), sizeof(buf), pFile ); + int ret = strtol (buf, NULL, 10); + fclose(pFile); + return ret; +} + +int +onlp_sfpi_set_file_byte(int port, char* attr, int value){ + if(!onlp_sfpi_port_is_valid(port)){ + return -1; + } + if(value > 10 || value < 0){ + return -1; + } + char path[128]={0}; + int err = snprintf(path, sizeof(path), "/sys/class/swps/port%d/%s", (port-1), attr); + if( err < 0){ + return err; + } + FILE* pFile = fopen(path, "r+"); + if(pFile == NULL){ + return ONLP_STATUS_E_UNSUPPORTED; + } + char buf = 0; + buf = value+'0'; + err = fwrite(&buf, sizeof(buf), sizeof(buf), pFile); + if(err < 0){ + return err; + } + fclose(pFile); + return err; +} + +int +onlp_sfpi_port2chan(int port){ + return port+9; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {1, 54} + */ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 1; p <= NUM_OF_ALL_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present = -999; + present = onlp_sfpi_get_file_byte(port, "present"); + if(present >= 0){ + return (-present)+1; + } + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + AIM_BITMAP_CLR_ALL(dst); + int port=MUX_START_INDEX; + for(port=MUX_START_INDEX;port<=NUM_OF_ALL_PORT;port++){ + if(onlp_sfpi_is_present(port)) + AIM_BITMAP_SET(dst, port); + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_rx_los(int port) +{ + if(port <= NUM_OF_SFP_PORT){ + if (onlp_sfpi_is_present(port) == 1){ + int rxlos = onlp_sfpi_get_file_byte(port, "rxlos"); + if(rxlos < 0){ + AIM_LOG_ERROR("Unable to read rxlos from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return rxlos; + } + return 0; + } + else if(port > NUM_OF_SFP_PORT){ + return 0; + } + AIM_LOG_ERROR("Read rxlos from port(%d) out of range.\r\n", port); + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + AIM_BITMAP_CLR_ALL(dst); + int port=MUX_START_INDEX; + for(port=MUX_START_INDEX;port<=NUM_OF_ALL_PORT;port++){ + if(onlp_sfpi_is_rx_los(port)) + AIM_BITMAP_SET(dst, port); + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_post_insert(int port, sff_info_t* info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + memset(data, 0, 256); + + int byte = -1; + byte = onlp_i2c_read(onlp_sfpi_port2chan(port), 0x50, 0, 256, data, 0); + if(byte < 0){ + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_port2chan(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = onlp_sfpi_port2chan(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_port2chan(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = onlp_sfpi_port2chan(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + if(port >= NUM_OF_SFP_PORT && port < (NUM_OF_SFP_PORT + NUM_OF_QSFP_PORT)){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + case ONLP_SFP_CONTROL_RX_LOS: + *rv = 0; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + if(port <= NUM_OF_SFP_PORT){ + *rv = 1; + } + else if(port >= NUM_OF_SFP_PORT && port < (NUM_OF_SFP_PORT + NUM_OF_QSFP_PORT)){ + *rv = 0; + } + break; + case ONLP_SFP_CONTROL_LP_MODE: + if(port >= NUM_OF_SFP_PORT && port < (NUM_OF_SFP_PORT + NUM_OF_QSFP_PORT)){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + default: + break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int ret_val = 0; + int err = 0; + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + err = onlp_sfpi_set_file_byte(port, "reset", value); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + err = onlp_sfpi_set_file_byte(port, "tx_disable", value); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_LP_MODE: + err = onlp_sfpi_set_file_byte(port, "lpmod", value); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + ret_val = ONLP_STATUS_OK; + break; + default: + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return ret_val; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int ret_val = 0; + int err = 0; + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + err = onlp_sfpi_get_file_byte(port, "reset"); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + *value = err; + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + err = onlp_sfpi_get_file_byte(port, "rxlos"); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + *value = err; + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + err = onlp_sfpi_get_file_byte(port, "tx_disable"); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + *value = err; + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_LP_MODE: + err = onlp_sfpi_get_file_byte(port, "lpmod"); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + *value = err; + ret_val = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_TX_FAULT: + err = onlp_sfpi_get_file_byte(port, "tx_fault"); + if(err == ONLP_STATUS_E_UNSUPPORTED){ + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + *value = err; + ret_val = ONLP_STATUS_OK; + break; + default: + ret_val = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return ret_val; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + +void +onlp_sfpi_debug(int port, aim_pvs_t* pvs) +{ + aim_printf(pvs, "Debug data for port %d goes here.", port); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..f1544719 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,1173 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "x86_64_inventec_d5254_int.h" +#include "x86_64_inventec_d5254_log.h" + +#include "platform_lib.h" + +#define SYSI_ONIE_TYPE_SUPPORT_NUM 17 +#define SYSI_PLATFORM_INFO_TYPE_STR_MAX 10 +#define SYSI_PLATFORM_INFO_NUM 2 + +/** + * The TLV Types. + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + + +typedef struct sysi_onie_vpd_s { + uint8_t type; + char file[ONLP_CONFIG_INFO_STR_MAX]; +} sysi_onie_vpd_t; + + + + + +typedef struct sysi_platform_info_s { + char type[SYSI_PLATFORM_INFO_TYPE_STR_MAX]; + char file[ONLP_CONFIG_INFO_STR_MAX]; + int (*parsing_func_ptr)(char* file_str, char* version); +} sysi_platform_info_t; + +static int _sysi_cpld_version_parsing(char* file_str, char* version); +static int _sysi_psoc_version_parsing(char* file_str, char* version); +static int _sysi_onie_product_name_get(char** product_name); +static int _sysi_onie_part_number_get(char** part_number); +static int _sysi_onie_serial_number_get(char** serial_number); +static int _sysi_onie_mac_base_get(uint8_t mac_base[6]); +static int _sysi_onie_manuf_date_get(char** manuf_date); +static int _sysi_onie_device_version_get(uint8_t* device_version); +static int _sysi_onie_label_revision_get(char** label_revision); +static int _sysi_onie_platform_name_get(char** platform_name); +static int _sysi_onie_onie_version_get(char** onie_version); +static int _sysi_onie_mac_size_get(uint16_t* mac_size); +static int _sysi_onie_manuf_name_get(char** manuf_name); +static int _sysi_onie_manuf_country_get(char** manuf_country); +static int _sysi_onie_vendor_name_get(char** vendor_name); +static int _sysi_onie_diag_version_get(char** diag_version); +static int _sysi_onie_service_tag_get(char** service_tag); +static int _sysi_onie_vendor_ext_get(list_head_t *vendor_ext); +static int _sysi_onie_crc_32_get(uint32_t* crc_32); + +static int _sysi_onie_info_total_len_get(onlp_onie_info_t *onie, uint16_t *total_len); + + + +static sysi_onie_vpd_t __tlv_vpd_info[SYSI_ONIE_TYPE_SUPPORT_NUM] = { + { + TLV_CODE_PRODUCT_NAME, + "/sys/class/eeprom/vpd/product_name" + }, + { + TLV_CODE_PART_NUMBER, + "/sys/class/eeprom/vpd/pn" + }, + { + TLV_CODE_SERIAL_NUMBER, + "/sys/class/eeprom/vpd/sn" + }, + { + TLV_CODE_MAC_BASE, + "/sys/class/eeprom/vpd/base_mac_addr" + }, + { + TLV_CODE_MANUF_DATE, + "/sys/class/eeprom/vpd/man_date" + }, + { + TLV_CODE_DEVICE_VERSION, + "/sys/class/eeprom/vpd/dev_ver" + }, + { + TLV_CODE_LABEL_REVISION, + "/sys/class/eeprom/vpd/label_rev" + }, + { + TLV_CODE_PLATFORM_NAME, + "/sys/class/eeprom/vpd/plat_name" + }, + { + TLV_CODE_ONIE_VERSION, + "/sys/class/eeprom/vpd/ldr_ver" + }, + { + TLV_CODE_MAC_SIZE, + "/sys/class/eeprom/vpd/mac_addr" + }, + { + TLV_CODE_MANUF_NAME, + "/sys/class/eeprom/vpd/manufacturer" + }, + { + TLV_CODE_MANUF_COUNTRY, + "/sys/class/eeprom/vpd/country_code" + }, + { + TLV_CODE_VENDOR_NAME, + "/sys/class/eeprom/vpd/vendor_name" + }, + { + TLV_CODE_DIAG_VERSION, + "/sys/class/eeprom/vpd/diag_ver" + }, + { + TLV_CODE_SERVICE_TAG, + "/sys/class/eeprom/vpd/service_tag" + }, + { + TLV_CODE_VENDOR_EXT, + "/sys/class/eeprom/vpd/vendor_ext" + }, + { + TLV_CODE_CRC_32, + "/sys/class/eeprom/vpd/crc32" + } +}; + + +static sysi_platform_info_t __platform_info[SYSI_PLATFORM_INFO_NUM] = { + {"cpld", "/sys/class/hwmon/hwmon2/device/info",_sysi_cpld_version_parsing}, + {"psoc", "/sys/class/hwmon/hwmon1/device/version",_sysi_psoc_version_parsing} +}; + + +static onlp_oid_t __oid_info[] = { + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_PHY), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE0), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE1), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE2), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE3), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_MAIN_BROAD), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_MAIN_BROAD), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_3_ON_MAIN_BROAD), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_4_ON_MAIN_BROAD), + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_5_ON_MAIN_BROAD), + ONLP_FAN_ID_CREATE(ONLP_FAN_1), + ONLP_FAN_ID_CREATE(ONLP_FAN_2), + ONLP_FAN_ID_CREATE(ONLP_FAN_3), + ONLP_FAN_ID_CREATE(ONLP_FAN_4), + ONLP_FAN_ID_CREATE(ONLP_FAN_5), + ONLP_PSU_ID_CREATE(ONLP_PSU_1), + ONLP_PSU_ID_CREATE(ONLP_PSU_2), + ONLP_LED_ID_CREATE(ONLP_LED_MGMT_GREEN), + ONLP_LED_ID_CREATE(ONLP_LED_MGMT_RED), + 0 /*end*/ +}; + + + + +static int _sysi_cpld_version_parsing(char* file_str, char* version) +{ + int rv = ONLP_STATUS_OK; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX*4]; + char *temp; + + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX*4, &len, file_str); + + temp = strstr(buf, "The CPLD version is "); + if(temp) { + temp += strlen("The CPLD version is "); + snprintf(version,ONLP_CONFIG_INFO_STR_MAX, temp); + /*remove '\n'*/ + version[strlen(version)-1] = 0; + } else { + rv = ONLP_STATUS_E_MISSING; + } + return rv; +} + +static int _sysi_psoc_version_parsing(char* file_str, char* version) +{ + int rv = ONLP_STATUS_OK; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + char *temp; + + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, file_str); + temp = strstr(buf, "ver: "); + if(temp) { + temp += strlen("ver: "); + snprintf(version,ONLP_CONFIG_INFO_STR_MAX, temp); + /*remove '\n'*/ + version[strlen(version)-1] = 0; + } else { + rv = ONLP_STATUS_E_MISSING; + } + return rv; +} + +static int _sysi_onie_product_name_get(char** product_name) +{ + int rv = ONLP_STATUS_OK; + int i; + int len; + char* path; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + + for(i=0; iproduct_name)!= 0) { + len += 2; + len += strlen(onie->product_name); + } + /*part_number*/ + if(strlen(onie->part_number)!= 0) { + len += 2; + len += strlen(onie->part_number); + } + /*serial_number*/ + if(strlen(onie->serial_number)!= 0) { + len += 2; + len += strlen(onie->serial_number); + } + + /*mac*/ + len += 2; + len += 6; + + /*manufacture_date*/ + if(strlen(onie->manufacture_date)!= 0) { + len += 2; + len += 19; + } + + /*device_version*/ + len += 2; + len += 1; + + /*label_revision*/ + if(strlen(onie->label_revision)!= 0) { + len += 2; + len += strlen(onie->label_revision); + } + + /*platform_name*/ + if(strlen(onie->platform_name)!= 0) { + len += 2; + len += strlen(onie->platform_name); + } + + /*onie_version*/ + if(strlen(onie->onie_version)!= 0) { + len += 2; + len += strlen(onie->onie_version); + } + + /*mac_range*/ + len += 2; + len += 2; + + /*manufacturer*/ + if(strlen(onie->manufacturer)!= 0) { + len += 2; + len += strlen(onie->manufacturer); + } + + /*country_code*/ + if(strlen(onie->country_code)!= 0) { + len += 2; + len += 2; + } + + /*vendor*/ + if(strlen(onie->vendor)!= 0) { + len += 2; + len += strlen(onie->vendor); + } + + /*diag_version*/ + if(strlen(onie->diag_version)!= 0) { + len += 2; + len += strlen(onie->diag_version); + } + + /*service_tag*/ + if(strlen(onie->service_tag)!= 0) { + len += 2; + len += strlen(onie->service_tag); + } + + /*crc*/ + len += 2; + len += 4; + + /*vx_list*/ + /*TODO*/ + + *total_len = len; + return ONLP_STATUS_OK; +} + + + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-inventec-d5254-r0"; +} + + +/* + * This function is called to return the physical base address + * of the ONIE boot rom. + * + * The ONLP framework will mmap() and parse the ONIE TLV structure + * from the given data. + * + * If you platform does not support a mappable address for the ONIE + * eeprom then you should not provide this function at all. + * + * For the purposes of this example we will provide it but + * return UNSUPPORTED (which is all the default implementation does). + * + */ +int +onlp_sysi_onie_data_phys_addr_get(void** pa) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * If you cannot provide a base address you must provide the ONLP + * framework the raw ONIE data through whatever means necessary. + * + * This function will be called as a backup in the event that + * onlp_sysi_onie_data_phys_addr_get() fails. + */ +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ +#if 0 + int rv; + int i; + + /* + * This represents the example ONIE data. + */ + static uint8_t onie_data[] = { + 'T', 'l', 'v','I','n','f','o', 0, + 0x1, 0x0, 0x0, + 0x21, 0x8, 'O', 'N', 'L', 'P', 'I', 'E', 0, 0, + 0x22, 0x3, 'O', 'N', 'L', + 0xFE, 0x4, 0x4b, 0x1b, 0x1d, 0xde, + }; + + + memcpy(*data, onie_data, ONLPLIB_CONFIG_I2C_BLOCK_SIZE); + return 0; +#endif + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * IF the ONLP frame calles onlp_sysi_onie_data_get(), + * if will call this function to free the data when it + * is finished with it. + * + * This function is optional, and depends on the data + * you return in onlp_sysi_onie_data_get(). + */ +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + /* + * We returned a static array in onlp_sysi_onie_data_get() + * so no free operation is required. + */ + if(data) { + aim_free(data); + } +} + +int +onlp_sysi_onie_info_get (onlp_onie_info_t *onie) +{ + int rv = ONLP_STATUS_OK; + uint16_t total_len; + + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_product_name_get(&onie->product_name); + } + + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_part_number_get(&onie->part_number); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_serial_number_get(&onie->serial_number); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_mac_base_get(onie->mac); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_manuf_date_get(&onie->manufacture_date); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_device_version_get(&onie->device_version); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_label_revision_get(&onie->label_revision); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_platform_name_get(&onie->platform_name); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_onie_version_get(&onie->onie_version); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_mac_size_get(&onie->mac_range); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_manuf_name_get(&onie->manufacturer); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_manuf_country_get(&onie->country_code); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_vendor_name_get(&onie->vendor); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_diag_version_get(&onie->diag_version); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_service_tag_get(&onie->service_tag); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_vendor_ext_get(&onie->vx_list); + } + if(ONLP_STATUS_OK == rv) { + rv = _sysi_onie_crc_32_get(&onie->crc); + } + + _sysi_onie_info_total_len_get(onie, &total_len); + + onie->_hdr_id_string = aim_fstrdup("TlvInfo"); + onie->_hdr_version = 0x1; + onie->_hdr_length = total_len; + return rv; +} + + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i; + int rv = ONLP_STATUS_OK; + char cpld_str[ONLP_CONFIG_INFO_STR_MAX]= {0}; + char other_str[ONLP_CONFIG_INFO_STR_MAX]= {0}; + char version[ONLP_CONFIG_INFO_STR_MAX]; + + for(i=0 ; i 0) { + pi->cpld_versions = aim_fstrdup("%s",cpld_str); + } + + /*other version*/ + if(strlen(other_str) > 0) { + pi->other_versions = aim_fstrdup("%s",other_str); + } + return rv; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + if(pi->cpld_versions) { + aim_free(pi->cpld_versions); + } + if(pi->other_versions) { + aim_free(pi->other_versions); + } + return; +} + + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + for(i=0; i + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +typedef struct thermali_info_s { + char file[ONLP_CONFIG_INFO_STR_MAX]; +} thermali_info_t; + +static thermali_info_t __info_list[ONLP_THERMAL_COUNT] = { + {}, + {"/sys/class/hwmon/hwmon0/temp1_input"}, + {"/sys/class/hwmon/hwmon0/temp2_input"}, + {"/sys/class/hwmon/hwmon0/temp3_input"}, + {"/sys/class/hwmon/hwmon0/temp4_input"}, + {"/sys/class/hwmon/hwmon0/temp5_input"}, + {"/sys/class/hwmon/hwmon1/device/temp1_input"}, + {"/sys/class/hwmon/hwmon1/device/temp2_input"}, + {"/sys/class/hwmon/hwmon1/device/temp3_input"}, + {"/sys/class/hwmon/hwmon1/device/temp4_input"}, + {"/sys/class/hwmon/hwmon1/device/temp5_input"}, + {"/sys/class/hwmon/hwmon1/device/thermal_psu1"}, + {"/sys/class/hwmon/hwmon1/device/thermal2_psu1"}, + {"/sys/class/hwmon/hwmon1/device/thermal_psu2"}, + {"/sys/class/hwmon/hwmon1/device/thermal2_psu2"} +}; + + +/* Static values */ +static onlp_thermal_info_t __onlp_thermal_info[ONLP_THERMAL_COUNT] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_PHY), "CPU Physical", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE0), "CPU Core0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE1), "CPU Core1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE2), "CPU Core2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE3), "CPU Core3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_MAIN_BROAD), "Thermal Sensor 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_MAIN_BROAD), "Thermal Sensor 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_3_ON_MAIN_BROAD), "Thermal Sensor 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_4_ON_MAIN_BROAD), "Thermal Sensor 4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_5_ON_MAIN_BROAD), "Thermal Sensor 5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(ONLP_PSU_1)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(ONLP_PSU_1)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(ONLP_PSU_2)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(ONLP_PSU_2)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_thermal_info[local_id]; + return onlp_file_read_int(&info->mcelsius, __info_list[local_id].file); +} + + +/** + * @brief Retrieve the thermal's operational status. + * @param id The thermal oid. + * @param rv [out] Receives the operational status. + */ +int onlp_thermali_status_get(onlp_oid_t id, uint32_t* rv) +{ + int local_id; + + onlp_thermal_info_t* info; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + info = &__onlp_thermal_info[local_id]; + + *rv = info->status; + + return ONLP_STATUS_OK; +} + +/** + * @brief Retrieve the thermal's oid header. + * @param id The thermal oid. + * @param rv [out] Receives the header. + */ +int onlp_thermali_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int local_id; + onlp_thermal_info_t* info; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + info = &__onlp_thermal_info[local_id]; + + *rv = info->hdr; + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_config.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_config.c new file mode 100644 index 00000000..f19d52c8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_inventec_d5254_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_inventec_d5254_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d5254_config_STRINGIFY_NAME(_x) +x86_64_inventec_d5254_config_settings_t x86_64_inventec_d5254_config_settings[] = +{ +#ifdef x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_inventec_d5254_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_PORTING_STDLIB + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_PORTING_STDLIB), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_inventec_d5254_CONFIG_PORTING_STDLIB(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_inventec_d5254_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_inventec_d5254_config_STRINGIFY_NAME(x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d5254_config_STRINGIFY_VALUE(x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_inventec_d5254_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d5254_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_inventec_d5254_config_STRINGIFY_VALUE +#undef __x86_64_inventec_d5254_config_STRINGIFY_NAME + +const char* +x86_64_inventec_d5254_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_inventec_d5254_config_settings[i].name; i++) { + if(strcmp(x86_64_inventec_d5254_config_settings[i].name, setting)) { + return x86_64_inventec_d5254_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_inventec_d5254_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_inventec_d5254_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_inventec_d5254_config_settings[i].name, x86_64_inventec_d5254_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_enums.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_enums.c new file mode 100644 index 00000000..c9e1ff62 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_int.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_int.h new file mode 100644 index 00000000..23a13acd --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_inventec_d5254 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5254_INT_H__ +#define __x86_64_inventec_d5254_INT_H__ + +#include + + +#endif /* __x86_64_inventec_d5254_INT_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.c new file mode 100644 index 00000000..0436c9c2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d5254_log.h" +/* + * x86_64_inventec_d5254 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_inventec_d5254_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_inventec_d5254_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_inventec_d5254_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.h new file mode 100644 index 00000000..4e50920e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5254_LOG_H__ +#define __x86_64_inventec_d5254_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_inventec_d5254 +#include + +#endif /* __x86_64_inventec_d5254_LOG_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_module.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_module.c new file mode 100644 index 00000000..d62d4ff3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d5254_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_inventec_d5254_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_inventec_d5254_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_ucli.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_ucli.c new file mode 100644 index 00000000..296932d9 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/onlp/builds/src/module/src/x86_64_inventec_d5254_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_inventec_d5254_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_inventec_d5254_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d5254) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_inventec_d5254_ucli_module__ = + { + "x86_64_inventec_d5254_ucli", + NULL, + x86_64_inventec_d5254_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_inventec_d5254_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_inventec_d5254_ucli_module__); + n = ucli_node_create("x86_64_inventec_d5254", NULL, &x86_64_inventec_d5254_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d5254")); + return n; +} + +#else +void* +x86_64_inventec_d5254_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/PKG.yml new file mode 100644 index 00000000..b24bf46d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d5254 REVISION=r0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/healthstatus.sh b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/healthstatus.sh new file mode 100755 index 00000000..093b3a86 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/healthstatus.sh @@ -0,0 +1,96 @@ +#!/bin/bash +#follow Gulmohar_HW_Specification_V0.8_20180702 +normal='0 : normal' +unpowered='2 : unpowered' +fault='4 : fault' +notinstalled='7 : not installed' +FAN_UNPLUG_NUM=0 +FAN_LED_RED='fan_led_red' +NUM=1 +FAN_NUM=5 +FIRST_READ=0 +SECOND_READ=0 +#PSU_STAUS='000' +#switch is ready , transfer control of cpld to cpu +echo 1 > /sys/bus/i2c/devices/i2c-0/0-0055/ctl + +while true +do + +#monitor how many fan modules are unplugged + + +#first check +FAN_UNPLUG_NUM=0 +FAN_ARR=$(cat /sys/class/hwmon/hwmon1/$FAN_LED_RED?) + +while read -r line; do + fan_led_red_check=$(echo "$line") + if [ $fan_led_red_check -eq 1 ] + then + let FAN_UNPLUG_NUM=FAN_UNPLUG_NUM+1 + fi +done <<< "$FAN_ARR" +FIRST_READ=$FAN_UNPLUG_NUM + +#second check +FAN_UNPLUG_NUM=0 +FAN_ARR=$(cat /sys/class/hwmon/hwmon1/$FAN_LED_RED?) + +while read -r line; do + fan_led_red_check=$(echo "$line") + if [ $fan_led_red_check -eq 1 ] + then + let FAN_UNPLUG_NUM=FAN_UNPLUG_NUM+1 + fi +done <<< "$FAN_ARR" +SECOND_READ=$FAN_UNPLUG_NUM + +if [ $FIRST_READ -ne $SECOND_READ ] +then + #echo "not equl:$FIRST_READ != $SECOND_READ" + continue +fi + +if [ $FAN_UNPLUG_NUM -ge 2 ] +then + #echo "solid red" + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led + echo 0 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led + sleep 1 + continue +elif [ $FAN_UNPLUG_NUM -eq 1 ] +then + #solid orange + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led + sleep 1 + continue +fi + + #echo "normal" + psu0var=$(cat /sys/bus/i2c/devices/i2c-0/0-0055/psu0) # bottom PSU + psu1var=$(cat /sys/bus/i2c/devices/i2c-0/0-0055/psu1) # top PSU + + if [ "$psu0var" = "$normal" ] && + [ "$psu1var" = "$normal" ] # PSU normal operatio + then + #solid green + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led + echo 0 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led + #echo "solid green" + else + if [ "$psu0var" = "$unpowered" ] || + [ "$psu1var" = "$unpowered" ] + then + #echo solid orange + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led + fi + + fi + + +sleep 1 +done + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/x86-64-inventec-d5254-r0.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/x86-64-inventec-d5254-r0.yml new file mode 100644 index 00000000..0cfd9812 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/lib/x86-64-inventec-d5254-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for d5254 +# +###################################################################### + +x86-64-inventec-d5254-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/python/x86_64_inventec_d5254_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/python/x86_64_inventec_d5254_r0/__init__.py new file mode 100644 index 00000000..9e07ddc1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5254/platform-config/r0/src/python/x86_64_inventec_d5254_r0/__init__.py @@ -0,0 +1,28 @@ +from onl.platform.base import * +from onl.platform.inventec import * + +class OnlPlatform_x86_64_inventec_d5254_r0(OnlPlatformInventec, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-inventec-d5254-r0' + MODEL="D5254" + SYS_OBJECT_ID=".1.32" + + def baseconfig(self): + os.system("insmod /lib/modules/`uname -r`/onl/inventec/x86-64-inventec-d5254/gpio-ich.ko") + #self.insmod('gpio-ich.ko') + self.insmod('i2c-gpio') + self.insmod('inv_platform') + self.insmod('inv_psoc') + os.system("echo inv_cpld 0x55 > /sys/bus/i2c/devices/i2c-0/new_device") + os.system("echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/new_device") + self.insmod('inv_cpld') + self.insmod('inv_mux') + self.insmod('io_expander') + self.insmod('transceiver') + self.insmod('inv_swps') + self.insmod('onie_tlvinfo') + self.insmod('inv_vpd') + os.system("/lib/platform-config/x86-64-inventec-d5254-r0/onl/healthstatus.sh &") + + return True + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/.gitignore new file mode 100644 index 00000000..73326b8f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/.gitignore @@ -0,0 +1,2 @@ +*x86*64*inventec*d5264q28b*.mk +onlpdump.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/PKG.yml new file mode 100644 index 00000000..02c71a93 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d5264q28b ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/Makefile new file mode 100644 index 00000000..740ae3a3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := inventec +BASENAME := x86-64-inventec-d5264q28b +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/Makefile new file mode 100644 index 00000000..754b0b21 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/Makefile @@ -0,0 +1,10 @@ +#obj-m += gpio-ich.o +obj-m += inv_cpld.o +obj-m += inv_mux.o +obj-m += inv_platform.o +obj-m += inv_psoc.o +obj-m += inv_swps.o +obj-m += inv_vpd.o +obj-m += io_expander.o +obj-m += onie_tlvinfo.o +obj-m += transceiver.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/gpio-ich.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/gpio-ich.c new file mode 100644 index 00000000..70304220 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/gpio-ich.c @@ -0,0 +1,548 @@ +/* + * 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 +#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))); +} + +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; + chip->dev = &ichx_priv.dev->dev; + + /* 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, +}; + +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; + 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; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_cpld.c new file mode 100644 index 00000000..57791f62 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_cpld.c @@ -0,0 +1,463 @@ +/* + * This program is free software; you can 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 + "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 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, +}; + +/*-----------------------------------------------------------------------*/ + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..a0f5ce34 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.c @@ -0,0 +1,281 @@ +#include +#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 = "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; + mod_dsc = "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; + mod_dsc = "Hedera force mode"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + 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; + mod_dsc = "Normal mode :48"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_69_PAC9548: + 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; + mod_dsc = "Normal mode :69"; + 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__); +} +EXPORT_SYMBOL(clean_mux_gpio); + + +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; +} +EXPORT_SYMBOL(reset_mux_gpio); + + +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; +} +EXPORT_SYMBOL(init_mux_gpio); + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..429754a8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_mux.h @@ -0,0 +1,36 @@ +#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) + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_platform.c new file mode 100644 index 00000000..3da78567 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_platform.c @@ -0,0 +1,280 @@ +#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(1),}, {.adap_id = bus_id(2),}, + {.adap_id = bus_id(3),}, {.adap_id = bus_id(4),}, + {.adap_id = bus_id(5),}, {.adap_id = bus_id(8),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.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),}, {.adap_id = bus_id(22),}, + {.adap_id = bus_id(23),}, {.adap_id = bus_id(24),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.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),}, {.adap_id = bus_id(30),}, + {.adap_id = bus_id(31),}, {.adap_id = bus_id(32),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.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),}, {.adap_id = bus_id(38),}, + {.adap_id = bus_id(39),}, {.adap_id = bus_id(40),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(41),}, {.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),}, +}; + + +static struct pca954x_platform_mode mux_modes_0_7[] = { + {.adap_id = bus_id(9),}, {.adap_id = bus_id(10),}, + {.adap_id = bus_id(11),}, {.adap_id = bus_id(12),}, +}; +static struct pca954x_platform_mode mux_modes_0_7_0[] = { + {.adap_id = bus_id(49),}, {.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),}, +}; + +static struct pca954x_platform_mode mux_modes_0_7_1[] = { + {.adap_id = bus_id(57),}, {.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),}, +}; + +static struct pca954x_platform_mode mux_modes_0_7_2[] = { + {.adap_id = bus_id(65),}, {.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),}, +}; + +static struct pca954x_platform_mode mux_modes_0_7_3[] = { + {.adap_id = bus_id(73),}, {.adap_id = bus_id(74),}, + {.adap_id = bus_id(75),}, {.adap_id = bus_id(76),}, + {.adap_id = bus_id(77),}, {.adap_id = bus_id(78),}, + {.adap_id = bus_id(79),}, {.adap_id = bus_id(80),}, +}; + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 6, +}; +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_7 = { + .modes = mux_modes_0_7, + .num_modes = 4, +}; +static struct pca954x_platform_data mux_data_0_7_0 = { + .modes = mux_modes_0_7_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_7_1 = { + .modes = mux_modes_0_7_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_7_2 = { + .modes = mux_modes_0_7_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_7_3 = { + .modes = mux_modes_0_7_3, + .num_modes = 8, +}; + + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"inv_cpld", 0, 0x55, 0, 0, 0}, + {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info1[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 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_info8[] __initdata = { + {"inv_cpld", 0, 0x77, 0, 0, 0}, + {"pca9548", 0, 0x71, &mux_data_0_7, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info9[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info10[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7_1, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info11[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7_2, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info12[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7_3, 0, 0}, +}; + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0, mux0 + {8, ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux9 + + {bus_id(1), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 }, //mux1 + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux2 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux3 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux4 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, + + {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux5 + {bus_id(10), ARRAY_SIZE(i2c_device_info10), i2c_device_info10 }, //mux6 + {bus_id(11), ARRAY_SIZE(i2c_device_info11), i2c_device_info11 }, //mux7 + {bus_id(12), ARRAY_SIZE(i2c_device_info12), i2c_device_info12 }, //mux8 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +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_lavender_x86_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + printk("el6661 plat_lavender_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 +#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 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__)) 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_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(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_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, + + //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, + + //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, + + + 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; + } + + 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; + } + + 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) +{ + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..723d664c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.c @@ -0,0 +1,2912 @@ +#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, + (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; +} + + +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_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); +} + +/* ========== 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); + +/* ========== 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_LAVENDER: + 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_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_LAVENDER + case PLATFORM_TYPE_LAVENDER: + 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; + } + 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: + 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_LAVENDER_P01P08: + case IOEXP_TYPE_LAVENDER_P09P16: + 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 0 + if (init_mux_gpio(gpio_rest_mux) < 0){ + goto err_init_mux; + } +#endif + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..3a937f04 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_swps.h @@ -0,0 +1,762 @@ +#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.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_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_LAVENDER (161) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_LAVENDER + +/* 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_LAVENDER) + #define SWPS_LAVENDER (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_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_LAVENDER, "Lavender" }, +}; + + +/* ========================================== + * 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_NAB, { {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 */ + }, + {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 + + + +/* ========================================== + * 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 + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#ifdef SWPS_LAVENDER +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +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_LAVENDER_P01P08, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {1, IOEXP_TYPE_LAVENDER_P09P16, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {2, IOEXP_TYPE_LAVENDER_P01P08, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {3, IOEXP_TYPE_LAVENDER_P09P16, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {4, IOEXP_TYPE_LAVENDER_P01P08, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {5, IOEXP_TYPE_LAVENDER_P09P16, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {6, IOEXP_TYPE_LAVENDER_P01P08, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {7, IOEXP_TYPE_LAVENDER_P09P16, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1-4 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1-4 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, /* addr[2] = I/O Expander 1-4 C */ + }, + }, + {8, IOEXP_TYPE_LAVENDER_P65, { {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xf6, 0xff}, {0xf8, 0xff}, }, /* addr[0] = I/O Expander */ + }, + }, +}; + +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, CHIP_TYPE_D5264Q28B, { 1, 2, 3, 4} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 5, 6, 7, 8} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 9, 10, 11, 12} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 13, 14, 15, 16} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 17, 18, 19, 20} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 21, 22, 23, 24} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 25, 26, 27, 28} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 29, 30, 31, 32} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 33, 34, 35, 36} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 37, 38, 39, 40} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 41, 42, 43, 44} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 45, 46, 47, 48} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 49, 50, 51, 52} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 53, 54, 55, 56} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 57, 58, 59, 60} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 61, 62, 63, 64} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 65, 66, 67, 68} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 69, 70, 71, 72} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 73, 74, 75, 76} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 77, 78, 79, 80} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 81, 82, 83, 84} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 85, 86, 87, 88} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 89, 90, 91, 92} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 93, 94, 95, 96} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, { 97, 98, 99,100} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {101,102,103,104} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {105,106,107,108} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {109,110,111,112} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {113,114,115,116} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {117,118,119,120} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {121,122,123,124} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {125,126,127,128} }, + + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {129,130,131,132} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {133,134,135,136} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {137,138,139,140} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {141,142,143,144} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {145,146,147,148} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {149,150,151,152} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {153,154,155,156} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {157,158,159,160} }, + + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {161,162,163,164} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {165,166,167,168} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {169,170,171,172} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {173,174,175,176} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {177,178,179,180} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {181,182,183,184} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {185,186,187,188} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {189,190,191,192} }, + + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {193,194,195,196} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {197,198,199,200} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {201,202,203,204} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {205,206,207,208} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {209,210,211,212} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {213,214,215,216} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {217,218,219,220} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {221,222,223,224} }, + + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {225,226,227,228} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {229,230,231,232} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {233,234,235,236} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {237,238,239,240} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {241,242,243,244} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {245,246,247,248} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {249,250,251,252} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {253,254,255,256} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_D5264Q28B, {257,258,259,260} }, +}; +#endif + + +#endif /* INV_SWPS_H */ + + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..b6d755e1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +static int +__swp_match(struct device *dev, +#ifdef VPD_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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..58c7fe33 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/inv_vpd.h @@ -0,0 +1,46 @@ +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_ENTRY_SIZE (17) +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.c new file mode 100644 index 00000000..5d609ba8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.c @@ -0,0 +1,1831 @@ +#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; + + +/* ========== 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_lavender_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_tx_disable = { {3, 0, 0}, /* map_tx_disable[0] = DIS_QSFP28_P(X) */ + {3, 0, 1}, /* map_tx_disable[1] = DIS_QSFP28_P(X+1) */ + {3, 0, 2}, /* map_tx_disable[2] = DIS_QSFP28_P(X+2) */ + {3, 0, 3}, /* map_tx_disable[3] = DIS_QSFP28_P(X+3) */ + {3, 0, 4}, /* map_tx_disable[4] = DIS_QSFP28_P(X+4) */ + {3, 0, 5}, /* map_tx_disable[5] = DIS_QSFP28_P(X+5) */ + {3, 0, 6}, /* map_tx_disable[6] = DIS_QSFP28_P(X+6) */ + {3, 0, 7}, /* map_tx_disable[7] = DIS_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) */ + }, + .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_rxlos = { {2, 0, 0}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {2, 0, 1}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {2, 0, 2}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {2, 0, 3}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {2, 0, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {2, 0, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {2, 0, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {2, 0, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_tx_disable = { {3, 1, 0}, /* map_tx_disable[0] = DIS_QSFP28_P(X) */ + {3, 1, 1}, /* map_tx_disable[1] = DIS_QSFP28_P(X+1) */ + {3, 1, 2}, /* map_tx_disable[2] = DIS_QSFP28_P(X+2) */ + {3, 1, 3}, /* map_tx_disable[3] = DIS_QSFP28_P(X+3) */ + {3, 1, 4}, /* map_tx_disable[4] = DIS_QSFP28_P(X+4) */ + {3, 1, 5}, /* map_tx_disable[5] = DIS_QSFP28_P(X+5) */ + {3, 1, 6}, /* map_tx_disable[6] = DIS_QSFP28_P(X+6) */ + {3, 1, 7}, /* map_tx_disable[7] = DIS_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) */ + }, + .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_rxlos = { {2, 0, 0}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {2, 0, 1}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {2, 0, 2}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {2, 0, 3}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {2, 0, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {2, 0, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {2, 0, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {2, 0, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .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) */ + }, +}; + +struct ioexp_map_s ioexp_map_lavender_p65 = { + .chip_amount = 1, + .data_width = 2, + .map_modsel = { {0, 0, 0} }, /* map_modsel[0] = MODSEL_QSFP28_N_P(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_rxlos = { {0, 0, 3} }, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + .map_present = { {0, 0, 4} }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_tx_disable = { {0, 0, 5} }, /* map_tx_disable[0] = DIS_QSFP28_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; + + /* 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_LAVENDER_P01P08: + return &ioexp_map_lavender_p01p08_p17p24; + case IOEXP_TYPE_LAVENDER_P09P16: + return &ioexp_map_lavender_p09p16_p25p32; + 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; + } + 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_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->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; + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_LAVENDER_P01P08: + case IOEXP_TYPE_LAVENDER_P09P16: + 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_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_LAVENDER_P01P08: + case IOEXP_TYPE_LAVENDER_P09P16: + 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) < 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; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +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; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +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__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +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; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + + +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; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +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"); + 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; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.h new file mode 100644 index 00000000..440d671d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/io_expander.h @@ -0,0 +1,172 @@ +#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_LAVENDER_P01P08 (10208) +#define IOEXP_TYPE_LAVENDER_P09P16 (10209) +#define IOEXP_TYPE_LAVENDER_P65 (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[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_bitmap_s map_hard_rs0[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[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 (*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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..303ffde7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,820 @@ +#include +#include +#include +#include +//#include +#include + +//#include +//#include +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +#if 0 +static unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} +#else +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} +#endif + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %d\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %d\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} +EXPORT_SYMBOL(read_eeprom); + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} +EXPORT_SYMBOL(prog_eeprom); + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} +EXPORT_SYMBOL(tlvinfo_decode_tlv); + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} +EXPORT_SYMBOL(tlvinfo_delete_tlv); + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} +EXPORT_SYMBOL(tlvinfo_add_tlv); + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} +#if 0 +int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf) +{ + int tlv_end; + int curr_tlv; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int iFind = 0; + + if( !is_valid_tlvinfo_header(eeprom_hdr) ) { + printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n"); + return -1; + } + + curr_tlv = sizeof(tlvinfo_header_t); + tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while(curr_tlv < tlv_end){ + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv]; + if (!is_valid_tlv(eeprom_tlv)) { + printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n", + curr_tlv); + return -1; + } + + decode_tlv_value(eeprom_tlv, c_buf); + if( eeprom_tlv->type == i_offset){ + iFind = 1; + break; + } + curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + if( iFind == 0 ) + return -1; + else + return 0; +} +#endif diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..74f3c960 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); +//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.c new file mode 100644 index 00000000..a4a509a8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.c @@ -0,0 +1,8220 @@ +#include +#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); +} +EXPORT_SYMBOL(alarm_msg_2_user); + + +/* ========== 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; +} +EXPORT_SYMBOL(lock_transvr_obj); + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + + +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; //workaround for molex dac 3m cable + } + 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; +} +EXPORT_SYMBOL(create_transvr_obj); + + +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; +} +EXPORT_SYMBOL(isolate_transvr_obj); + + +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; +} +EXPORT_SYMBOL(resync_channel_tier_2); + + +/* ----------------------------------------- + * 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) + */ + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.h new file mode 100644 index 00000000..5eee7db2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/modules/builds/src/transceiver.h @@ -0,0 +1,795 @@ +#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 */ + +/* Lavender chip type define */ +#define CHIP_TYPE_D5264Q28B (31003) /* 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]; + + + /* ========== 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/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/PKG.yml new file mode 100644 index 00000000..276a661a --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d5264q28b ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/lib/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/lib/Makefile new file mode 100644 index 00000000..e2588772 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-inventec-d5264q28b +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_inventec_d5264q28b onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-inventec-d5264q28b.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/onlpdump/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..e6ab65e9 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_inventec_d5264q28b onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/.module b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/.module new file mode 100644 index 00000000..d283bbf2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_inventec_d5264q28b diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/Makefile new file mode 100644 index 00000000..7d78a253 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_inventec_d5264q28b +AUTOMODULE := x86_64_inventec_d5264q28b +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..53e27c6b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_inventec_d5264q28b Autogeneration +# +############################################################################### +x86_64_inventec_d5264q28b_AUTO_DEFS := module/auto/x86_64_inventec_d5264q28b.yml +x86_64_inventec_d5264q28b_AUTO_DIRS := module/inc/x86_64_inventec_d5264q28b module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/x86_64_inventec_d5264q28b.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/x86_64_inventec_d5264q28b.yml new file mode 100644 index 00000000..c1466116 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/auto/x86_64_inventec_d5264q28b.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_inventec_d5264q28b Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB +- x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_inventec_d5264q28b_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_inventec_d5264q28b_config + + portingmacro: + x86_64_inventec_d5264q28b: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b.x b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b.x new file mode 100644 index 00000000..a75d6241 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_config.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_config.h new file mode 100644 index 00000000..a3ee091f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d5264q28b Configuration Header + * + * @addtogroup x86_64_inventec_d5264q28b-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5264q28b_CONFIG_H__ +#define __x86_64_inventec_d5264q28b_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_inventec_d5264q28b_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING +#define x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT +#define x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB +#define x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI +#define x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_inventec_d5264q28b_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_inventec_d5264q28b_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_inventec_d5264q28b_config_settings table. */ +extern x86_64_inventec_d5264q28b_config_settings_t x86_64_inventec_d5264q28b_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_inventec_d5264q28b_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_inventec_d5264q28b_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_inventec_d5264q28b_porting.h" + +#endif /* __x86_64_inventec_d5264q28b_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_dox.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_dox.h new file mode 100644 index 00000000..3d96784d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_inventec_d5264q28b Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5264q28b_DOX_H__ +#define __x86_64_inventec_d5264q28b_DOX_H__ + +/** + * @defgroup x86_64_inventec_d5264q28b x86_64_inventec_d5264q28b - x86_64_inventec_d5264q28b Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_inventec_d5264q28b-x86_64_inventec_d5264q28b Public Interface + * @defgroup x86_64_inventec_d5264q28b-config Compile Time Configuration + * @defgroup x86_64_inventec_d5264q28b-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_inventec_d5264q28b_DOX_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_porting.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_porting.h new file mode 100644 index 00000000..d243b89f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/inc/x86_64_inventec_d5264q28b/x86_64_inventec_d5264q28b_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d5264q28b Porting Macros. + * + * @addtogroup x86_64_inventec_d5264q28b-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5264q28b_PORTING_H__ +#define __x86_64_inventec_d5264q28b_PORTING_H__ + + +/* */ +#if x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_inventec_d5264q28b_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_inventec_d5264q28b_MALLOC GLOBAL_MALLOC + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_MALLOC malloc + #else + #error The macro x86_64_inventec_d5264q28b_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_FREE + #if defined(GLOBAL_FREE) + #define x86_64_inventec_d5264q28b_FREE GLOBAL_FREE + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_FREE free + #else + #error The macro x86_64_inventec_d5264q28b_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_inventec_d5264q28b_MEMSET GLOBAL_MEMSET + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_MEMSET memset + #else + #error The macro x86_64_inventec_d5264q28b_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_inventec_d5264q28b_MEMCPY GLOBAL_MEMCPY + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_MEMCPY memcpy + #else + #error The macro x86_64_inventec_d5264q28b_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_inventec_d5264q28b_STRNCPY GLOBAL_STRNCPY + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_STRNCPY strncpy + #else + #error The macro x86_64_inventec_d5264q28b_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_inventec_d5264q28b_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_VSNPRINTF vsnprintf + #else + #error The macro x86_64_inventec_d5264q28b_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_inventec_d5264q28b_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_SNPRINTF snprintf + #else + #error The macro x86_64_inventec_d5264q28b_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d5264q28b_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_inventec_d5264q28b_STRLEN GLOBAL_STRLEN + #elif x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d5264q28b_STRLEN strlen + #else + #error The macro x86_64_inventec_d5264q28b_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_inventec_d5264q28b_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..c828753b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_inventec_d5264q28b_INCLUDES := -I $(THIS_DIR)inc +x86_64_inventec_d5264q28b_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_inventec_d5264q28b_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d5264q28b ucli:x86_64_inventec_d5264q28b + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..2614feee --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_inventec_d5264q28b_ucli.c + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/debug.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..e72ef0b6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_inventec_d5264q28b_int.h" + +#if x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_inventec_d5264q28b_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..bc6a0bbd --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/fani.c @@ -0,0 +1,398 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +#define SLOW_PWM 100 +#define NORMAL_PWM 175 +#define MAX_PWM 255 +#define STEP_SIZE 100 +#define FAN_ON_MAIN_BOARD_COUNT 4 +#define LOCAL_ID_TO_PSU_ID(id) (id-FAN_ON_MAIN_BOARD_COUNT) + +#define FAN_CAPS ONLP_FAN_CAPS_GET_RPM|ONLP_FAN_CAPS_GET_PERCENTAGE + +static int _fani_status_failed_check(uint32_t* status, int local_id); +static int _fani_status_present_check(uint32_t* status, int local_id); + +#define MAKE_FAN_INFO_NODE_ON_FAN_BOARD(id) \ + { \ + { \ + ONLP_FAN_ID_CREATE(ONLP_FAN_##id), "Fan "#id, 0, \ + { \ + ONLP_LED_ID_CREATE(ONLP_LED_FAN##id), \ + } \ + }, \ + 0, 0 \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id) \ + { \ + { ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_##psu_id), "PSU-"#psu_id" Fan", ONLP_PSU_ID_CREATE(ONLP_PSU_##psu_id)}, \ + 0, 0 \ + } + + +/* Static values */ +static onlp_fan_info_t __onlp_fan_info[ONLP_FAN_COUNT] = { + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_FAN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_PSU(1), + MAKE_FAN_INFO_NODE_ON_PSU(2), +}; + + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rv = ONLP_STATUS_OK; + int local_id; + int lrpm, rrpm, pwm, psu_id; + VALIDATE(id); + pwm = 0; + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + rv = ONLP_STATUS_E_INVALID; + } + if(rv ==ONLP_STATUS_OK) { + *info = __onlp_fan_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + rv = onlp_fani_status_get(id, &info->status); + } + + if(rv == ONLP_STATUS_OK) { + if(info->status & ONLP_FAN_STATUS_PRESENT){ + switch(local_id){ + case ONLP_FAN_1: + case ONLP_FAN_2: + case ONLP_FAN_3: + case ONLP_FAN_4: + if(info->status & ONLP_FAN_STATUS_F2B){ + info->caps = FAN_CAPS|ONLP_FAN_CAPS_F2B; + }else if(info->status & ONLP_FAN_STATUS_B2F){ + info->caps = FAN_CAPS|ONLP_FAN_CAPS_B2F; + }else{ + info->caps = FAN_CAPS; + } + + rv = onlp_file_read_int(&lrpm, INV_HWMON_PREFIX"fan%d_input", local_id*2-1); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int(&rrpm, INV_HWMON_PREFIX"fan%d_input", local_id*2); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int(&pwm,INV_HWMON_PREFIX"pwm%d", local_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + + if(lrpm <=0 && rrpm <=0){ + info->rpm = 0; + }else if(lrpm <= 0){ + info->rpm = rrpm; + }else if(rrpm <= 0){ + info->rpm = lrpm; + }else{ + info->rpm = (lrpm+rrpm)/2; + } + + break; + case ONLP_FAN_PSU_1: + case ONLP_FAN_PSU_2: + info->caps = FAN_CAPS|ONLP_FAN_CAPS_F2B; + psu_id = LOCAL_ID_TO_PSU_ID(local_id); + rv = onlp_file_read_int(&info->rpm,INV_HWMON_PREFIX"rpm_psu%d", psu_id); + if(rv != ONLP_STATUS_OK) { return rv; } + rv = onlp_file_read_int(&pwm, INV_HWMON_PREFIX"pwm_psu%d", psu_id); + if(rv != ONLP_STATUS_OK) { return rv; } + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + if(rv == ONLP_STATUS_OK) { + if(info->rpm <= 0) { + info->mode = ONLP_FAN_MODE_OFF; + info->percentage = 0; + } else { + info->percentage = (pwm*100)/MAX_PWM; + if(pwm < SLOW_PWM) { + info->mode = ONLP_FAN_MODE_SLOW; + } else if(pwm < NORMAL_PWM) { + info->mode = ONLP_FAN_MODE_NORMAL; + } else if(pwm < MAX_PWM) { + info->mode = ONLP_FAN_MODE_FAST; + } else { + info->mode = ONLP_FAN_MODE_MAX; + } + } + } + }else{ + info->caps = 0; + info->rpm = 0; + info->percentage = 0; + info->mode = ONLP_FAN_MODE_OFF; + } + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + } + return rv; +} +static int _fani_status_failed_check(uint32_t* status, int local_id) +{ + int rv; + int lrpm, rrpm, rpm, pwm, psu_id; + switch(local_id){ + case ONLP_FAN_1: + case ONLP_FAN_2: + case ONLP_FAN_3: + case ONLP_FAN_4: + rv = onlp_file_read_int(&lrpm, INV_HWMON_PREFIX"fan%d_input", local_id*2-1); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int(&rrpm, INV_HWMON_PREFIX"fan%d_input", local_id*2); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int(&pwm,INV_HWMON_PREFIX"pwm%d", local_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + + if( lrpm <= 0 || rrpm <=0 || pwm <=0 || pwm > MAX_PWM){ + *status |= ONLP_FAN_STATUS_FAILED; + *status &= (~ONLP_FAN_STATUS_B2F); + *status &= (~ONLP_FAN_STATUS_F2B); + }else{ + *status &= (~ONLP_FAN_STATUS_FAILED); + } + break; + case ONLP_FAN_PSU_1: + case ONLP_FAN_PSU_2: + psu_id = LOCAL_ID_TO_PSU_ID(local_id); + rv = onlp_file_read_int(&rpm, INV_HWMON_PREFIX"rpm_psu%d", psu_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int(&pwm, INV_HWMON_PREFIX"pwm_psu%d", psu_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + + if( rpm <= 0 || pwm <=0 || pwm > MAX_PWM){ + *status |= ONLP_FAN_STATUS_FAILED; + *status &= (~ONLP_FAN_STATUS_B2F); + *status &= (~ONLP_FAN_STATUS_F2B); + }else{ + *status &= (~ONLP_FAN_STATUS_FAILED); + } + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + return rv; +} + +static int _fani_status_present_check(uint32_t* status, int local_id) +{ + int rv; + int gpi; + int info_idx; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + info_idx = LOCAL_ID_TO_INFO_IDX(local_id); + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_HWMON_PREFIX"fan_gpi"); + if( rv == ONLP_STATUS_OK ){ + sscanf( buf, "0x%x\n", &gpi); + /* B[0-3] installed(0)/uninstalled(1) + B[4-7] FRtype(0)/RFtype(1) */ + if (!((gpi>>info_idx) & 1)){ + *status |= ONLP_FAN_STATUS_PRESENT; + if (!((gpi>>(info_idx+4)) & 1)){ + *status |= ONLP_FAN_STATUS_F2B; + }else{ + *status |= ONLP_FAN_STATUS_B2F; + } + } else { + *status = 0; + } + } + return rv; +} + + +/** + * @brief Retrieve the fan's operational status. + * @param id The fan OID. + * @param rv [out] Receives the fan's operations status flags. + * @notes Only operational state needs to be returned - + * PRESENT/FAILED + */ +int onlp_fani_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_fan_info_t* info; + int local_id; + VALIDATE(id); + uint32_t psu_status; + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_fan_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + switch(local_id){ + case ONLP_FAN_1: + case ONLP_FAN_2: + case ONLP_FAN_3: + case ONLP_FAN_4: + result = _fani_status_present_check(&info->status, local_id); + if (result == ONLP_STATUS_OK ){ + if (info->status & ONLP_FAN_STATUS_PRESENT){ + result = _fani_status_failed_check(&info->status, local_id); + } + } + break; + case ONLP_FAN_PSU_1: + case ONLP_FAN_PSU_2: + result = onlp_psui_status_get((&info->hdr)->poid, &psu_status); + if(result != ONLP_STATUS_OK){ return result; } + + if(psu_status & ONLP_PSU_STATUS_PRESENT){ + info->status |= ONLP_FAN_STATUS_PRESENT; + result = _fani_status_failed_check(&info->status, local_id); + }else{ + info->status = 0; + } + break; + default: + result = ONLP_STATUS_E_INVALID; + break; + } + *rv = info->status; + } + return result; +} + +/** + * @brief Retrieve the fan's OID hdr. + * @param id The fan OID. + * @param rv [out] Receives the OID header. + */ +int onlp_fani_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* hdr) +{ + int result = ONLP_STATUS_OK; + onlp_fan_info_t* info; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_FAN_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_fan_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + *hdr = info->hdr; + } + return result; +} + + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..bda4629c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,441 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ + +/* CAPS*/ +#define SYS_LED_CAPS ONLP_LED_CAPS_ON_OFF|ONLP_LED_CAPS_GREEN|ONLP_LED_CAPS_GREEN_BLINKING|ONLP_LED_CAPS_RED|ONLP_LED_CAPS_RED_BLINKING +#define FAN_LED_CAPS ONLP_LED_CAPS_RED|ONLP_LED_CAPS_GREEN + +#define LOCAL_ID_TO_FAN_ID(id) (id-1) + +typedef enum sys_led_mode_e { + SYS_LED_MODE_OFF = 0, + SYS_LED_MODE_0_5_HZ = 1, + SYS_LED_MODE_1_HZ = 2, + SYS_LED_MODE_2_HZ = 3, + SYS_LED_MODE_ON = 7 +} sys_led_mode_t; + +/* function declarations*/ +static int _sys_onlp_led_mode_convert(sys_led_mode_t grn_mode, sys_led_mode_t red_mode, onlp_led_mode_t* pmode); +static int _sys_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info); +static int _fan_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info); +static int _sys_onlp_ledi_mode_set(onlp_led_mode_t onlp_mode); + +/* + * Get the information for the given LED OID. + */ +#define MAKE_MGMT_LED_INFO_NODE \ + { \ + { ONLP_LED_ID_CREATE(ONLP_LED_MGMT), "MGMT LED" , 0 }, \ + ONLP_LED_STATUS_PRESENT, \ + SYS_LED_CAPS, \ + } + +#define MAKE_LED_INFO_NODE_ON_FAN(fan_id) \ + { \ + { ONLP_LED_ID_CREATE(ONLP_LED_FAN##fan_id), \ + "FAN LED "#fan_id, \ + ONLP_FAN_ID_CREATE(ONLP_FAN_##fan_id) \ + }, \ + 0, \ + 0, \ + } + +static onlp_led_info_t __onlp_led_info[ONLP_LED_COUNT] = { + MAKE_MGMT_LED_INFO_NODE, + MAKE_LED_INFO_NODE_ON_FAN(1), + MAKE_LED_INFO_NODE_ON_FAN(2), + MAKE_LED_INFO_NODE_ON_FAN(3), + MAKE_LED_INFO_NODE_ON_FAN(4), +}; + + + +/* convert platform led type to onlp_led_mode type*/ +static int _sys_onlp_led_mode_convert(sys_led_mode_t grn_mode, sys_led_mode_t red_mode, onlp_led_mode_t* pmode) +{ + int rv = ONLP_STATUS_OK; + *pmode = ONLP_LED_MODE_OFF; + + switch(grn_mode) { + case SYS_LED_MODE_0_5_HZ: + case SYS_LED_MODE_1_HZ: + case SYS_LED_MODE_2_HZ: + *pmode = ONLP_LED_MODE_GREEN_BLINKING; + break; + case SYS_LED_MODE_ON: + *pmode = ONLP_LED_MODE_GREEN; + break; + case SYS_LED_MODE_OFF: + *pmode = ONLP_LED_MODE_OFF; + break; + default: + return ONLP_STATUS_E_INVALID; + break; + } + switch(red_mode) { + case SYS_LED_MODE_0_5_HZ: + case SYS_LED_MODE_1_HZ: + case SYS_LED_MODE_2_HZ: + if(grn_mode == SYS_LED_MODE_OFF){ + *pmode = ONLP_LED_MODE_RED_BLINKING; + }else{ + return ONLP_STATUS_E_INVALID; + } + break; + case SYS_LED_MODE_ON: + if(grn_mode == SYS_LED_MODE_OFF){ + *pmode = ONLP_LED_MODE_RED; + }else{ + return ONLP_STATUS_E_INVALID; + } + break; + case SYS_LED_MODE_OFF: + if(grn_mode == SYS_LED_MODE_OFF){ + *pmode = ONLP_LED_MODE_OFF; + } + break; + default: + return ONLP_STATUS_E_INVALID; + break; + } + return rv; +} + + +static int _sys_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + sys_led_mode_t grn_mode, red_mode; + local_id = ONLP_OID_ID_GET(id); + int idx = LOCAL_ID_TO_INFO_IDX(local_id); + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_led_info[idx]; + + rv = onlp_file_read_int((int*)&grn_mode, INV_SYSLED_PREFIX"grn_led"); + if(rv != ONLP_STATUS_OK){ return rv; } + rv = onlp_file_read_int((int*)&red_mode, INV_SYSLED_PREFIX"red_led"); + if(rv != ONLP_STATUS_OK){ return rv; } + + rv = _sys_onlp_led_mode_convert(grn_mode, red_mode, &info->mode); + if(rv != ONLP_STATUS_OK){ return rv; } + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } else { + info->status &= (~ONLP_LED_STATUS_ON); + } + + + return rv; +} + +static int _fan_onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + int rv = ONLP_STATUS_OK; + int grn_mode, red_mode; + + local_id = ONLP_OID_ID_GET(id); + int fan_id = LOCAL_ID_TO_FAN_ID(local_id); + int idx = LOCAL_ID_TO_INFO_IDX(local_id); + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_led_info[idx]; + + rv = onlp_ledi_status_get(id, &info->status); + if( rv != ONLP_STATUS_OK ){ return rv; } + + if( info->status & ONLP_LED_STATUS_PRESENT){ + info->caps = FAN_LED_CAPS; + rv = onlp_file_read_int((int*)&grn_mode, INV_HWMON_PREFIX"fan_led_grn%d", fan_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_read_int((int*)&red_mode, INV_HWMON_PREFIX"fan_led_red%d", fan_id); + if(rv != ONLP_STATUS_OK ){ return rv; } + + if(grn_mode == 1 && red_mode == 0){ + info->mode = ONLP_LED_MODE_GREEN; + }else if(grn_mode == 0 && red_mode == 1){ + info->mode = ONLP_LED_MODE_RED; + }else if(grn_mode == 0 && red_mode == 0){ + info->mode = ONLP_LED_MODE_OFF; + }else{ + rv = ONLP_STATUS_E_INVALID; + } + }else{ + info->mode = ONLP_LED_MODE_OFF; + } + return rv; +} + +static int _sys_onlp_ledi_mode_set(onlp_led_mode_t onlp_mode) +{ + int rv = ONLP_STATUS_OK; + + if( onlp_mode == ONLP_LED_MODE_OFF){ + rv = onlp_file_write_int(SYS_LED_MODE_OFF, INV_SYSLED_PREFIX"grn_led"); + if(rv != ONLP_STATUS_OK ){ return rv; } + rv = onlp_file_write_int(SYS_LED_MODE_OFF, INV_SYSLED_PREFIX"red_led"); + }else{ + rv = ONLP_STATUS_E_UNSUPPORTED; + } + return rv; +} + + + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int rv = ONLP_STATUS_OK; + VALIDATE(id); + int local_id; + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + + switch(local_id) { + case ONLP_LED_MGMT: + rv = _sys_onlp_ledi_info_get(id, info); + break; + case ONLP_LED_FAN1: + case ONLP_LED_FAN2: + case ONLP_LED_FAN3: + case ONLP_LED_FAN4: + rv = _fan_onlp_ledi_info_get(id, info); + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + return rv; +} + +/** + * @brief Get the LED operational status. + * @param id The LED OID + * @param rv [out] Receives the operational status. + */ +int onlp_ledi_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_led_info_t* info; + + VALIDATE(id); + int local_id = ONLP_OID_ID_GET(id); + int info_idx = LOCAL_ID_TO_INFO_IDX(local_id); + int fan_id = LOCAL_ID_TO_FAN_ID(local_id); + int mode, grn_mode, red_mode; + onlp_led_mode_t pmode; + uint32_t fan_status; + + if(local_id >= ONLP_LED_MAX) { + result = ONLP_STATUS_E_INVALID; + } + if(result == ONLP_STATUS_OK) { + info = &__onlp_led_info[info_idx]; + switch(local_id) { + case ONLP_LED_MGMT: + result = onlp_file_read_int((int*)&grn_mode, INV_SYSLED_PREFIX"grn_led"); + if(result != ONLP_STATUS_OK){ return result; } + result = onlp_file_read_int((int*)&red_mode, INV_SYSLED_PREFIX"red_led"); + if(result != ONLP_STATUS_OK){ return result; } + + result = _sys_onlp_led_mode_convert(grn_mode, red_mode, &pmode); + if(result != ONLP_STATUS_OK){ return result; } + + if( pmode != ONLP_LED_MODE_OFF){ + info->status |= ONLP_LED_STATUS_ON; + }else{ + info->status &= (~ONLP_LED_STATUS_ON); + } + + *rv = info->status; + break; + case ONLP_LED_FAN1: + case ONLP_LED_FAN2: + case ONLP_LED_FAN3: + case ONLP_LED_FAN4: + result = onlp_fani_status_get((&info->hdr)->poid, &fan_status); + if(result != ONLP_STATUS_OK){ return result; } + + if(fan_status & ONLP_FAN_STATUS_PRESENT){ + info->status |= ONLP_LED_STATUS_PRESENT; + info->status &= (~ONLP_LED_STATUS_ON); + + result = onlp_file_read_int((int*)&mode, INV_HWMON_PREFIX"fan_led_grn%d", fan_id); + if(result != ONLP_STATUS_OK){ return result; } + if(mode){ + info->status |= ONLP_LED_STATUS_ON; + } + + result = onlp_file_read_int((int*)&mode, INV_HWMON_PREFIX"fan_led_red%d", fan_id); + if(result != ONLP_STATUS_OK){ return result; } + if(mode){ + info->status |= ONLP_LED_STATUS_ON; + } + } else { + info->status = 0; + } + *rv = info->status; + break; + default: + result = ONLP_STATUS_E_INVALID; + break; + } + } + + return result; +} + +/** + * @brief Get the LED header. + * @param id The LED OID + * @param rv [out] Receives the header. + */ +int onlp_ledi_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_led_info_t* info; + + VALIDATE(id); + + int local_id; + local_id = ONLP_OID_ID_GET(id); + int idx = LOCAL_ID_TO_INFO_IDX(local_id); + if(local_id >= ONLP_LED_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_led_info[idx]; + *rv = info->hdr; + } + return result; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + onlp_led_mode_t mode; + VALIDATE(id); + int local_id; + local_id = ONLP_OID_ID_GET(id); + int idx = LOCAL_ID_TO_INFO_IDX(local_id); + + if(local_id >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + + if (__onlp_led_info[idx].caps & ONLP_LED_CAPS_ON_OFF) { + mode = on_or_off?ONLP_LED_MODE_ON:ONLP_LED_MODE_OFF; + return onlp_ledi_mode_set(id, mode); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int rv = ONLP_STATUS_OK; + VALIDATE(id); + int local_id; + local_id = ONLP_OID_ID_GET(id); + + if(local_id >= ONLP_LED_MAX) { + return ONLP_STATUS_E_INVALID; + } + switch(local_id) { + case ONLP_LED_MGMT: + rv = _sys_onlp_ledi_mode_set(mode); + break; + case ONLP_LED_FAN1: + case ONLP_LED_FAN2: + case ONLP_LED_FAN3: + case ONLP_LED_FAN4: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + default: + rv = ONLP_STATUS_E_INVALID; + break; + } + + return rv; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..5db38681 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_inventec_d5264q28b +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..bb04678b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,50 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + + +int platform_hwmon_diag_enable_read(int *enable) +{ + int rv = ONLP_STATUS_OK; + rv = onlp_file_read_int((int*)enable, INV_HWMON_PREFIX"diag"); + return rv; +} + + +int platform_hwmon_diag_enable_write(int enable) +{ + int rv = ONLP_STATUS_OK; + rv = onlp_file_write_int(enable, INV_HWMON_PREFIX"diag"); + return rv; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..a3405d8c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,138 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_inventec_d5264q28b_log.h" + +/* This is definitions for x86-64-inventec-d5264q28b*/ +/* OID map*/ +/* + * SYS---------ONLP_THERMAL_CPU_PHY + * |----ONLP_THERMAL_CPU_CORE0 + * |----ONLP_THERMAL_CPU_CORE1 + * |----ONLP_THERMAL_CPU_CORE2 + * |----ONLP_THERMAL_CPU_CORE3 + * |----ONLP_THERMAL_1_ON_MAIN_BROAD + * |----ONLP_THERMAL_2_ON_MAIN_BROAD + * |----ONLP_THERMAL_3_ON_MAIN_BROAD + * |----ONLP_THERMAL_4_ON_MAIN_BROAD + * |----ONLP_THERMAL_5_ON_MAIN_BROAD + * |----ONLP_FAN_1--------ONLP_LED_FAN1 + * | + * |----ONLP_FAN_2--------ONLP_LED_FAN2 + * | + * |----ONLP_FAN_3--------ONLP_LED_FAN3 + * | + * |----ONLP_FAN_4--------ONLP_LED_FAN4 + * | + * |----ONLP_PSU_1--------ONLP_THERMAL_1_ON_PSU1 + * | |--ONLP_THERMAL_2_ON_PSU1 + * | |--ONLP_FAN_PSU_1 + * | + * |----ONLP_PSU_2--------ONLP_THERMAL_1_ON_PSU2 + * | |--ONLP_THERMAL_2_ON_PSU2 + * | |--ONLP_FAN_PSU_2 + * | + * |----ONLP_LED_MGMT + */ + +#define INV_SYSLED_PREFIX "/sys/class/hwmon/hwmon2/device/" +#define INV_HWMON_PREFIX "/sys/class/hwmon/hwmon1/device/" +#define INV_CTMP_PREFIX "/sys/class/hwmon/hwmon0/" +#define INV_SFP_PREFIX "/sys/class/swps/" +#define INV_SYS_PREFIX "/sys/class/eeprom/vpd/" + +#define OID_MAP_TO_INFO_IDX(oid) ONLP_OID_ID_GET(oid)-1 +#define LOCAL_ID_TO_INFO_IDX(id) (id-1) + +/* Thermal definitions*/ +enum onlp_thermal_id { + ONLP_THERMAL_CPU_PHY = 1, + ONLP_THERMAL_CPU_CORE0, + ONLP_THERMAL_CPU_CORE1, + ONLP_THERMAL_CPU_CORE2, + ONLP_THERMAL_CPU_CORE3, + ONLP_THERMAL_1_ON_MAIN_BROAD, + ONLP_THERMAL_2_ON_MAIN_BROAD, + ONLP_THERMAL_3_ON_MAIN_BROAD, + ONLP_THERMAL_4_ON_MAIN_BROAD, + ONLP_THERMAL_5_ON_MAIN_BROAD, + ONLP_THERMAL_1_ON_PSU1, + ONLP_THERMAL_2_ON_PSU1, + ONLP_THERMAL_1_ON_PSU2, + ONLP_THERMAL_2_ON_PSU2, + ONLP_THERMAL_MAX +}; + +#define ONLP_THERMAL_COUNT 14 /*include "reserved"*/ + +/* Fan definitions*/ +enum onlp_fan_id { + ONLP_FAN_1 = 1, + ONLP_FAN_2, + ONLP_FAN_3, + ONLP_FAN_4, + ONLP_FAN_PSU_1, + ONLP_FAN_PSU_2, + ONLP_FAN_MAX +}; + +#define ONLP_FAN_COUNT 6 /*include "reserved"*/ + +/* PSU definitions*/ +enum onlp_psu_id { + ONLP_PSU_1 = 1, + ONLP_PSU_2, + ONLP_PSU_MAX +}; + +#define ONLP_PSU_COUNT 2 /*include "reserved"*/ + +/* LED definitions*/ +enum onlp_led_id { + ONLP_LED_MGMT = 1, + ONLP_LED_FAN1, + ONLP_LED_FAN2, + ONLP_LED_FAN3, + ONLP_LED_FAN4, + ONLP_LED_MAX +}; + +#define ONLP_LED_COUNT 5 /*include "reserved"*/ + + +/* platform functions*/ +#define PLATFORM_HWMON_DIAG_LOCK platform_hwmon_diag_enable_write(0) +#define PLATFORM_HWMON_DIAG_UNLOCK platform_hwmon_diag_enable_write(1) +int platform_hwmon_diag_enable_read(int *enable); +int platform_hwmon_diag_enable_write(int enable); + + + + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..1c260d22 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/psui.c @@ -0,0 +1,215 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" +#include +#include + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +typedef enum hwmon_psu_state_e { + HWMON_PSU_NORMAL = 0, + HWMON_PSU_UNPOWERED = 2, //010 + HWMON_PSU_FAULT = 4, //100 + HWMON_PSU_NOT_INSTALLED = 7 //111 +} hwmon_psu_state_t; + +/* + * Get all information about the given PSU oid. + */ +#define MAKE_PSU_NODE_INFO(id) \ + { \ + { \ + ONLP_PSU_ID_CREATE(ONLP_PSU_##id), "PSU-"#id, 0, \ + { \ + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_1_ON_PSU##id), \ + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_2_ON_PSU##id), \ + ONLP_FAN_ID_CREATE(ONLP_FAN_PSU_##id) \ + } \ + }, \ + "","", 0, 0 \ + } + +static onlp_psu_info_t __onlp_psu_info[ONLP_PSU_COUNT] = { + MAKE_PSU_NODE_INFO(1), + MAKE_PSU_NODE_INFO(2) +}; + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int ret = ONLP_STATUS_OK; + int len; + int local_id = ONLP_OID_ID_GET(id); + uint8_t temp[ONLP_CONFIG_INFO_STR_MAX] = {0}; + + VALIDATE(id); + + if(local_id >= ONLP_PSU_MAX) { + return ONLP_STATUS_E_INVALID; + } + + + *info = __onlp_psu_info[LOCAL_ID_TO_INFO_IDX(local_id)]; /* Set the onlp_oid_hdr_t */ + + ret = onlp_file_read(temp, ONLP_CONFIG_INFO_STR_MAX, &len, INV_HWMON_PREFIX"psoc_psu%d_vender", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + /*remove the '\n'*/ + temp[strlen((char*)temp)-1] = 0; + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "%s", temp); + + + memset(temp, 0, ONLP_CONFIG_INFO_STR_MAX); + ret = onlp_file_read(temp, ONLP_CONFIG_INFO_STR_MAX, &len, INV_HWMON_PREFIX"psoc_psu%d_serial", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + /*remove the '\n'*/ + temp[strlen((char*)temp)-1] = 0; + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "%s", temp); + + ret = onlp_psui_status_get(id, &info->status); + if(ret != ONLP_STATUS_OK){ return ret; } + + if(info->status & ONLP_PSU_STATUS_PRESENT){ + info->caps = ONLP_PSU_CAPS_AC; + /*millivolts*/ + ret = onlp_file_read_int(&info->mvin, INV_HWMON_PREFIX"psoc_psu%d_vin", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->mvin >= 0){ + info->caps |= ONLP_PSU_CAPS_VIN; + } + ret = onlp_file_read_int(&info->mvout, INV_HWMON_PREFIX"psoc_psu%d_vout", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->mvout >= 0){ + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + /* milliamps */ + ret = onlp_file_read_int(&info->miin, INV_HWMON_PREFIX"psoc_psu%d_iin", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->miin >= 0){ + info->caps |= ONLP_PSU_CAPS_IIN; + } + ret = onlp_file_read_int(&info->miout, INV_HWMON_PREFIX"psoc_psu%d_iout", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->miout >= 0){ + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + /* milliwatts */ + ret = onlp_file_read_int(&info->mpin, INV_HWMON_PREFIX"psoc_psu%d_pin", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->mpin >= 0){ + info->caps |= ONLP_PSU_CAPS_PIN; + } + ret = onlp_file_read_int(&info->mpout, INV_HWMON_PREFIX"psoc_psu%d_pout", local_id); + if(ret != ONLP_STATUS_OK){ return ret; } + if(info->mpout >= 0){ + info->caps |= ONLP_PSU_CAPS_POUT; + } + } + return ret; +} + + +/** + * @brief Get the PSU's operational status. + * @param id The PSU OID. + * @param rv [out] Receives the operational status. + */ +int onlp_psui_status_get(onlp_oid_t id, uint32_t* rv) +{ + int result = ONLP_STATUS_OK; + hwmon_psu_state_t psu_state; + int local_id; + VALIDATE(id); + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_PSU_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + result = onlp_file_read((uint8_t*)&buf, ONLP_CONFIG_INFO_STR_MAX, &len, "%s""psu%d", INV_HWMON_PREFIX, local_id-1); + if( result != ONLP_STATUS_OK ){return result;} + psu_state = (uint8_t)strtoul(buf, NULL, 0); + if( psu_state == HWMON_PSU_UNPOWERED) { + *rv = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_UNPLUGGED; + } else if ( psu_state == HWMON_PSU_NORMAL) { + *rv = ONLP_PSU_STATUS_PRESENT; + } else if( psu_state == HWMON_PSU_FAULT) { + *rv = ONLP_PSU_STATUS_PRESENT|ONLP_PSU_STATUS_FAILED; + } else if( psu_state == HWMON_PSU_NOT_INSTALLED){ + *rv = 0; + } else{ + result = ONLP_STATUS_E_INVALID; + } + } + return result; +} + +/** + * @brief Get the PSU's oid header. + * @param id The PSU OID. + * @param rv [out] Receives the header. + */ +int onlp_psui_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int result = ONLP_STATUS_OK; + onlp_psu_info_t* info; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_PSU_MAX) { + result = ONLP_STATUS_E_INVALID; + } else { + info = &__onlp_psu_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + *rv = info->hdr; + } + return result; +} + + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..a632f769 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,314 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ + +#include +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include + +#define MAX_SFP_PATH 128 + +#define MUX_START_INDEX 17 +#define QSFP_DEV_ADDR 0x50 +#define NUM_OF_QSFP_PORT 64 +#define NUM_OF_ALL_PORT (NUM_OF_QSFP_PORT) + +#define FRONT_PORT_TO_MUX_INDEX(port) (port+MUX_START_INDEX) +#define VALIDATE_PORT(p) { if ((p < 0) || (p >= NUM_OF_ALL_PORT)) return ONLP_STATUS_E_PARAM; } +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int onlp_sfpi_port_map(int port, int* rport) +{ + VALIDATE_PORT(port); + *rport = port; + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 63} + */ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 0; p < NUM_OF_ALL_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + VALIDATE_PORT(port); + int present; + int rv; + if(onlp_file_read_int(&present, INV_SFP_PREFIX"port%d/present", port) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + if(present == 0){ + rv = 1; + } else if (present == 1){ + rv = 0; + } + else { + AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port); + return ONLP_STATUS_E_INTERNAL; + } + return rv; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + AIM_BITMAP_CLR_ALL(dst); + int port; + for(port = 0; port < NUM_OF_ALL_PORT; port++){ + if(onlp_sfpi_is_present(port) == 1){ + AIM_BITMAP_MOD(dst, port, 1); + }else if(onlp_sfpi_is_present(port) == 0){ + AIM_BITMAP_MOD(dst, port, 0); + }else{ + return ONLP_STATUS_E_INTERNAL; + } + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_rx_los(int port) +{ + int rxlos; + int rv; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + if(port > NUM_OF_ALL_PORT){ + return ONLP_STATUS_E_INVALID; + } + if(onlp_sfpi_is_present(port) == 0){ + return ONLP_STATUS_E_INVALID; + } + if(onlp_file_read((uint8_t*)buf, ONLP_CONFIG_INFO_STR_MAX, &len, INV_SFP_PREFIX"port%d/soft_rx_los", port) != ONLP_STATUS_OK){ + return ONLP_STATUS_E_INTERNAL; + } + if(sscanf( buf, "0x%x\n", &rxlos) != 1){ + AIM_LOG_ERROR("Unable to read rxlos from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if(rxlos < 0 || rxlos > 0x0f){ + AIM_LOG_ERROR("Unable to read rxlos from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + }else if(rxlos == 0){ + rv = 1; + }else{ + rv = 0; + } + return rv; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + AIM_BITMAP_CLR_ALL(dst); + int port; + int isrxlos; + for(port = 0; port < NUM_OF_ALL_PORT; port++){ + if(onlp_sfpi_is_present(port) == 1){ + isrxlos = onlp_sfpi_is_rx_los(port); + if(isrxlos == 1){ + AIM_BITMAP_MOD(dst, port, 1); + }else if(isrxlos == 0){ + AIM_BITMAP_MOD(dst, port, 0); + }else{ + return ONLP_STATUS_E_INTERNAL; + } + } + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_post_insert(int port, sff_info_t* info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + memset(data, 0, 256); + + VALIDATE_PORT(port); + int sts; + int bus = FRONT_PORT_TO_MUX_INDEX(port); + sts = onlp_i2c_read(bus, QSFP_DEV_ADDR, 0, 256, data, ONLP_I2C_F_FORCE); + if(sts < 0){ + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_MISSING; + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + VALIDATE_PORT(port); + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + VALIDATE_PORT(port); + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + VALIDATE_PORT(port); + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + VALIDATE_PORT(port); + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + *rv = 0; + if(port >= 0 && port < NUM_OF_QSFP_PORT){ + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + case ONLP_SFP_CONTROL_LP_MODE: + *rv = 1; + break; + default: + break; + } + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int ret = ONLP_STATUS_E_UNSUPPORTED; + if(port >= 0 && port < NUM_OF_QSFP_PORT){ + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + ret = onlp_file_write_int(value, INV_SFP_PREFIX"port%d/reset", port); + break; + case ONLP_SFP_CONTROL_LP_MODE: + ret = onlp_file_write_int(value, INV_SFP_PREFIX"port%d/lpmod", port); + break; + default: + break; + } + } + return ret; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int ret = ONLP_STATUS_E_UNSUPPORTED; + if(port >= 0 && port < NUM_OF_QSFP_PORT){ + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + ret = onlp_file_read_int(value, INV_SFP_PREFIX"port%d/reset", port); + break; + case ONLP_SFP_CONTROL_LP_MODE: + ret = onlp_file_read_int(value, INV_SFP_PREFIX"port%d/lpmod", port); + break; + default: + break; + } + } + return ret; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + +void +onlp_sfpi_debug(int port, aim_pvs_t* pvs) +{ + aim_printf(pvs, "Debug data for port %d goes here.", port); +} + +int +onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..602f9632 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,426 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "x86_64_inventec_d5264q28b_int.h" +#include "x86_64_inventec_d5264q28b_log.h" + +#include "platform_lib.h" + +#define SYSI_ONIE_TYPE_SUPPORT_NUM 17 +#define SYSI_PLATFORM_INFO_TYPE_STR_MAX 10 +#define SYSI_PLATFORM_INFO_NUM 2 + +/** + * The TLV Types. + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +static uint8_t __tlv_code_list[SYSI_ONIE_TYPE_SUPPORT_NUM] = { + TLV_CODE_PRODUCT_NAME, + TLV_CODE_PART_NUMBER, + TLV_CODE_SERIAL_NUMBER, + TLV_CODE_MAC_BASE, + TLV_CODE_MANUF_DATE, + TLV_CODE_DEVICE_VERSION, + TLV_CODE_LABEL_REVISION, + TLV_CODE_PLATFORM_NAME, + TLV_CODE_ONIE_VERSION, + TLV_CODE_MAC_SIZE, + TLV_CODE_MANUF_NAME, + TLV_CODE_MANUF_COUNTRY, + TLV_CODE_VENDOR_NAME, + TLV_CODE_DIAG_VERSION, + TLV_CODE_SERVICE_TAG, + TLV_CODE_VENDOR_EXT, + TLV_CODE_CRC_32 +}; + + +static int _sysi_version_parsing(char* file_str, char* str_buf, char* version); +static void _case_tlv_code_string(onlp_onie_info_t* info, char** member, char* path); +static int _parse_tlv(onlp_onie_info_t* info, uint8_t type); + +static int _sysi_version_parsing(char* file_str, char* str_buf, char* version) +{ + int rv = ONLP_STATUS_OK; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX*4]; + char *temp; + + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX*4, &len, file_str); + if( rv != ONLP_STATUS_OK ) { return rv; } + + temp = strstr(buf, str_buf); + if(temp) { + temp += strlen(str_buf); + snprintf(version,ONLP_CONFIG_INFO_STR_MAX, temp); + /*remove '\n'*/ + version[strlen(version)-1] = '\0'; + } else { + rv = ONLP_STATUS_E_MISSING; + } + return rv; +} + +static void _case_tlv_code_string(onlp_onie_info_t* info, char** member, char* path) +{ + int rv = ONLP_STATUS_OK; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, path); + if( rv == ONLP_STATUS_OK ) { + info->_hdr_length += 2; + buf[strlen(buf)-1] = '\0'; + *member = aim_fstrdup("%s",buf); + info->_hdr_length += strlen(*member); + } else { + *member = aim_zmalloc(1); + rv = ONLP_STATUS_OK; + } + return; +} + + +static int _parse_tlv(onlp_onie_info_t* info, uint8_t type) +{ + int rv = ONLP_STATUS_OK; + int len; + char buf[ONLP_CONFIG_INFO_STR_MAX]; + switch(type) + { + case TLV_CODE_PRODUCT_NAME: + _case_tlv_code_string(info, &(info->product_name), INV_SYS_PREFIX"product_name"); + break; + case TLV_CODE_PART_NUMBER: + _case_tlv_code_string(info, &(info->part_number), INV_SYS_PREFIX"pn"); + break; + case TLV_CODE_SERIAL_NUMBER: + _case_tlv_code_string(info, &(info->serial_number), INV_SYS_PREFIX"sn"); + break; + case TLV_CODE_MANUF_DATE: + _case_tlv_code_string(info, &(info->manufacture_date), INV_SYS_PREFIX"man_date"); + break; + case TLV_CODE_LABEL_REVISION: + _case_tlv_code_string(info, &(info->label_revision), INV_SYS_PREFIX"label_rev"); + break; + case TLV_CODE_PLATFORM_NAME: + _case_tlv_code_string(info, &(info->platform_name), INV_SYS_PREFIX"plat_name"); + break; + case TLV_CODE_ONIE_VERSION: + _case_tlv_code_string(info, &(info->onie_version), INV_SYS_PREFIX"ldr_ver"); + break; + case TLV_CODE_MANUF_NAME: + _case_tlv_code_string(info, &(info->manufacturer), INV_SYS_PREFIX"manufacturer"); + break; + case TLV_CODE_MANUF_COUNTRY: + _case_tlv_code_string(info, &(info->country_code), INV_SYS_PREFIX"country_code"); + break; + case TLV_CODE_VENDOR_NAME: + _case_tlv_code_string(info, &(info->vendor), INV_SYS_PREFIX"vendor_name"); + break; + case TLV_CODE_SERVICE_TAG: + _case_tlv_code_string(info, &(info->service_tag), INV_SYS_PREFIX"service_tag"); + break; + case TLV_CODE_DIAG_VERSION: + _case_tlv_code_string(info, &(info->diag_version), INV_SYS_PREFIX"diag_ver"); + break; + + case TLV_CODE_MAC_BASE: + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_SYS_PREFIX"base_mac_addr" ); + if( rv == ONLP_STATUS_OK ) { + if(sscanf( buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n", + &info->mac[0], &info->mac[1], &info->mac[2], + &info->mac[3], &info->mac[4], &info->mac[5]) == 6) { + info->_hdr_length += 2; + info->_hdr_length += 6; + } else { + /*parsing fail*/ + memset(info->mac, 0, 6); + } + } else { + memset(info->mac, 0, 6); + rv = ONLP_STATUS_OK; + } + break; + + case TLV_CODE_DEVICE_VERSION: + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_SYS_PREFIX"dev_ver"); + if( rv == ONLP_STATUS_OK ) { + info->_hdr_length += 2; + info->device_version= (uint8_t)strtoul(buf, NULL, 0); + info->_hdr_length += 1; + }else{ + info->device_version = 0; + rv = ONLP_STATUS_OK; + } + break; + case TLV_CODE_MAC_SIZE: + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_SYS_PREFIX"mac_addr"); + if( rv == ONLP_STATUS_OK ) { + info->_hdr_length += 2; + info->mac_range = (uint16_t)strtoul(buf, NULL, 0); + info->_hdr_length += 2; + }else{ + info->mac_range = 0; + rv = ONLP_STATUS_OK; + } + break; + + case TLV_CODE_VENDOR_EXT: + list_init(&info->vx_list); + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_SYS_PREFIX"vendor_ext"); + if( rv == ONLP_STATUS_OK ) { + /*TODO*/ + } + rv = ONLP_STATUS_OK; + break; + + case TLV_CODE_CRC_32: + rv = onlp_file_read((uint8_t*)buf,ONLP_CONFIG_INFO_STR_MAX, &len, INV_SYS_PREFIX"crc32"); + if( rv == ONLP_STATUS_OK ) { + info->_hdr_length += 2; + info->crc = (uint32_t)strtoul(buf, NULL, 0); + info->_hdr_length += 4; + }else{ + info->crc = 0; + rv = ONLP_STATUS_OK; + } + break; + + default: + break; + } + return rv; +} + + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-inventec-d5264q28b-r0"; +} + + +/* + * This function is called to return the physical base address + * of the ONIE boot rom. + * + * The ONLP framework will mmap() and parse the ONIE TLV structure + * from the given data. + * + * If you platform does not support a mappable address for the ONIE + * eeprom then you should not provide this function at all. + * + * For the purposes of this example we will provide it but + * return UNSUPPORTED (which is all the default implementation does). + * + */ +int +onlp_sysi_onie_data_phys_addr_get(void** pa) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * If you cannot provide a base address you must provide the ONLP + * framework the raw ONIE data through whatever means necessary. + * + * This function will be called as a backup in the event that + * onlp_sysi_onie_data_phys_addr_get() fails. + */ +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ +#if 0 + int rv; + int i; + + /* + * This represents the example ONIE data. + */ + static uint8_t onie_data[] = { + 'T', 'l', 'v','I','n','f','o', 0, + 0x1, 0x0, 0x0, + 0x21, 0x8, 'O', 'N', 'L', 'P', 'I', 'E', 0, 0, + 0x22, 0x3, 'O', 'N', 'L', + 0xFE, 0x4, 0x4b, 0x1b, 0x1d, 0xde, + }; + + + memcpy(*data, onie_data, ONLPLIB_CONFIG_I2C_BLOCK_SIZE); + return 0; +#endif + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * IF the ONLP frame calles onlp_sysi_onie_data_get(), + * if will call this function to free the data when it + * is finished with it. + * + * This function is optional, and depends on the data + * you return in onlp_sysi_onie_data_get(). + */ +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + /* + * We returned a static array in onlp_sysi_onie_data_get() + * so no free operation is required. + */ + if(data) { + aim_free(data); + } +} + + +int +onlp_sysi_onie_info_get (onlp_onie_info_t *onie) +{ + int rv = ONLP_STATUS_OK; + int i; + onie->_hdr_length = 0; + for(i = 0; i < SYSI_ONIE_TYPE_SUPPORT_NUM; i++) + { + if( rv != ONLP_STATUS_OK ) { return rv; } + rv = _parse_tlv(onie, (__tlv_code_list[i])); + + } + + onie->_hdr_id_string = aim_fstrdup("TlvInfo"); + onie->_hdr_version = 0x1; + return rv; +} + + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int rv = ONLP_STATUS_OK; + char cpld_str[ONLP_CONFIG_INFO_STR_MAX]= {0}; + char other_str[ONLP_CONFIG_INFO_STR_MAX]= {0}; + char version[ONLP_CONFIG_INFO_STR_MAX]; + + rv = _sysi_version_parsing(INV_SYSLED_PREFIX"info", "The CPLD version is ", version); + if( rv != ONLP_STATUS_OK ) { return rv; } + snprintf(cpld_str, ONLP_CONFIG_INFO_STR_MAX, "%s%s ", cpld_str, version); + rv = _sysi_version_parsing(INV_HWMON_PREFIX"version", "ver: ", version); + if( rv != ONLP_STATUS_OK ) { return rv; } + snprintf(other_str, ONLP_CONFIG_INFO_STR_MAX, "%s%s.%s " + ,other_str, "psoc", version); + + /*cpld version*/ + if(strlen(cpld_str) > 0) { + pi->cpld_versions = aim_fstrdup("%s",cpld_str); + } + + /*other version*/ + if(strlen(other_str) > 0) { + pi->other_versions = aim_fstrdup("%s",other_str); + } + return rv; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + if(pi->cpld_versions) { + aim_free(pi->cpld_versions); + } + if(pi->other_versions) { + aim_free(pi->other_versions); + } + return; +} + + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + for(i=1; i + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +typedef struct thermali_path_s { + char file[ONLP_CONFIG_INFO_STR_MAX]; +} thermali_path_t; + +#define MAKE_THERMAL_PATH_ON_CPU(id) { INV_CTMP_PREFIX"temp"#id"_input"} +#define MAKE_THERMAL_PATH_ON_MAIN_BROAD(id) { INV_HWMON_PREFIX"temp"#id"_input"} +#define MAKE_THERMAL1_PATH_ON_PSU(psu_id) { INV_HWMON_PREFIX"thermal_psu"#psu_id} +#define MAKE_THERMAL2_PATH_ON_PSU(psu_id) { INV_HWMON_PREFIX"thermal2_psu"#psu_id} + +static thermali_path_t __path_list[ONLP_THERMAL_COUNT] = { + MAKE_THERMAL_PATH_ON_CPU(1), + MAKE_THERMAL_PATH_ON_CPU(2), + MAKE_THERMAL_PATH_ON_CPU(3), + MAKE_THERMAL_PATH_ON_CPU(4), + MAKE_THERMAL_PATH_ON_CPU(5), + MAKE_THERMAL_PATH_ON_MAIN_BROAD(1), + MAKE_THERMAL_PATH_ON_MAIN_BROAD(2), + MAKE_THERMAL_PATH_ON_MAIN_BROAD(3), + MAKE_THERMAL_PATH_ON_MAIN_BROAD(4), + MAKE_THERMAL_PATH_ON_MAIN_BROAD(5), + MAKE_THERMAL1_PATH_ON_PSU(1), + MAKE_THERMAL2_PATH_ON_PSU(1), + MAKE_THERMAL1_PATH_ON_PSU(2), + MAKE_THERMAL2_PATH_ON_PSU(2) +}; + +#define MAKE_THERMAL_INFO_NODE_ON_CPU_PHY \ + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_PHY), "CPU Physical", 0}, \ + ONLP_THERMAL_STATUS_PRESENT, \ + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS \ + } +#define MAKE_THERMAL_INFO_NODE_ON_CPU_CORE(id) \ + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_CPU_CORE##id), "CPU Core "#id, 0},\ + ONLP_THERMAL_STATUS_PRESENT, \ + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS \ + } +#define MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(id) \ + { { ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_##id##_ON_MAIN_BROAD), "Thermal Sensor "#id, 0}, \ + ONLP_THERMAL_STATUS_PRESENT, \ + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS \ + } +#define MAKE_THERMAL_INFO_NODE_ON_PSU(thermal_id, psu_id) \ + { { \ + ONLP_THERMAL_ID_CREATE(ONLP_THERMAL_##thermal_id##_ON_PSU##psu_id), \ + "PSU-"#psu_id" Thermal Sensor "#thermal_id, \ + ONLP_PSU_ID_CREATE(ONLP_PSU_##psu_id) \ + }, \ + ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS \ + } + +/* Static values */ +static onlp_thermal_info_t __onlp_thermal_info[ONLP_THERMAL_COUNT] = { + MAKE_THERMAL_INFO_NODE_ON_CPU_PHY, + MAKE_THERMAL_INFO_NODE_ON_CPU_CORE(0), + MAKE_THERMAL_INFO_NODE_ON_CPU_CORE(1), + MAKE_THERMAL_INFO_NODE_ON_CPU_CORE(2), + MAKE_THERMAL_INFO_NODE_ON_CPU_CORE(3), + MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(1), + MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(2), + MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(3), + MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(4), + MAKE_THERMAL_INFO_NODE_ON_MAIN_BROAD(5), + MAKE_THERMAL_INFO_NODE_ON_PSU(1,1), + MAKE_THERMAL_INFO_NODE_ON_PSU(2,1), + MAKE_THERMAL_INFO_NODE_ON_PSU(1,2), + MAKE_THERMAL_INFO_NODE_ON_PSU(2,2) +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id; + VALIDATE(id); + int ret; + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = __onlp_thermal_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + ret = onlp_thermali_status_get(id, &info->status); + if( ret != ONLP_STATUS_OK ){ return ret; } + + if(info->status & ONLP_THERMAL_STATUS_PRESENT){ + ret = onlp_file_read_int(&info->mcelsius, __path_list[LOCAL_ID_TO_INFO_IDX(local_id)].file); + } + + return ret; +} + + +/** + * @brief Retrieve the thermal's operational status. + * @param id The thermal oid. + * @param rv [out] Receives the operational status. + */ +int onlp_thermali_status_get(onlp_oid_t id, uint32_t* rv) +{ + int local_id; + int ret = ONLP_STATUS_OK; + onlp_thermal_info_t* info; + VALIDATE(id); + uint32_t psu_status; + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + info = &__onlp_thermal_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + + switch(local_id){ + case ONLP_THERMAL_1_ON_PSU1: + case ONLP_THERMAL_2_ON_PSU1: + case ONLP_THERMAL_1_ON_PSU2: + case ONLP_THERMAL_2_ON_PSU2: + ret = onlp_psui_status_get((&info->hdr)->poid, &psu_status); + if(ret != ONLP_STATUS_OK){return ret;} + + if(psu_status & ONLP_PSU_STATUS_PRESENT){ + info->status |= ONLP_THERMAL_STATUS_PRESENT; + }else{ + info->status = 0; + } + break; + default: + break; + } + + *rv = info->status; + + return ret; +} + +/** + * @brief Retrieve the thermal's oid header. + * @param id The thermal oid. + * @param rv [out] Receives the header. + */ +int onlp_thermali_hdr_get(onlp_oid_t id, onlp_oid_hdr_t* rv) +{ + int local_id; + onlp_thermal_info_t* info; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if(local_id >= ONLP_THERMAL_MAX) { + return ONLP_STATUS_E_INVALID; + } + info = &__onlp_thermal_info[LOCAL_ID_TO_INFO_IDX(local_id)]; + + *rv = info->hdr; + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_config.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_config.c new file mode 100644 index 00000000..bfff2079 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(_x) +x86_64_inventec_d5264q28b_config_settings_t x86_64_inventec_d5264q28b_config_settings[] = +{ +#ifdef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_PORTING_STDLIB(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_inventec_d5264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d5264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_inventec_d5264q28b_config_STRINGIFY_VALUE +#undef __x86_64_inventec_d5264q28b_config_STRINGIFY_NAME + +const char* +x86_64_inventec_d5264q28b_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_inventec_d5264q28b_config_settings[i].name; i++) { + if(strcmp(x86_64_inventec_d5264q28b_config_settings[i].name, setting)) { + return x86_64_inventec_d5264q28b_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_inventec_d5264q28b_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_inventec_d5264q28b_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_inventec_d5264q28b_config_settings[i].name, x86_64_inventec_d5264q28b_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_enums.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_enums.c new file mode 100644 index 00000000..9996e458 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_int.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_int.h new file mode 100644 index 00000000..f28c89f3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_inventec_d5264q28b Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5264q28b_INT_H__ +#define __x86_64_inventec_d5264q28b_INT_H__ + +#include + + +#endif /* __x86_64_inventec_d5264q28b_INT_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.c new file mode 100644 index 00000000..d2c6fca5 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d5264q28b_log.h" +/* + * x86_64_inventec_d5264q28b log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_inventec_d5264q28b_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_inventec_d5264q28b_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_inventec_d5264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.h new file mode 100644 index 00000000..bff46fc2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d5264q28b_LOG_H__ +#define __x86_64_inventec_d5264q28b_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_inventec_d5264q28b +#include + +#endif /* __x86_64_inventec_d5264q28b_LOG_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_module.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_module.c new file mode 100644 index 00000000..f0f861a3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d5264q28b_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_inventec_d5264q28b_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_inventec_d5264q28b_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_ucli.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_ucli.c new file mode 100644 index 00000000..43a4f3c2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/onlp/builds/src/module/src/x86_64_inventec_d5264q28b_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_inventec_d5264q28b_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_inventec_d5264q28b_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d5264q28b) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_inventec_d5264q28b_ucli_module__ = + { + "x86_64_inventec_d5264q28b_ucli", + NULL, + x86_64_inventec_d5264q28b_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_inventec_d5264q28b_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_inventec_d5264q28b_ucli_module__); + n = ucli_node_create("x86_64_inventec_d5264q28b", NULL, &x86_64_inventec_d5264q28b_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d5264q28b")); + return n; +} + +#else +void* +x86_64_inventec_d5264q28b_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/PKG.yml new file mode 100644 index 00000000..c78c705f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d5264q28b REVISION=r0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/healthstatus.sh b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/healthstatus.sh new file mode 100755 index 00000000..90254700 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/healthstatus.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +normal='0 : normal' +unpowered='2 : unpowered' +fault='4 : fault' +notinstalled='7 : not installed' + +while true +do + psu0var=$(cat /sys/bus/i2c/devices/i2c-0/0-0055/psu0) # bottom PSU + psu1var=$(cat /sys/bus/i2c/devices/i2c-0/0-0055/psu1) # top PSU + fan1in=$(cat /sys/class/hwmon/hwmon1/device/fan1_input) # fanmodule1, far right, back view + fan2in=$(cat /sys/class/hwmon/hwmon1/device/fan2_input) # fanmodule1, far right, back view + fan3in=$(cat /sys/class/hwmon/hwmon1/device/fan3_input) # fanmodule2 + fan4in=$(cat /sys/class/hwmon/hwmon1/device/fan4_input) # fanmodule2 + fan5in=$(cat /sys/class/hwmon/hwmon1/device/fan5_input) # fanmodule3 + fan6in=$(cat /sys/class/hwmon/hwmon1/device/fan6_input) # fanmodule3 + fan7in=$(cat /sys/class/hwmon/hwmon1/device/fan7_input) # fanmodule4, far left, back view + fan8in=$(cat /sys/class/hwmon/hwmon1/device/fan8_input) # fanmodule4, far left, back view + + if [ "$psu0var" = "$normal" ] && + [ "$psu1var" = "$normal" ] && # PSU normal operation + [ "$fan1in" -gt 0 ] && [ "$fan2in" -gt 0 ] && # fan on + [ "$fan3in" -gt 0 ] && [ "$fan4in" -gt 0 ] && + [ "$fan5in" -gt 0 ] && [ "$fan6in" -gt 0 ] && + [ "$fan7in" -gt 0 ] && [ "$fan8in" -gt 0 ] + then + echo 1 > /sys/bus/i2c/devices/i2c-0/0-0055/ctl + echo 0 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led # red off + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led # grn solid + + elif [ "$psu0var" = "$unpowered" ] || + [ "$psu1var" = "$unpowered" ] || # PSU unpowered + [ "$fan1in" -eq 0 ] || [ "$fan2in" -eq 0 ] || # fan off + [ "$fan3in" -eq 0 ] || [ "$fan4in" -eq 0 ] || + [ "$fan5in" -eq 0 ] || [ "$fan6in" -eq 0 ] || + [ "$fan7in" -eq 0 ] || [ "$fan8in" -eq 0 ] + then + echo 1 > /sys/bus/i2c/devices/i2c-0/0-0055/ctl + echo 0 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led # red off + echo 3 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led # grn @2Hz + + elif [ "$psu0var" = "$fault" ] || + [ "$psu0var" = "$notinstalled" ] || + [ "$psu1var" = "$fault" ] || + [ "$psu1var" = "$notinstalled" ] # PSU fault or PSU not installed + then + echo 1 > /sys/bus/i2c/devices/i2c-0/0-0055/ctl + echo 0 > /sys/bus/i2c/devices/i2c-0/0-0055/grn_led # grn off + echo 7 > /sys/bus/i2c/devices/i2c-0/0-0055/red_led # red solid + fi + sleep 1 +done diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/x86-64-inventec-d5264q28b-r0.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/x86-64-inventec-d5264q28b-r0.yml new file mode 100644 index 00000000..85fd855b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/lib/x86-64-inventec-d5264q28b-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for d5264q28b +# +###################################################################### + +x86-64-inventec-d5264q28b-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/python/x86_64_inventec_d5264q28b_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/python/x86_64_inventec_d5264q28b_r0/__init__.py new file mode 100644 index 00000000..e5e64483 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d5264q28b/platform-config/r0/src/python/x86_64_inventec_d5264q28b_r0/__init__.py @@ -0,0 +1,43 @@ +from onl.platform.base import * +from onl.platform.inventec import * + +class OnlPlatform_x86_64_inventec_d5264q28b_r0(OnlPlatformInventec, + OnlPlatformPortConfig_64x100): + PLATFORM='x86-64-inventec-d5264q28b-r0' + MODEL="D5264Q28B" + SYS_OBJECT_ID=".1.32" + + def baseconfig(self): + os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko") + + #self.insmod('inv_platform') + os.system("echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device") + os.system("sleep 1") + os.system("echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-8/new_device") + os.system("sleep 1") + #Upper + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-3/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-4/new_device") + os.system("sleep 1") + #Lower + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-9/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-10/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-11/new_device") + os.system("echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-12/new_device") + + self.insmod('inv_psoc') + os.system("echo inv_cpld 0x55 > /sys/bus/i2c/devices/i2c-0/new_device") + os.system("echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/new_device") + self.insmod('inv_cpld') + self.insmod('inv_mux') + self.insmod('io_expander') + self.insmod('transceiver') + self.insmod('inv_swps') + self.insmod('onie_tlvinfo') + self.insmod('inv_vpd') + + os.system("/lib/platform-config/x86-64-inventec-d5264q28b-r0/onl/healthstatus.sh &") + + return True diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/PKG.yml new file mode 100644 index 00000000..8e1d3767 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d6556 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/Makefile new file mode 100644 index 00000000..5fe8392a --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := inventec +BASENAME := x86-64-inventec-d6556 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/Makefile new file mode 100644 index 00000000..47b3610f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/Makefile @@ -0,0 +1,8 @@ +obj-m += i2c-gpio.o +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_pthread.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o inv_mux.o transceiver.o +obj-m += vpd.o +vpd-objs := inv_vpd.o onie_tlvinfo.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/i2c-gpio.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/i2c-gpio.c new file mode 100644 index 00000000..71a45b21 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/i2c-gpio.c @@ -0,0 +1,293 @@ +/* + * Bitbanging I2C bus driver using the GPIO API + * + * Copyright (C) 2007 Atmel Corporation + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; + +/* Toggle SDA by changing the direction of the pin */ +static void i2c_gpio_setsda_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->sda_pin); + else + gpio_direction_output(pdata->sda_pin, 0); +} + +/* + * Toggle SDA by changing the output value of the pin. This is only + * valid for pins configured as open drain (i.e. setting the value + * high effectively turns off the output driver.) + */ +static void i2c_gpio_setsda_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->sda_pin, state); +} + +/* Toggle SCL by changing the direction of the pin. */ +static void i2c_gpio_setscl_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->scl_pin); + else + gpio_direction_output(pdata->scl_pin, 0); +} + +/* + * Toggle SCL by changing the output value of the pin. This is used + * for pins that are configured as open drain and for output-only + * pins. The latter case will break the i2c protocol, but it will + * often work in practice. + */ +static void i2c_gpio_setscl_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->scl_pin, state); +} + +static int i2c_gpio_getsda(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->sda_pin); +} + +static int i2c_gpio_getscl(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->scl_pin); +} + +static int of_i2c_gpio_get_pins(struct device_node *np, + unsigned int *sda_pin, unsigned int *scl_pin) +{ + if (of_gpio_count(np) < 2) + return -ENODEV; + + *sda_pin = of_get_gpio(np, 0); + *scl_pin = of_get_gpio(np, 1); + + if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, *sda_pin, *scl_pin); + return -ENODEV; + } + + return 0; +} + +static void of_i2c_gpio_get_props(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); +} + +static int i2c_gpio_probe(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_gpio_platform_data *pdata; + struct i2c_algo_bit_data *bit_data; + struct i2c_adapter *adap; + unsigned int sda_pin, scl_pin; + int ret; + + /* First get the GPIO pins; if it fails, we'll defer the probe. */ + if (pdev->dev.of_node) { + ret = of_i2c_gpio_get_pins(pdev->dev.of_node, + &sda_pin, &scl_pin); + if (ret) + return ret; + } else { + if (!dev_get_platdata(&pdev->dev)) + return -ENXIO; + pdata = dev_get_platdata(&pdev->dev); + sda_pin = pdata->sda_pin; + scl_pin = pdata->scl_pin; + } + + ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + pdata->sda_pin = sda_pin; + pdata->scl_pin = scl_pin; + of_i2c_gpio_get_props(pdev->dev.of_node, pdata); + } else { + memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); + } + + if (pdata->sda_is_open_drain) { + gpio_direction_output(pdata->sda_pin, 1); + bit_data->setsda = i2c_gpio_setsda_val; + } else { + gpio_direction_input(pdata->sda_pin); + bit_data->setsda = i2c_gpio_setsda_dir; + } + + if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { + gpio_direction_output(pdata->scl_pin, 1); + bit_data->setscl = i2c_gpio_setscl_val; + } else { + gpio_direction_input(pdata->scl_pin); + bit_data->setscl = i2c_gpio_setscl_dir; + } + + if (!pdata->scl_is_output_only) + bit_data->getscl = i2c_gpio_getscl; + bit_data->getsda = i2c_gpio_getsda; + + if (pdata->udelay) + bit_data->udelay = pdata->udelay; + else if (pdata->scl_is_output_only) + bit_data->udelay = 50; /* 10 kHz */ + else + bit_data->udelay = 5; /* 100 kHz */ + + if (pdata->timeout) + bit_data->timeout = pdata->timeout; + else + bit_data->timeout = HZ / 10; /* 100 ms */ + + bit_data->data = pdata; + + adap->owner = THIS_MODULE; + if (pdev->dev.of_node) + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + else + snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); + + adap->algo_data = bit_data; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + adap->nr = pdev->id; + ret = i2c_bit_add_numbered_bus(adap); + if (ret) + return ret; + + platform_set_drvdata(pdev, priv); + + dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", + pdata->sda_pin, pdata->scl_pin, + pdata->scl_is_output_only + ? ", no clock stretching" : ""); + + return 0; +} + +static int i2c_gpio_remove(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_gpio_platform_data *pdata; + struct i2c_adapter *adap; + + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + pdata = &priv->pdata; + + i2c_del_adapter(adap); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + +static struct platform_driver i2c_gpio_driver = { + .driver = { + .name = "i2c-gpio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), + }, + .probe = i2c_gpio_probe, + .remove = i2c_gpio_remove, +}; + +static int __init i2c_gpio_init(void) +{ + int ret; + + ret = platform_driver_register(&i2c_gpio_driver); + if (ret) + printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); + + return ret; +} +subsys_initcall(i2c_gpio_init); + +static void __exit i2c_gpio_exit(void) +{ + platform_driver_unregister(&i2c_gpio_driver); +} +module_exit(i2c_gpio_exit); + +MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); +MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:i2c-gpio"); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_cpld.c new file mode 100644 index 00000000..5ee4b26c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..89e95f12 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.c @@ -0,0 +1,275 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..ebed0444 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_mux.h @@ -0,0 +1,40 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_platform.c new file mode 100644 index 00000000..d98aab3b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_platform.c @@ -0,0 +1,222 @@ +#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 = { +// {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc +// {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"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 platform_device *device_i2c_gpio0; +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 58, //494, + .sda_pin = 75, //511, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +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__); + + //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); //i2c-gpio sdl (GPIO58) + outl( inl(0x541) | (1<<3), 0x541); //i2c-gpio sda (GPIO75) + 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) + + device_i2c_gpio0 = platform_device_alloc("i2c-gpio", 1); + if (!device_i2c_gpio0) { + printk(KERN_ERR "i2c-gpio: platform_device_alloc fail\n"); + return -ENOMEM; + } + device_i2c_gpio0->name = "i2c-gpio"; + device_i2c_gpio0->id = 1; + device_i2c_gpio0->dev.platform_data = &i2c_gpio_platdata0; + + ret = platform_device_add(device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret); + } + + for(i=0; idev.platform_data = NULL; + platform_device_unregister(device_i2c_gpio0); +} + +module_init(inv_platform_init); +module_exit(inv_platform_exit); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Platform devices"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_psoc.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_psoc.c new file mode 100644 index 00000000..e19bb7a3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_psoc.c @@ -0,0 +1,994 @@ +/* + * This program is free software; you can 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 +#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);} + sysfs_remove_group(device_kobj, &psoc_group); + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_pthread.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_pthread.c new file mode 100644 index 00000000..9faf33e7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_pthread.c @@ -0,0 +1,1207 @@ +/***************************** + 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); +} + +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]; + +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" ); +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +}; +#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 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 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(&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/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) { + 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 = 0; + + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..eb09d758 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.c @@ -0,0 +1,3043 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..18c21b1d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_swps.h @@ -0,0 +1,1157 @@ +#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 = MUX_RST_GPIO_69_PAC9548; + +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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..2075fd4e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.c @@ -0,0 +1,332 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, const char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = (char*)buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..58c7fe33 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/inv_vpd.h @@ -0,0 +1,46 @@ +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_ENTRY_SIZE (17) +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/io_expander.c new file mode 100644 index 00000000..4564b585 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/io_expander.h new file mode 100644 index 00000000..810b730d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/io_expander.h @@ -0,0 +1,180 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..aaa3d507 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,815 @@ +#include +#include +#include +#include +//#include +#include + +//#include +//#include +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +#if 0 +static unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} +#else +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = (unsigned char*)buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} +#endif + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %zd\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %zd\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} +#if 0 +int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf) +{ + int tlv_end; + int curr_tlv; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int iFind = 0; + + if( !is_valid_tlvinfo_header(eeprom_hdr) ) { + printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n"); + return -1; + } + + curr_tlv = sizeof(tlvinfo_header_t); + tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while(curr_tlv < tlv_end){ + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv]; + if (!is_valid_tlv(eeprom_tlv)) { + printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n", + curr_tlv); + return -1; + } + + decode_tlv_value(eeprom_tlv, c_buf); + if( eeprom_tlv->type == i_offset){ + iFind = 1; + break; + } + curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + if( iFind == 0 ) + return -1; + else + return 0; +} +#endif diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..da0a0759 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); +//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.c new file mode 100644 index 00000000..114f0b28 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.c @@ -0,0 +1,8382 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.h new file mode 100644 index 00000000..f179599b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/src/transceiver.h @@ -0,0 +1,808 @@ +#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/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/PKG.yml new file mode 100644 index 00000000..05479502 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d6556 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/Makefile new file mode 100644 index 00000000..94067247 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-inventec-d6556 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_inventec_d6556 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-inventec-d6556.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/libonlp-x86-64-inventec-d6556.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/libonlp-x86-64-inventec-d6556.mk new file mode 100644 index 00000000..7a0b81d4 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/lib/libonlp-x86-64-inventec-d6556.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-inventec-d6556 module. +# +# Autogenerated 2018-11-30 07:22:16.900798 +# +############################################################################### +libonlp-x86-64-inventec-d6556_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..c8fa58d8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_inventec_d6556 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/onlpdump.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/onlpdump.mk new file mode 100644 index 00000000..38ffcbdb --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/onlpdump/onlpdump.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the onlpdump module. +# +# Autogenerated 2018-11-30 07:22:10.961262 +# +############################################################################### +onlpdump_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/.module b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/.module new file mode 100644 index 00000000..63419b7b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_inventec_d6556 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/Makefile new file mode 100644 index 00000000..820243bf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_inventec_d6556 +AUTOMODULE := x86_64_inventec_d6556 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..5daed4d0 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_inventec_d6556 Autogeneration +# +############################################################################### +x86_64_inventec_d6556_AUTO_DEFS := module/auto/x86_64_inventec_d6556.yml +x86_64_inventec_d6556_AUTO_DIRS := module/inc/x86_64_inventec_d6556 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/x86_64_inventec_d6556.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/x86_64_inventec_d6556.yml new file mode 100644 index 00000000..9fde9db5 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/auto/x86_64_inventec_d6556.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_inventec_d6556 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_inventec_d6556_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_inventec_d6556_CONFIG_PORTING_STDLIB +- x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_inventec_d6556_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_inventec_d6556_config + + portingmacro: + x86_64_inventec_d6556: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556.x b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556.x new file mode 100644 index 00000000..311d0e48 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_config.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_config.h new file mode 100644 index 00000000..83f3c163 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d6556 Configuration Header + * + * @addtogroup x86_64_inventec_d6556-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6556_CONFIG_H__ +#define __x86_64_inventec_d6556_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_inventec_d6556_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING +#define x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT +#define x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_inventec_d6556_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_PORTING_STDLIB +#define x86_64_inventec_d6556_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d6556_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI +#define x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_inventec_d6556_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_inventec_d6556_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_inventec_d6556_config_settings table. */ +extern x86_64_inventec_d6556_config_settings_t x86_64_inventec_d6556_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_inventec_d6556_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_inventec_d6556_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_inventec_d6556_porting.h" + +#endif /* __x86_64_inventec_d6556_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_dox.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_dox.h new file mode 100644 index 00000000..ce8411db --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_inventec_d6556 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6556_DOX_H__ +#define __x86_64_inventec_d6556_DOX_H__ + +/** + * @defgroup x86_64_inventec_d6556 x86_64_inventec_d6556 - x86_64_inventec_d6556 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_inventec_d6556-x86_64_inventec_d6556 Public Interface + * @defgroup x86_64_inventec_d6556-config Compile Time Configuration + * @defgroup x86_64_inventec_d6556-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_inventec_d6556_DOX_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_porting.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_porting.h new file mode 100644 index 00000000..36a3ac83 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/inc/x86_64_inventec_d6556/x86_64_inventec_d6556_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d6556 Porting Macros. + * + * @addtogroup x86_64_inventec_d6556-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6556_PORTING_H__ +#define __x86_64_inventec_d6556_PORTING_H__ + + +/* */ +#if x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_inventec_d6556_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_inventec_d6556_MALLOC GLOBAL_MALLOC + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_MALLOC malloc + #else + #error The macro x86_64_inventec_d6556_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_FREE + #if defined(GLOBAL_FREE) + #define x86_64_inventec_d6556_FREE GLOBAL_FREE + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_FREE free + #else + #error The macro x86_64_inventec_d6556_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_inventec_d6556_MEMSET GLOBAL_MEMSET + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_MEMSET memset + #else + #error The macro x86_64_inventec_d6556_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_inventec_d6556_MEMCPY GLOBAL_MEMCPY + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_MEMCPY memcpy + #else + #error The macro x86_64_inventec_d6556_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_inventec_d6556_STRNCPY GLOBAL_STRNCPY + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_STRNCPY strncpy + #else + #error The macro x86_64_inventec_d6556_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_inventec_d6556_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_VSNPRINTF vsnprintf + #else + #error The macro x86_64_inventec_d6556_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_inventec_d6556_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_SNPRINTF snprintf + #else + #error The macro x86_64_inventec_d6556_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6556_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_inventec_d6556_STRLEN GLOBAL_STRLEN + #elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6556_STRLEN strlen + #else + #error The macro x86_64_inventec_d6556_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_inventec_d6556_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..ccd19207 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_inventec_d6556_INCLUDES := -I $(THIS_DIR)inc +x86_64_inventec_d6556_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_inventec_d6556_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d6556 ucli:x86_64_inventec_d6556 + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..2b04d852 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_inventec_d6556_ucli.c + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/debug.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..2d04002f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_inventec_d6556_int.h" + +#if x86_64_inventec_d6556_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_inventec_d6556_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..45fe2b53 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/fani.c @@ -0,0 +1,275 @@ +/************************************************************ + * fani.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define FAN_GPI_ON_MAIN_BOARD INV_PSOC_PREFIX"/fan_gpi" + +#define MAX_FAN_SPEED 18000 +#define MAX_PSU_FAN_SPEED 25500 + +#define PROJECT_NAME +#define LEN_FILE_NAME 80 + +static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_PSOC_PREFIX"/fan1_input", + INV_PSOC_PREFIX"/fan2_input", + INV_PSOC_PREFIX"/fan3_input", + INV_PSOC_PREFIX"/fan4_input", + INV_PSOC_PREFIX"/fan5_input", + INV_PSOC_PREFIX"/fan6_input", + INV_PSOC_PREFIX"/fan7_input", + INV_PSOC_PREFIX"/fan8_input", + INV_PSOC_PREFIX"/rpm_psu1", + INV_PSOC_PREFIX"/rpm_psu2", +}; + +#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[FAN_MAX] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + memset(vstr, 0, 32); + /* get fan present status */ + ret = onlp_file_read_str(vp, FAN_GPI_ON_MAIN_BOARD); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%x", &value); + if (value & (1 << (fid-1))) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + else { + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + } + + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + + return ONLP_STATUS_OK; +} + + +static uint32_t +_onlp_get_fan_direction_on_psu(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) { + continue; + } + + if (PSU_TYPE_AC_F2B == psu_type) { + return ONLP_FAN_STATUS_F2B; + } + else { + return ONLP_FAN_STATUS_B2F; + } + } + + return 0; +} + + +static int +_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info) +{ + int value, ret, index; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan direction */ + info->status |= _onlp_get_fan_direction_on_psu(); + + if (info->status & ONLP_FAN_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + index = ONLP_OID_ID_GET(info->hdr.id); + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + rc = _onlp_fani_info_get_fan_on_psu(local_id, info); + break; + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + rc = _onlp_fani_info_get_fan(local_id, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + switch (fid) + { + case FAN_1_ON_PSU1: + return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p); + case FAN_1_ON_PSU2: + return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p); + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + path = FAN_NODE(fan_duty_cycle_percentage); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, path, NULL) != 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..a695afda --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,308 @@ +/************************************************************ + * ledi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define filename "brightness" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_CPLD_PREFIX"/%s_led", + INV_PSOC_PREFIX"/fan_led_%s1", + INV_PSOC_PREFIX"/fan_led_%s2", + INV_PSOC_PREFIX"/fan_led_%s3", + INV_PSOC_PREFIX"/fan_led_%s4", +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_BLUE, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { + {LED_SYS, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_SYS, LED_MODE_RED, ONLP_LED_MODE_RED}, + {LED_FAN1,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN2,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN3,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN4,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +}; + +static char last_path[][10] = /* must map with onlp_led_id */ +{ + "reserved", + "diag", + "loc", + "fan", + "psu1", + "psu2" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[LED_MAX] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_SYS), "Chassis LED (SYSTEM LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN1), "Fan LED 1 (FAN1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN2), "Fan LED 2 (FAN2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN3), "Fan LED 3 (FAN3 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN4), "Fan LED 4 (FAN4 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, +}; + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + /* + * Diag LED Off + */ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_SYS), ONLP_LED_MODE_OFF); + + return ONLP_STATUS_OK; +} + +int onlp_chassis_led_read(char *pathp, char *buf, size_t len) +{ + FILE * fp; + + fp = fopen (pathp, "r"); + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + if( fgets (buf, len, fp) == NULL ) { + perror("Error fgets operation"); + } + fclose(fp); + + return(0); +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id, gret = 0, rret = 0; + char fullpath_grn[50] = {0}; + char fullpath_red[50] = {0}; + int gvalue = 0, rvalue = 0; + char buf[32] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + switch (local_id) { + case LED_SYS: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + gret = onlp_chassis_led_read(fullpath_grn, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + gvalue = 1; + } + + rret = onlp_chassis_led_read(fullpath_red, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + rvalue = 1; + } + if (gret < 0 && rret < 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = -1; + rvalue = -1; + } + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + if (onlp_file_read_int(&gvalue, fullpath_grn) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = 0; + } + if (onlp_file_read_int(&rvalue, fullpath_red) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + rvalue = 0; + } + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + gvalue = -1; + rvalue = -1; + break; + } + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + if (gvalue == 1 && rvalue == 0) { + info->mode = ONLP_LED_MODE_GREEN; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 1) { + info->mode = ONLP_LED_MODE_RED; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 1 && rvalue == 1) { + info->mode = ONLP_LED_MODE_ORANGE; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 0) { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_ON; + } + else { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_FAILED; + } + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int local_id; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + switch (local_id) { + case LED_SYS: + sprintf(fullpath, "%s%s/%s", INV_CPLD_PREFIX, last_path[local_id], filename); + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath, "%s%s/%s", INV_PSOC_PREFIX, last_path[local_id], filename); + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + return ONLP_STATUS_E_INTERNAL; + } + + if (onlp_file_write_int(onlp_to_driver_led_mode(local_id, mode), fullpath, NULL) != 0) + { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..cf92933f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_inventec_d6556 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..ab185ab6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,184 @@ +/************************************************************ + * platform_lib.c + * + * Copyright 2018 Inventec Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define PSU_NODE_MAX_PATH_LEN 64 + +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + return onlp_file_read((uint8_t*)buffer, buf_size, &data_len, "%s", filename); +} + +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 32 +#define I2C_PSU_FAN_DIR_LEN 8 +#include +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + char fan_dir[I2C_PSU_FAN_DIR_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name); + + if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if(isspace(model_name[strlen(model_name)-1])) { + model_name[strlen(model_name)] = 0; + } + + if (strncmp(model_name, "YM-2651Y", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F; + } + } + + if (strncmp(model_name, "YM-2651V", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_DC_48V_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_DC_48V_B2F; + } + } + + if (strncmp(model_name, "PSU-12V-750", 11) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); + } + + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", 3) == 0) { + return PSU_TYPE_DC_12V_F2B; + } + + if (strncmp(fan_dir, "B2F", 3) == 0) { + return PSU_TYPE_DC_12V_B2F; + } + + if (strncmp(fan_dir, "NON", 3) == 0) { + return PSU_TYPE_DC_12V_FANLESS; + } + } + + if (strncmp(model_name, "DPS-150AB-10", 12) == 0) { + if (modelname) { + strncpy(modelname, model_name, 12); + } + + return PSU_TYPE_DC_12V_F2B; + } + + return PSU_TYPE_UNKNOWN; +} + +int psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + *value = 0; + + if (PSU1_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + } + else + if (PSU2_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); + } + else { + return ONLP_STATUS_E_INTERNAL; + } + + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int psu_pmbus_info_set(int id, char *node, int value) +{ + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + switch (id) { + case PSU1_ID: + sprintf(path, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + break; + case PSU2_ID: + sprintf(path, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + }; + + if (onlp_file_write_int(value, path, NULL) != 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..8757e268 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,142 @@ +/************************************************************ + * platform_lib.h + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_inventec_d6556_log.h" + +#define ONLP_NODE_MAX_INT_LEN (8) +#define ONLP_NODE_MAX_PATH_LEN (64) + +#define INV_CPLD_COUNT (2) +#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/" +#define INV_CPLD2_PREFIX "/sys/bus/i2c/devices/0-0077/" +#define INV_PSOC_PREFIX "/sys/devices/virtual/hwmon/hwmon1/" +#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/" +#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/" + +#define CHASSIS_SFP_COUNT (56) + +/* + * Definitions of Chassis EEPROM + */ +#define EEPROM_NODE(node) INV_EPRM_PREFIX#node + + +/* + * Definitions of D7264Q28B device + */ +enum onlp_thermal_id { + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE_FIRST, + THERMAL_CPU_CORE_2, + THERMAL_CPU_CORE_3, + THERMAL_CPU_CORE_4, + THERMAL_CPU_CORE_LAST, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, + THERMAL_MAX +}; +#define CHASSIS_THERMAL_COUNT (10) + +enum onlp_fan_id { + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_2_ON_MAIN_BOARD, + FAN_3_ON_MAIN_BOARD, + FAN_4_ON_MAIN_BOARD, + FAN_5_ON_MAIN_BOARD, + FAN_6_ON_MAIN_BOARD, + FAN_7_ON_MAIN_BOARD, + FAN_8_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2, + FAN_MAX +}; +#define CHASSIS_FAN_COUNT (8) + +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_SYS, + LED_FAN1, + LED_FAN2, + LED_FAN3, + LED_FAN4, + LED_MAX +}; +#define CHASSIS_LED_COUNT (1) + +enum onlp_psu_id +{ + PSU_RESERVED = 0, + PSU1_ID, + PSU2_ID, + PSU_MAX +}; +#define CHASSIS_PSU_COUNT (2) + + +#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX +#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_HWMON_PREFIX INV_CPLD_PREFIX +#define PSU2_AC_HWMON_PREFIX INV_CPLD_PREFIX + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F, + PSU_TYPE_DC_48V_F2B, + PSU_TYPE_DC_48V_B2F, + PSU_TYPE_DC_12V_FANLESS, + PSU_TYPE_DC_12V_F2B, + PSU_TYPE_DC_12V_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +/* + * Definitions of FAN device + */ +#define FAN_BOARD_PATH INV_PSOC_PREFIX +#define FAN_NODE(node) FAN_BOARD_PATH#node + +/* + * Prototypes + */ +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_pmbus_info_set(int id, char *node, int value); + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..70b19202 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/psui.c @@ -0,0 +1,246 @@ +/************************************************************ + * psui.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT (0) +#define PSU_STATUS_POWER_GOOD (1) +#define PSU_STATUS_UNPOWERED (2) +#define PSU_STATUS_FAULT (4) +#define PSU_STATUS_UNINSTALLED (7) + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_CPLD_PREFIX"/psu0", + INV_CPLD_PREFIX"/psu1", +}; + +static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_PSOC_PREFIX"/psoc_psu1_%s", + INV_PSOC_PREFIX"/psoc_psu2_%s", +}; + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, status_devfiles__[id]); + } + else if (PSU2_ID == id) { + sprintf(node_path, status_devfiles__[id]); + } + + ret = onlp_file_read_str(vp, node_path); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); + return ONLP_STATUS_E_INTERNAL; + } + + if (!isdigit(*vstrp)) { + return ONLP_STATUS_E_INTERNAL; + } + *value = *vstrp - '0'; + return ONLP_STATUS_OK; +} + + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_module_info_get(int id, onlp_psu_info_t* info) +{ + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + int value = 0; + + info->caps |= ONLP_PSU_CAPS_DC12; + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path); + } + else { + info->mvout = value; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path); + } + else { + info->miout = value; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path); + } + else { + info->mpout = value; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path); + } + else { + info->mvin = value; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path); + } + else { + info->miin = value; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path); + } + else { + info->mpin = value; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "model"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->model, *vp, ret-1); + } + else { + //AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->model, "N/A", 3); + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "serial"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->serial, *vp, ret-1); + } + else { + AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->serial, "N/A", 3); + } + + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { + ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1) + } + }, + }, + { + { + ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2) + } + }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) { + printf("Unable to read PSU(%d) node(psu)\r\n", index); + return ret; + } + + if (val == 0) { + info->status = ONLP_PSU_STATUS_PRESENT; + } + else + if (val == 1) { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ret; + } + else { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; + } + + if ((ret = psu_module_info_get(index, info)) != ONLP_STATUS_OK) { + printf("Unable to read PSU(%d) module information\r\n", index); + } + + return ret; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..39f34fa2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,221 @@ +/************************************************************ + * sfpi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include + +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +static char sfp_node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + +#define NUM_OF_SFP_PORT (CHASSIS_SFP_COUNT) +static const int sfp_mux_index[NUM_OF_SFP_PORT] = { +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, +10, 11, 12, 13, 14, 15, 16, 17 +}; + +#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]) + +static int +sfp_node_read_int(char *node_path, int *value, int data_len) +{ + int ret = 0; + *value = 0; + + ret = onlp_file_read_int(value, node_path); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +static char* +sfp_get_port_path(int port, char *node_name) +{ + sprintf(sfp_node_path, "/sys/class/swps/port%d/%s", port, node_name); + + return sfp_node_path; +} + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 64} + */ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 0; p < NUM_OF_SFP_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + char* path = sfp_get_port_path(port, "present"); + if (sfp_node_read_int(path, &present, 0) != 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (present == 0) { + present = 1; + } + else + if (present == 1) { + present = 0; + } + else { + AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port); + return ONLP_STATUS_E_INTERNAL; + } + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t presence_all[2] = {0}; + int port, ret, index; + + for (port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) { + if (port == 32) { + index = 1; + } + + ret = onlp_sfpi_is_present(port); + if (ret == 1) { + presence_all[index] |= (1<>= 1; + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ +#if 1 + int bus = FRONT_PORT_TO_MUX_INDEX(port); + + memset(data, 0, 256); + /* Read eeprom information into data[] */ + if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0) + { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#else + char* path; + int len = 0; + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + memset(data, 0, 256); + path = sfp_get_port_path(port, "eeprom"); + if (onlp_file_read(&data[0], 256, &len, path) < 0) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#endif + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return onlp_sfpi_eeprom_read( port, data); +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..7b792a4e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,111 @@ +/************************************************************ + * sysi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "x86_64_inventec_d6556_int.h" +#include "x86_64_inventec_d6556_log.h" + +#include "platform_lib.h" + +#define NUM_OF_CPLD INV_CPLD_COUNT + +#define NUM_OF_THERMAL_ON_MAIN_BROAD (CHASSIS_THERMAL_COUNT) +#define NUM_OF_FAN_ON_MAIN_BROAD (CHASSIS_FAN_COUNT) +#define NUM_OF_PSU_ON_MAIN_BROAD (CHASSIS_PSU_COUNT) +#define NUM_OF_LED_ON_MAIN_BROAD (CHASSIS_LED_COUNT) + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-inventec-d6556-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, EEPROM_NODE(eeprom)) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 4 Thermal sensors on the chassis */ + for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 4 Fans on the chassis */ + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +static char *arr_cplddev_version[NUM_OF_CPLD] = +{ + INV_CPLD_PREFIX"/version", + INV_CPLD2_PREFIX"/version", +}; + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD]={0}; + for (i=0; i < NUM_OF_CPLD; i++) { + v[i] = 0; + if(onlp_file_read_int(v+i, arr_cplddev_version[i]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + } + pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + return 0; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/thermali.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/thermali.c new file mode 100644 index 00000000..e5d573a2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,147 @@ +/************************************************************ + * thermali.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_CTMP_PREFIX"/temp1_%s", + INV_CTMP_PREFIX"/temp2_%s", + INV_CTMP_PREFIX"/temp3_%s", + INV_CTMP_PREFIX"/temp4_%s", + INV_CTMP_PREFIX"/temp5_%s", + INV_PSOC_PREFIX"/temp1_input", + INV_PSOC_PREFIX"/temp2_input", + INV_PSOC_PREFIX"/temp3_input", + INV_PSOC_PREFIX"/temp4_input", + INV_PSOC_PREFIX"/temp5_input", + INV_PSOC_PREFIX"/thermal_psu1", + INV_PSOC_PREFIX"/thermal2_psu1", + INV_PSOC_PREFIX"/thermal_psu2", + INV_PSOC_PREFIX"/thermal2_psu2", +}; + +/* Static values */ +static onlp_thermal_info_t linfo[THERMAL_MAX] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "Physical id 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_2), "CPU Core 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_4), "CPU Core 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_LAST), "CPU Core 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "Chassis Thermal Sensor 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "Chassis Thermal Sensor 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[local_id]; + + if(local_id >= THERMAL_CPU_CORE_FIRST && local_id <= THERMAL_CPU_CORE_LAST) { + char desc[32], *dp = &desc[0]; + int rv = onlp_file_read_str(&dp, devfiles__[local_id], "label"); + if (rv > 0) { + memset (info->hdr.description, 0, ONLP_OID_DESC_SIZE); + strncpy(info->hdr.description, dp, rv); + } + + /* Set the onlp_oid_hdr_t and capabilities */ + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id], "input"); + } + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_config.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_config.c new file mode 100644 index 00000000..042d15c4 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_inventec_d6556_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_inventec_d6556_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d6556_config_STRINGIFY_NAME(_x) +x86_64_inventec_d6556_config_settings_t x86_64_inventec_d6556_config_settings[] = +{ +#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_PORTING_STDLIB + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_PORTING_STDLIB), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_inventec_d6556_CONFIG_PORTING_STDLIB(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_inventec_d6556_config_STRINGIFY_VALUE +#undef __x86_64_inventec_d6556_config_STRINGIFY_NAME + +const char* +x86_64_inventec_d6556_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_inventec_d6556_config_settings[i].name; i++) { + if(strcmp(x86_64_inventec_d6556_config_settings[i].name, setting)) { + return x86_64_inventec_d6556_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_inventec_d6556_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_inventec_d6556_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_inventec_d6556_config_settings[i].name, x86_64_inventec_d6556_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_enums.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_enums.c new file mode 100644 index 00000000..e81966dc --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_int.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_int.h new file mode 100644 index 00000000..41232e1f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_inventec_d6556 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6556_INT_H__ +#define __x86_64_inventec_d6556_INT_H__ + +#include + + +#endif /* __x86_64_inventec_d6556_INT_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.c new file mode 100644 index 00000000..7eb13c1c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d6556_log.h" +/* + * x86_64_inventec_d6556 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.h new file mode 100644 index 00000000..0a9496fe --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6556_LOG_H__ +#define __x86_64_inventec_d6556_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_inventec_d6556 +#include + +#endif /* __x86_64_inventec_d6556_LOG_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_module.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_module.c new file mode 100644 index 00000000..99713455 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d6556_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_inventec_d6556_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_inventec_d6556_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_ucli.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_ucli.c new file mode 100644 index 00000000..567cd4b6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/module/src/x86_64_inventec_d6556_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_inventec_d6556_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d6556) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_inventec_d6556_ucli_module__ = + { + "x86_64_inventec_d6556_ucli", + NULL, + x86_64_inventec_d6556_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_inventec_d6556_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_inventec_d6556_ucli_module__); + n = ucli_node_create("x86_64_inventec_d6556", NULL, &x86_64_inventec_d6556_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d6556")); + return n; +} + +#else +void* +x86_64_inventec_d6556_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/x86_64_inventec_d6556.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/x86_64_inventec_d6556.mk new file mode 100644 index 00000000..c60e9765 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/onlp/builds/src/x86_64_inventec_d6556.mk @@ -0,0 +1,13 @@ + +############################################################################### +# +# Inclusive Makefile for the x86_64_inventec_d6556 module. +# +# Autogenerated 2018-11-30 07:22:11.055018 +# +############################################################################### +x86_64_inventec_d6556_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(x86_64_inventec_d6556_BASEDIR)module/make.mk +include $(x86_64_inventec_d6556_BASEDIR)module/src/make.mk +include $(x86_64_inventec_d6556_BASEDIR)module/auto/make.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/PKG.yml new file mode 100644 index 00000000..de598c2e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d6556 REVISION=r0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/lib/x86-64-inventec-d6556-r0.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/lib/x86-64-inventec-d6556-r0.yml new file mode 100644 index 00000000..8d6ba0b5 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/lib/x86-64-inventec-d6556-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for d6556 +# +###################################################################### + +x86-64-inventec-d6556-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/python/x86_64_inventec_d6556_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/python/x86_64_inventec_d6556_r0/__init__.py new file mode 100644 index 00000000..b76c89f1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6556/platform-config/r0/src/python/x86_64_inventec_d6556_r0/__init__.py @@ -0,0 +1,22 @@ +from onl.platform.base import * +from onl.platform.inventec import * + +class OnlPlatform_x86_64_inventec_d6556_r0(OnlPlatformInventec, + OnlPlatformPortConfig_48x25_8x100): + PLATFORM='x86-64-inventec-d6556-r0' + MODEL="D6556" + SYS_OBJECT_ID=".6556.1" + + def baseconfig(self): + os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0") + self.insmod('i2c-gpio') + self.insmod('inv_platform') + self.insmod('inv_psoc') + self.new_i2c_device('inv_cpld', 0x55, 0) + self.insmod('inv_cpld') + self.new_i2c_device('inv_eeprom', 0x53, 0) + self.insmod('inv_eeprom') + self.insmod('swps') + self.insmod('vpd') + self.insmod('inv_pthread') + return True diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/.gitignore new file mode 100644 index 00000000..b617fd5a --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/.gitignore @@ -0,0 +1,2 @@ +*x86*64*inventec*d7032q28b*.mk +onlpdump.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/Makefile index 1fe88c1d..92d0e7f8 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/Makefile +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/Makefile @@ -1,5 +1,5 @@ KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 -KMODULES := $(wildcard *.c) +KMODULES := src VENDOR := inventec BASENAME := x86-64-inventec-d7032q28b ARCH := x86_64 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/Makefile new file mode 100644 index 00000000..c3bb6302 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/Makefile @@ -0,0 +1,8 @@ +obj-m += inv_platform.o +obj-m += inv_cpld.o +obj-m += inv_psoc.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o transceiver.o inv_mux.o +obj-m += vpd.o +vpd-objs := inv_vpd.o onie_tlvinfo.o +obj-m += inv_pthread.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/gpio-ich.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/gpio-ich.c new file mode 100644 index 00000000..70304220 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/gpio-ich.c @@ -0,0 +1,548 @@ +/* + * 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 +#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))); +} + +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; + chip->dev = &ichx_priv.dev->dev; + + /* 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, +}; + +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; + 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; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_cpld.c similarity index 96% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_cpld.c rename to packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_cpld.c index a5e38353..af587716 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_cpld.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_cpld.c @@ -15,8 +15,6 @@ #include #include -//#include "I2CHostCommunication.h" - #define USE_SMBUS 1 /* definition */ @@ -115,7 +113,6 @@ 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]; @@ -139,7 +136,6 @@ 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]; @@ -162,7 +158,6 @@ 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); @@ -179,7 +174,6 @@ 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]; @@ -202,7 +196,6 @@ 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; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..a0f5ce34 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.c @@ -0,0 +1,281 @@ +#include +#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 = "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; + mod_dsc = "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; + mod_dsc = "Hedera force mode"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + 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; + mod_dsc = "Normal mode :48"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_69_PAC9548: + 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; + mod_dsc = "Normal mode :69"; + 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__); +} +EXPORT_SYMBOL(clean_mux_gpio); + + +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; +} +EXPORT_SYMBOL(reset_mux_gpio); + + +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; +} +EXPORT_SYMBOL(init_mux_gpio); + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..429754a8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_mux.h @@ -0,0 +1,36 @@ +#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) + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_platform.c similarity index 76% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_platform.c rename to packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_platform.c index f046ba8c..cc31f1fb 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/inv_platform.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_platform.c @@ -1,5 +1,4 @@ #include -//#include #include #include #include @@ -10,7 +9,6 @@ #include #include -//#include #define IO_EXPAND_BASE 64 #define IO_EXPAND_NGPIO 16 @@ -111,39 +109,6 @@ static struct inv_i2c_board_info i2cdev_list[] = { {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; @@ -153,24 +118,6 @@ static int __init plat_redwood_x86_init(void) 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 "I2CHostCommunication.h" - #define USE_SMBUS 1 -//#define offsetof(st, m) ((size_t)(&((st *)0)->m)) #define FAN_NUM 5 #define PSU_NUM 2 @@ -94,7 +91,6 @@ struct __attribute__ ((__packed__)) psoc_layout { #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) @@ -182,17 +178,6 @@ static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned off #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; @@ -215,13 +200,6 @@ static u8 psoc_read8(struct i2c_client *client, u8 offset) 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) @@ -497,8 +475,6 @@ static ssize_t set_switch_tmp(struct device *dev, 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); @@ -528,7 +504,6 @@ 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; @@ -551,7 +526,6 @@ 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); @@ -675,7 +649,6 @@ static ssize_t show_psu(struct device *dev, struct device_attribute *da, 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) ); } @@ -725,9 +698,6 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET 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); @@ -742,10 +712,6 @@ 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); @@ -827,9 +793,6 @@ static struct attribute *psoc_attributes[] = { &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, @@ -842,10 +805,6 @@ static struct attribute *psoc_attributes[] = { &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, @@ -937,8 +896,6 @@ 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; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_pthread.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_pthread.c new file mode 100644 index 00000000..fe280c84 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_pthread.c @@ -0,0 +1,1233 @@ +/***************************** + 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); +} + +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]; + +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" ); +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +}; +#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) { + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..4d6e82c3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.c @@ -0,0 +1,2941 @@ +/************************************************************************* + * + * inv_swps.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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_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); +} + +static ssize_t +show_attr_eeprom(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_eeprom, + 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); +} + +/* ========== 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(eeprom, S_IRUGO, show_attr_eeprom, 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); + +/* ========== 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: + 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 + + 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; + } + 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; + } + if (device_create_file(device_p, &dev_attr_eeprom) < 0) { + err_attr = "eeprom"; + 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: + 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: + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..cba6d9ac --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_swps.h @@ -0,0 +1,752 @@ +/************************************************************************* + * + * inv_swps.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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.3" +#define SWP_LICENSE "GPL" + +#define SWPS_KERN_VER_AF_3_10 (1) + +/* 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 */ +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_REDWOOD + +/* 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) +#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" }, +}; + + +/* ========================================== + * 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_NAB, { {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 */ + }, + {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 + + +#endif /* INV_SWPS_H */ + + + + + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..b4b232a4 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.c @@ -0,0 +1,358 @@ +/************************************************************************* + * + * inv_vpd.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +static int +__swp_match(struct device *dev, +#ifdef VPD_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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = (char *)buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, (char *)buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; +#define VPD_ENTRY_SIZE (sizeof(VpdRegAttr)/sizeof(struct register_attr)) + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..7cbae65e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/inv_vpd.h @@ -0,0 +1,63 @@ +/************************************************************************* + * + * inv_vpd.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +#define VPD_KERN_VER_AF_3_10 (1) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.c new file mode 100644 index 00000000..3ef271ac --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.c @@ -0,0 +1,1700 @@ +/************************************************************************* + * + * io_expander.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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; + + +/* ========== 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) */ + }, +}; + + +/* ========== 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; + + 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_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->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; + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + 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: + 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; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +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; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +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__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +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; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + + +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; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +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"); + 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; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.h new file mode 100644 index 00000000..d57dfe15 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/io_expander.h @@ -0,0 +1,185 @@ +/************************************************************************* + * + * io_expander.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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) + +/* 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[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_bitmap_s map_hard_rs0[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[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 (*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/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..360219b2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,765 @@ +#include +#include +#include +#include +#include + +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = (unsigned char*)buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %zd\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %zd\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} +EXPORT_SYMBOL(read_eeprom); + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} +EXPORT_SYMBOL(prog_eeprom); + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} +EXPORT_SYMBOL(tlvinfo_decode_tlv); + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} +EXPORT_SYMBOL(tlvinfo_delete_tlv); + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} +EXPORT_SYMBOL(tlvinfo_add_tlv); + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..63df4620 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE +#define TLV_CODE_EEPROM_DATA 0x00 + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.c new file mode 100644 index 00000000..2f7338e3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.c @@ -0,0 +1,8273 @@ +/************************************************************************* + * + * transceiver.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#include +#include +#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, + .addr_eeprom =0x50, .page_eeprom =-1, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + + +/* ========== 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); +} +EXPORT_SYMBOL(alarm_msg_2_user); + + +/* ========== 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; +} +EXPORT_SYMBOL(lock_transvr_obj); + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + + +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_eeprom(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_eeprom, + self->eeprom_map_p->page_eeprom, + self->eeprom_map_p->offset_eeprom, + self->eeprom_map_p->length_eeprom, + self->eeprom, + "_common_update_attr_eeprom", + 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_eeprom(self, show_err) < 0) { + err_str = "_common_update_attr_eeprom"; + 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_eeprom(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, &_common_update_attr_eeprom, + "common_get_eeprom"); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + memset(buf, 0, self->eeprom_map_p->length_eeprom+1); + memcpy(buf, self->eeprom, self->eeprom_map_p->length_eeprom); + *(buf+self->eeprom_map_p->length_eeprom) = '\n'; + return self->eeprom_map_p->length_eeprom+1; +} + +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_eeprom = common_get_eeprom; + 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_eeprom = common_get_eeprom; + 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_eeprom = common_get_eeprom; + 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; +} +EXPORT_SYMBOL(create_transvr_obj); + + +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; +} +EXPORT_SYMBOL(isolate_transvr_obj); + + +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; +} +EXPORT_SYMBOL(resync_channel_tier_2); + + +/* ----------------------------------------- + * 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) + */ + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.h new file mode 100644 index 00000000..7ab56d38 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/modules/builds/src/transceiver.h @@ -0,0 +1,811 @@ +/************************************************************************* + * + * transceiver.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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_eeprom; int page_eeprom; int offset_eeprom; int length_eeprom; + 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]; + + uint8_t eeprom[256]; + + /* ========== 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_eeprom)(struct transvr_obj_s *self, char *buf_p); + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/debug.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..7831ccc8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_inventec_d7032q28b_int.h" + +#if x86_64_inventec_d7032q28b_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_inventec_d7032q28b_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/fani.c index 25addc7f..301055e3 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/fani.c @@ -1,36 +1,21 @@ /************************************************************ - * + * fani.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * * Fan Platform Implementation Defaults. * ***********************************************************/ +#include #include #include #include #include #include "platform_lib.h" -#define PREFIX_PATH_ON_MAIN_BOARD "/sys/bus/i2c/devices/2-0066/" -#define PREFIX_PATH_ON_PSU "/sys/bus/i2c/devices/" +#define FAN_GPI_ON_MAIN_BOARD INV_PSOC_PREFIX"/fan_gpi" #define MAX_FAN_SPEED 18000 #define MAX_PSU_FAN_SPEED 25500 @@ -38,41 +23,26 @@ #define PROJECT_NAME #define LEN_FILE_NAME 80 -#define FAN_RESERVED 0 -#define FAN_1_ON_MAIN_BOARD 1 -#define FAN_2_ON_MAIN_BOARD 2 -#define FAN_3_ON_MAIN_BOARD 3 -#define FAN_4_ON_MAIN_BOARD 4 -#define FAN_5_ON_MAIN_BOARD 5 -#define FAN_6_ON_MAIN_BOARD 6 -#define FAN_1_ON_PSU1 7 -#define FAN_1_ON_PSU2 8 - -enum fan_id { - FAN_1_ON_FAN_BOARD = 1, - FAN_2_ON_FAN_BOARD, - FAN_3_ON_FAN_BOARD, - FAN_4_ON_FAN_BOARD, - FAN_5_ON_FAN_BOARD, - FAN_1_ON_PSU_1, - FAN_1_ON_PSU_2, +static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_PSOC_PREFIX"/fan1_input", + INV_PSOC_PREFIX"/fan2_input", + INV_PSOC_PREFIX"/fan3_input", + INV_PSOC_PREFIX"/fan4_input", + INV_PSOC_PREFIX"/fan5_input", + INV_PSOC_PREFIX"/fan6_input", + INV_PSOC_PREFIX"/fan7_input", + INV_PSOC_PREFIX"/fan8_input", + INV_PSOC_PREFIX"/rpm_psu1", + INV_PSOC_PREFIX"/rpm_psu2", }; -#define _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) \ - { #prj"fan"#id"_present", #prj"fan"#id"_fault", #prj"fan"#id"_front_speed_rpm", \ - #prj"fan"#id"_direction", #prj"fan_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" } - -#define MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) - -#define MAKE_FAN_PATH_ON_PSU(folder) \ - {"", #folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ - "", #folder"/psu_fan1_duty_cycle_percentage", "" } - #define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ { \ { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ 0x0, \ - (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ 0, \ 0, \ ONLP_FAN_MODE_INVALID, \ @@ -82,14 +52,14 @@ enum fan_id { { \ { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ 0x0, \ - (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ 0, \ 0, \ ONLP_FAN_MODE_INVALID, \ } /* Static fan information */ -onlp_fan_info_t linfo[] = { +onlp_fan_info_t linfo[FAN_MAX] = { { }, /* Not used */ MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), @@ -97,6 +67,8 @@ onlp_fan_info_t linfo[] = { MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), MAKE_FAN_INFO_NODE_ON_PSU(1,1), MAKE_FAN_INFO_NODE_ON_PSU(2,1), }; @@ -108,78 +80,41 @@ onlp_fan_info_t linfo[] = { } \ } while(0) - static int _onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) { - int value, ret; + int value, ret; + char vstr[32], *vstrp = vstr, **vp = &vstrp; - /* get fan present status - */ - ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + memset(vstr, 0, 32); + /* get fan present status */ + ret = onlp_file_read_str(vp, FAN_GPI_ON_MAIN_BOARD); if (ret < 0) { return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%x", &value); + if (value & (1 << (fid-1))) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + else { + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + } - if (value == 0) { - return ONLP_STATUS_OK; - } - info->status |= ONLP_FAN_STATUS_PRESENT; - - - /* get fan fault status (turn on when any one fails) - */ - ret = onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid); + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); if (ret < 0) { return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; - if (value > 0) { - info->status |= ONLP_FAN_STATUS_FAILED; - } + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); - - /* get fan direction (both : the same) - */ - ret = onlp_file_read_int(&value, "%s""fan%d_direction", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - info->status |= value ? ONLP_FAN_STATUS_B2F : ONLP_FAN_STATUS_F2B; - - - /* get front fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - info->rpm = value; - - /* get rear fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - /* take the min value from front/rear fan speed - */ - if (info->rpm > value) { - info->rpm = value; - } - - /* get speed percentage from rpm - */ - ret = onlp_file_read_int(&value, "%s""fan_max_speed_rpm", FAN_BOARD_PATH); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - info->percentage = (info->rpm * 100)/value; - - return ONLP_STATUS_OK; + return ONLP_STATUS_OK; } @@ -212,28 +147,37 @@ _onlp_get_fan_direction_on_psu(void) static int -_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info) { - int val = 0; + int value, ret, index; + char vstr[32], *vstrp = vstr, **vp = &vstrp; - info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; - /* get fan direction - */ + /* get fan direction */ info->status |= _onlp_get_fan_direction_on_psu(); - /* get fan fault status - */ - if (psu_pmbus_info_get(pid, "psu_fan1_fault", &val) == ONLP_STATUS_OK) { - info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + if (info->status & ONLP_FAN_STATUS_FAILED) { + return ONLP_STATUS_OK; } - /* get fan speed - */ - if (psu_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { - info->rpm = val; - info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + index = ONLP_OID_ID_GET(info->hdr.id); + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); return ONLP_STATUS_OK; } @@ -260,7 +204,7 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) switch (local_id) { - case FAN_1_ON_PSU1: + case FAN_1_ON_PSU1: case FAN_1_ON_PSU2: rc = _onlp_fani_info_get_fan_on_psu(local_id, info); break; @@ -270,7 +214,9 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) case FAN_4_ON_MAIN_BOARD: case FAN_5_ON_MAIN_BOARD: case FAN_6_ON_MAIN_BOARD: - rc =_onlp_fani_info_get_fan(local_id, info); + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + rc = _onlp_fani_info_get_fan(local_id, info); break; default: rc = ONLP_STATUS_E_INVALID; @@ -305,15 +251,18 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) switch (fid) { - case FAN_1_ON_PSU_1: - return psu_pmbus_info_set(PSU1_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_PSU_2: - return psu_pmbus_info_set(PSU2_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_FAN_BOARD: - case FAN_2_ON_FAN_BOARD: - case FAN_3_ON_FAN_BOARD: - case FAN_4_ON_FAN_BOARD: - case FAN_5_ON_FAN_BOARD: + case FAN_1_ON_PSU1: + return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p); + case FAN_1_ON_PSU2: + return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p); + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: path = FAN_NODE(fan_duty_cycle_percentage); break; default: diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/ledi.c index 9cfd216b..a695afda 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/ledi.c @@ -1,38 +1,21 @@ /************************************************************ - * + * ledi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include #include #include +#include #include #include #include #include "platform_lib.h" -#define prefix_path "/sys/class/leds/inventec_d7032q28b_led::" #define filename "brightness" #define VALIDATE(_id) \ @@ -42,18 +25,16 @@ } \ } while(0) -/* LED related data - */ -enum onlp_led_id +static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */ { - LED_RESERVED = 0, - LED_DIAG, - LED_LOC, - LED_FAN, - LED_PSU1, - LED_PSU2 + "reserved", + INV_CPLD_PREFIX"/%s_led", + INV_PSOC_PREFIX"/fan_led_%s1", + INV_PSOC_PREFIX"/fan_led_%s2", + INV_PSOC_PREFIX"/fan_led_%s3", + INV_PSOC_PREFIX"/fan_led_%s4", }; - + enum led_light_mode { LED_MODE_OFF = 0, LED_MODE_GREEN, @@ -75,15 +56,14 @@ typedef struct led_light_mode_map { } led_light_mode_map_t; led_light_mode_map_t led_map[] = { -{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, -{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, -{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED}, -{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, -{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, -{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, -{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} + {LED_SYS, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_SYS, LED_MODE_RED, ONLP_LED_MODE_RED}, + {LED_FAN1,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN2,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN3,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN4,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, }; static char last_path[][10] = /* must map with onlp_led_id */ @@ -99,51 +79,41 @@ static char last_path[][10] = /* must map with onlp_led_id */ /* * Get the information for the given LED OID. */ -static onlp_led_info_t linfo[] = +static onlp_led_info_t linfo[LED_MAX] = { { }, /* Not used */ { - { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 1 (DIAG LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_SYS), "Chassis LED (SYSTEM LED)", 0 }, ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 2 (LOC LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN1), "Fan LED 1 (FAN1 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_BLUE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 3 (FAN LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN2), "Fan LED 2 (FAN2 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 4 (PSU1 LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN3), "Fan LED 3 (FAN3 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN4), "Fan LED 4 (FAN4 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, }; -static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) -{ - int i, nsize = sizeof(led_map)/sizeof(led_map[0]); - - for (i = 0; i < nsize; i++) - { - if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) - { - return led_map[i].onlp_led_mode; - } - } - - return 0; -} - static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) { int i, nsize = sizeof(led_map)/sizeof(led_map[0]); @@ -168,41 +138,113 @@ onlp_ledi_init(void) /* * Diag LED Off */ - onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF); + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_SYS), ONLP_LED_MODE_OFF); return ONLP_STATUS_OK; } +int onlp_chassis_led_read(char *pathp, char *buf, size_t len) +{ + FILE * fp; + + fp = fopen (pathp, "r"); + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + if( fgets (buf, len, fp) == NULL ) { + perror("Error fgets operation"); + } + fclose(fp); + + return(0); +} + int onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) { - int local_id; - char data[2] = {0}; - char fullpath[50] = {0}; + int local_id, gret = 0, rret = 0; + char fullpath_grn[50] = {0}; + char fullpath_red[50] = {0}; + int gvalue = 0, rvalue = 0; + char buf[32] = {0}; VALIDATE(id); local_id = ONLP_OID_ID_GET(id); /* get fullpath */ - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + switch (local_id) { + case LED_SYS: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + gret = onlp_chassis_led_read(fullpath_grn, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + gvalue = 1; + } + + rret = onlp_chassis_led_read(fullpath_red, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + rvalue = 1; + } + if (gret < 0 && rret < 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = -1; + rvalue = -1; + } + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + if (onlp_file_read_int(&gvalue, fullpath_grn) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = 0; + } + if (onlp_file_read_int(&rvalue, fullpath_red) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + rvalue = 0; + } + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + gvalue = -1; + rvalue = -1; + break; + } - /* Set the onlp_oid_hdr_t and capabilities */ + /* Set the onlp_oid_hdr_t and capabilities */ *info = linfo[ONLP_OID_ID_GET(id)]; - /* Set LED mode */ - if (onlp_file_read_string(fullpath, data, sizeof(data), 0) != 0) { - DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); - return ONLP_STATUS_E_INTERNAL; + if (gvalue == 1 && rvalue == 0) { + info->mode = ONLP_LED_MODE_GREEN; + info->status |= ONLP_LED_STATUS_ON; } - - info->mode = driver_to_onlp_led_mode(local_id, atoi(data)); - - /* Set the on/off status */ - if (info->mode != ONLP_LED_MODE_OFF) { - info->status |= ONLP_LED_STATUS_ON; + else + if (gvalue == 0 && rvalue == 1) { + info->mode = ONLP_LED_MODE_RED; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 1 && rvalue == 1) { + info->mode = ONLP_LED_MODE_ORANGE; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 0) { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_ON; + } + else { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_FAILED; } - return ONLP_STATUS_OK; } @@ -242,7 +284,20 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) VALIDATE(id); local_id = ONLP_OID_ID_GET(id); - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + switch (local_id) { + case LED_SYS: + sprintf(fullpath, "%s%s/%s", INV_CPLD_PREFIX, last_path[local_id], filename); + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath, "%s%s/%s", INV_PSOC_PREFIX, last_path[local_id], filename); + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + return ONLP_STATUS_E_INTERNAL; + } if (onlp_file_write_int(onlp_to_driver_led_mode(local_id, mode), fullpath, NULL) != 0) { diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.c index 9e4c5e06..43225d68 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.c @@ -1,27 +1,10 @@ /************************************************************ - * + * platform_lib.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include @@ -152,10 +135,14 @@ int psu_pmbus_info_get(int id, char *node, int *value) *value = 0; if (PSU1_ID == id) { - ret = onlp_file_read_int(value, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + ret = onlp_file_read_int(value, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + } + else + if (PSU2_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); } else { - ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + return ONLP_STATUS_E_INTERNAL; } if (ret < 0) { @@ -171,10 +158,10 @@ int psu_pmbus_info_set(int id, char *node, int value) switch (id) { case PSU1_ID: - sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + sprintf(path, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); break; case PSU2_ID: - sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + sprintf(path, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); break; default: return ONLP_STATUS_E_UNSUPPORTED; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.h index 2a50bf9e..d834b3cd 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/platform_lib.h @@ -1,61 +1,98 @@ /************************************************************ - * + * platform_lib.h * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #ifndef __PLATFORM_LIB_H__ #define __PLATFORM_LIB_H__ #include "x86_64_inventec_d7032q28b_log.h" -#define CHASSIS_FAN_COUNT 6 -#define CHASSIS_THERMAL_COUNT 5 +#define ONLP_NODE_MAX_INT_LEN (8) +#define ONLP_NODE_MAX_PATH_LEN (64) -#define PSU1_ID 1 -#define PSU2_ID 2 +#define INV_CPLD_COUNT (1) +#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/" +#define INV_PSOC_PREFIX "/sys/bus/i2c/devices/0-0066/" +#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/" +#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/" -#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/11-005b/" -#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/10-0058/" +#define CHASSIS_SFP_COUNT (32) + +/* + * Definitions of Chassis EEPROM + */ +#define EEPROM_NODE(node) INV_EPRM_PREFIX#node + +/* + * Definitions of PSU device + */ +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE_FIRST, + THERMAL_CPU_CORE_3, + THERMAL_CPU_CORE_4, + THERMAL_CPU_CORE_LAST, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_MAX +}; +#define CHASSIS_THERMAL_COUNT (9) + +enum fan_id { + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_2_ON_MAIN_BOARD, + FAN_3_ON_MAIN_BOARD, + FAN_4_ON_MAIN_BOARD, + FAN_5_ON_MAIN_BOARD, + FAN_6_ON_MAIN_BOARD, + FAN_7_ON_MAIN_BOARD, + FAN_8_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2, + FAN_MAX +}; +#define CHASSIS_FAN_COUNT (8) + +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_SYS, + LED_FAN1, + LED_FAN2, + LED_FAN3, + LED_FAN4, + LED_MAX +}; +#define CHASSIS_LED_COUNT (1) + +enum onlp_psu_id +{ + PSU_RESERVED = 0, + PSU1_ID, + PSU2_ID, + PSU_MAX +}; +#define CHASSIS_PSU_COUNT (2) + +#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX +#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX #define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node #define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node -#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/11-0053/" -#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/10-0050/" - -#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node -#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node - -#define FAN_BOARD_PATH "/sys/devices/platform/fan/" -#define FAN_NODE(node) FAN_BOARD_PATH#node - -#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0057/eeprom" - -int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); -int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); - -int psu_pmbus_info_get(int id, char *node, int *value); -int psu_pmbus_info_set(int id, char *node, int value); +#define PSU1_AC_HWMON_PREFIX INV_CPLD_PREFIX +#define PSU2_AC_HWMON_PREFIX INV_CPLD_PREFIX typedef enum psu_type { PSU_TYPE_UNKNOWN, @@ -70,6 +107,24 @@ typedef enum psu_type { psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +/* + * Definitions of FAN device + */ +#define FAN_BOARD_PATH INV_PSOC_PREFIX +#define FAN_NODE(node) FAN_BOARD_PATH#node + +/* + * Prototypes + */ +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_pmbus_info_set(int id, char *node, int value); + #define DEBUG_MODE 0 #if (DEBUG_MODE == 1) diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/psui.c index 8d12741e..b2247fb0 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/psui.c @@ -1,40 +1,24 @@ /************************************************************ - * + * psui.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include #include #include #include +#include #include "platform_lib.h" -#define PSU_STATUS_PRESENT 1 -#define PSU_STATUS_POWER_GOOD 1 - -#define PSU_NODE_MAX_INT_LEN 8 -#define PSU_NODE_MAX_PATH_LEN 64 +#define PSU_STATUS_PRESENT (0) +#define PSU_STATUS_POWER_GOOD (1) +#define PSU_STATUS_UNPOWERED (2) +#define PSU_STATUS_FAULT (4) +#define PSU_STATUS_UNINSTALLED (7) #define VALIDATE(_id) \ do { \ @@ -43,55 +27,57 @@ } \ } while(0) +static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_CPLD_PREFIX"/psu0", + INV_CPLD_PREFIX"/psu1", +}; + +static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_PSOC_PREFIX"/psu1_%s", + INV_PSOC_PREFIX"/psu2_%s", +}; + +static char* module2_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_PSOC_PREFIX"/psoc_psu1_%s", + INV_PSOC_PREFIX"/psoc_psu2_%s", +}; + static int psu_status_info_get(int id, char *node, int *value) { int ret = 0; - char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; *value = 0; if (PSU1_ID == id) { - sprintf(node_path, "%s%s", PSU1_AC_HWMON_PREFIX, node); + sprintf(node_path, status_devfiles__[id]); } else if (PSU2_ID == id) { - sprintf(node_path, "%s%s", PSU2_AC_HWMON_PREFIX, node); + sprintf(node_path, status_devfiles__[id]); } - ret = onlp_file_read_int(value, node_path); + ret = onlp_file_read_str(vp, node_path); if (ret < 0) { AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); return ONLP_STATUS_E_INTERNAL; } - return ret; + if (!isdigit(*vstrp)) { + return ONLP_STATUS_E_INTERNAL; + } + *value = *vstrp - '0'; + return ONLP_STATUS_OK; } -static int -psu_ym2651_pmbus_info_get(int id, char *node, int *value) -{ - int ret = 0; - char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; - - *value = 0; - - if (PSU1_ID == id) { - sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); - } - else { - sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); - } - - ret = onlp_file_read_int(value, node_path); - - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); - return ONLP_STATUS_E_INTERNAL; - } - - return ret; -} int onlp_psui_init(void) @@ -100,83 +86,100 @@ onlp_psui_init(void) } static int -psu_ym2651_info_get(onlp_psu_info_t* info) +psu_module_info_get(int id, onlp_psu_info_t* info) { - int val = 0; - int index = ONLP_OID_ID_GET(info->hdr.id); + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + int value = 0; - if (info->status & ONLP_PSU_STATUS_FAILED) { - return ONLP_STATUS_OK; + info->caps |= ONLP_PSU_CAPS_DC12; + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "vout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path); + return ONLP_STATUS_E_INTERNAL; + } + info->mvout = value; + info->caps |= ONLP_PSU_CAPS_VOUT; + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "iout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path); + } + else { + info->miout = value; + info->caps |= ONLP_PSU_CAPS_IOUT; } - /* Set the associated oid_table */ - info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); - info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); - - /* Read voltage, current and power */ - if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { - info->mvout = val; - info->caps |= ONLP_PSU_CAPS_VOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "pout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path); + } + else { + info->mpout = value; + info->caps |= ONLP_PSU_CAPS_POUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { - info->miout = val; - info->caps |= ONLP_PSU_CAPS_IOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "vin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path); + } + else { + info->mvin = value; + info->caps |= ONLP_PSU_CAPS_VIN; } - if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { - info->mpout = val; - info->caps |= ONLP_PSU_CAPS_POUT; - } - - return ONLP_STATUS_OK; -} - -#include -#define DC12V_750_REG_TO_CURRENT(low, high) (((low << 4 | high >> 4) * 20 * 1000) / 754) -#define DC12V_750_REG_TO_VOLTAGE(low, high) ((low << 4 | high >> 4) * 25) - -static int -psu_dc12v_750_info_get(onlp_psu_info_t* info) -{ - int pid = ONLP_OID_ID_GET(info->hdr.id); - int bus = (PSU1_ID == pid) ? 11 : 10; - int iout_low, iout_high; - int vout_low, vout_high; - - /* Set capability - */ - info->caps = ONLP_PSU_CAPS_DC12; - - if (info->status & ONLP_PSU_STATUS_FAILED) { - return ONLP_STATUS_OK; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "iin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path); + } + else { + info->miin = value; + info->caps |= ONLP_PSU_CAPS_IIN; } - /* Get current - */ - iout_low = onlp_i2c_readb(bus, 0x6f, 0x0, ONLP_I2C_F_FORCE); - iout_high = onlp_i2c_readb(bus, 0x6f, 0x1, ONLP_I2C_F_FORCE); - - if ((iout_low >= 0) && (iout_high >= 0)) { - info->miout = DC12V_750_REG_TO_CURRENT(iout_low, iout_high); - info->caps |= ONLP_PSU_CAPS_IOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module2_devfiles__[id], "pin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path); + } + else { + info->mpin = value; + info->caps |= ONLP_PSU_CAPS_PIN; } - /* Get voltage - */ - vout_low = onlp_i2c_readb(bus, 0x6f, 0x2, ONLP_I2C_F_FORCE); - vout_high = onlp_i2c_readb(bus, 0x6f, 0x3, ONLP_I2C_F_FORCE); - - if ((vout_low >= 0) && (vout_high >= 0)) { - info->mvout = DC12V_750_REG_TO_VOLTAGE(vout_low, vout_high); - info->caps |= ONLP_PSU_CAPS_VOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "model"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->model, *vp, ret-1); + } + else { + AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->model, "N/A", 3); } - /* Get power based on current and voltage - */ - if ((info->caps & ONLP_PSU_CAPS_IOUT) && (info->caps & ONLP_PSU_CAPS_VOUT)) { - info->mpout = (info->miout * info->mvout) / 1000; - info->caps |= ONLP_PSU_CAPS_POUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "sn"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->serial, *vp, ret-1); + } + else { + AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->serial, "N/A", 3); } return ONLP_STATUS_OK; @@ -189,10 +192,22 @@ static onlp_psu_info_t pinfo[] = { { }, /* Not used */ { - { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + { + ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1) + } + }, }, { - { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + { + ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2) + } + }, } }; @@ -202,7 +217,6 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) int val = 0; int ret = ONLP_STATUS_OK; int index = ONLP_OID_ID_GET(id); - psu_type_t psu_type; VALIDATE(id); @@ -210,63 +224,27 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ /* Get the present state */ - if (psu_status_info_get(index, "psu_present", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) { + printf("Unable to read PSU(%d) node(psu)\r\n", index); + return ret; } - if (val != PSU_STATUS_PRESENT) { - info->status &= ~ONLP_PSU_STATUS_PRESENT; - return ONLP_STATUS_OK; + if (val == 0) { + info->status = ONLP_PSU_STATUS_PRESENT; } - info->status |= ONLP_PSU_STATUS_PRESENT; - - - /* Get power good status */ - if (psu_status_info_get(index, "psu_power_good", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + else + if (val == 1) { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ret; + } + else { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; } - if (val != PSU_STATUS_POWER_GOOD) { - info->status |= ONLP_PSU_STATUS_FAILED; - } - - - /* Get PSU type - */ - psu_type = get_psu_type(index, info->model, sizeof(info->model)); - - switch (psu_type) { - case PSU_TYPE_AC_F2B: - case PSU_TYPE_AC_B2F: - info->caps = ONLP_PSU_CAPS_AC; - ret = psu_ym2651_info_get(info); - break; - case PSU_TYPE_DC_48V_F2B: - case PSU_TYPE_DC_48V_B2F: - info->caps = ONLP_PSU_CAPS_DC48; - ret = psu_ym2651_info_get(info); - break; - case PSU_TYPE_DC_12V_F2B: - case PSU_TYPE_DC_12V_B2F: - case PSU_TYPE_DC_12V_FANLESS: - ret = psu_dc12v_750_info_get(info); - break; - case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ - info->status |= ONLP_PSU_STATUS_UNPLUGGED; - info->status &= ~ONLP_PSU_STATUS_FAILED; - ret = ONLP_STATUS_OK; - break; - default: - ret = ONLP_STATUS_E_UNSUPPORTED; - break; + if ((ret = psu_module_info_get(index, info)) != ONLP_STATUS_OK) { + printf("Unable to read PSU(%d) module information\r\n", index); } return ret; } - -int -onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sfpi.c index 0b568114..6bd13c56 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sfpi.c @@ -1,27 +1,10 @@ /************************************************************ - * + * sfpi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include @@ -34,19 +17,17 @@ #include #include "platform_lib.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; +static char sfp_node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; -#define MUX_START_INDEX 18 -#define NUM_OF_SFP_PORT 32 +#define NUM_OF_SFP_PORT (CHASSIS_SFP_COUNT) static const int sfp_mux_index[NUM_OF_SFP_PORT] = { - 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 +22, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 36, 37, + 6, 7, 8, 9, 10, 11, 12, 13, +14, 15, 16, 17, 18, 19, 20, 21 }; -#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]+MUX_START_INDEX) +#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]) static int sfp_node_read_int(char *node_path, int *value, int data_len) @@ -67,9 +48,7 @@ sfp_node_read_int(char *node_path, int *value, int data_len) static char* sfp_get_port_path(int port, char *node_name) { - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-0050/%s", - FRONT_PORT_TO_MUX_INDEX(port), - node_name); + sprintf(sfp_node_path, "/sys/class/swps/port%d/%s", port, node_name); return sfp_node_path; } @@ -111,66 +90,69 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - + char* path = sfp_get_port_path(port, "present"); if (sfp_node_read_int(path, &present, 0) != 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - + if (present == 0) { + present = 1; + } + else + if (present == 1) { + present = 0; + } + else { + AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port); + return ONLP_STATUS_E_INTERNAL; + } return present; } int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[4]; - char* path; - FILE* fp; - - path = sfp_get_port_path(0, "sfp_is_present_all"); - fp = fopen(path, "r"); - - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3 - ); - fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - - /* Convert to 64 bit integer in port order */ - int i = 0; uint32_t presence_all = 0 ; - for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { - presence_all <<= 8; - presence_all |= bytes[i]; + int port, ret; + + for (port = 0; port < NUM_OF_SFP_PORT; port++) { + ret = onlp_sfpi_is_present(port); + if (ret == 1) { + presence_all |= (1<>= 1; } - return ONLP_STATUS_OK; } int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - int len = 0; +#if 1 + int bus = FRONT_PORT_TO_MUX_INDEX(port); + memset(data, 0, 256); + /* Read eeprom information into data[] */ + if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0) + { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#else + char* path; + int len = 0; /* * Read the SFP eeprom into data[] * @@ -178,15 +160,21 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) * Return OK if eeprom is read */ memset(data, 0, 256); - - if (onlp_file_read((uint8_t*)data, 256, &len, path) < 0) { + path = sfp_get_port_path(port, "eeprom"); + if (onlp_file_read(&data[0], 256, &len, path) < 0) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - +#endif return ONLP_STATUS_OK; } +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return onlp_sfpi_eeprom_read( port, data); +} + int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) { diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sysi.c index d3a4b629..4b774fda 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/sysi.c @@ -1,27 +1,10 @@ /************************************************************ - * + * sysi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include @@ -38,19 +21,12 @@ #include "platform_lib.h" -#define NUM_OF_THERMAL_ON_MAIN_BROAD CHASSIS_THERMAL_COUNT -#define NUM_OF_FAN_ON_MAIN_BROAD CHASSIS_FAN_COUNT -#define NUM_OF_PSU_ON_MAIN_BROAD 2 -#define NUM_OF_LED_ON_MAIN_BROAD 5 +#define NUM_OF_CPLD INV_CPLD_COUNT -#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/" -#define NUM_OF_CPLD 3 -static char arr_cplddev_name[NUM_OF_CPLD][10] = -{ - "4-0060", - "5-0062", - "6-0064" -}; +#define NUM_OF_THERMAL_ON_MAIN_BROAD (CHASSIS_THERMAL_COUNT) +#define NUM_OF_FAN_ON_MAIN_BROAD (CHASSIS_FAN_COUNT) +#define NUM_OF_PSU_ON_MAIN_BROAD (CHASSIS_PSU_COUNT) +#define NUM_OF_LED_ON_MAIN_BROAD (CHASSIS_LED_COUNT) const char* onlp_sysi_platform_get(void) @@ -62,7 +38,7 @@ int onlp_sysi_onie_data_get(uint8_t** data, int* size) { uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(onlp_file_read(rdata, 256, size, EEPROM_NODE(eeprom)) == ONLP_STATUS_OK) { if(*size == 256) { *data = rdata; return ONLP_STATUS_OK; @@ -74,27 +50,6 @@ onlp_sysi_onie_data_get(uint8_t** data, int* size) return ONLP_STATUS_E_INTERNAL; } -int -onlp_sysi_platform_info_get(onlp_platform_info_t* pi) -{ - int i, v[NUM_OF_CPLD]={0}; - for (i=0; i < NUM_OF_CPLD; i++) { - v[i] = 0; - if(onlp_file_read_int(v+i, "%s%s/version", PREFIX_PATH_ON_CPLD_DEV, arr_cplddev_name[i]) < 0) { - return ONLP_STATUS_E_INTERNAL; - } - } - pi->cpld_versions = aim_fstrdup("%d.%d.%d", v[0], v[1], v[2]); - return 0; -} - -void -onlp_sysi_platform_info_free(onlp_platform_info_t* pi) -{ - aim_free(pi->cpld_versions); -} - - int onlp_sysi_oids_get(onlp_oid_t* table, int max) { @@ -129,167 +84,27 @@ onlp_sysi_oids_get(onlp_oid_t* table, int max) return 0; } -typedef struct fan_ctrl_policy { - int duty_cycle; - int temp_down_adjust; /* The boundary temperature to down adjust fan speed */ - int temp_up_adjust; /* The boundary temperature to up adjust fan speed */ -} fan_ctrl_policy_t; - -fan_ctrl_policy_t fan_ctrl_policy_f2b[] = { -{32, 0, 174000}, -{38, 170000, 182000}, -{50, 178000, 190000}, -{63, 186000, 0} -}; - -fan_ctrl_policy_t fan_ctrl_policy_b2f[] = { -{32, 0, 140000}, -{38, 135000, 150000}, -{50, 145000, 160000}, -{69, 155000, 0} -}; - -#define FAN_DUTY_CYCLE_MAX 100 -#define FAN_SPEED_CTRL_PATH "/sys/bus/i2c/devices/2-0066/fan_duty_cycle_percentage" - -/* - * 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 - */ -int -onlp_sysi_platform_manage_fans(void) +static char *arr_cplddev_version[NUM_OF_CPLD] = { - int i = 0, arr_size, temp; - fan_ctrl_policy_t *policy; - int cur_duty_cycle, new_duty_cycle; - onlp_thermal_info_t thermal_1, thermal_2, thermal_3; + INV_CPLD_PREFIX"/version", +}; - int fd, len; - char buf[10] = {0}; - - /* Get each fan status - */ - for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) - { - onlp_fan_info_t fan_info; - - if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD]={0}; + for (i=0; i < NUM_OF_CPLD; i++) { + v[i] = 0; + if(onlp_file_read_int(v+i, arr_cplddev_version[i]) < 0) { return ONLP_STATUS_E_INTERNAL; } - - /* Decision 1: Set fan as full speed if any fan is failed. - */ - if (fan_info.status & ONLP_FAN_STATUS_FAILED) { - AIM_LOG_ERROR("Fan(%d) is not working, set the other fans as full speed\r\n", i); - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); - } - - /* Decision 1.1: Set fan as full speed if any fan is not present. - */ - if (!(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { - AIM_LOG_ERROR("Fan(%d) is not present, set the other fans as full speed\r\n", i); - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); - } - - /* Get fan direction (Only get the first one since all fan direction are the same) - */ - if (i == 1) { - if (fan_info.status & ONLP_FAN_STATUS_F2B) { - policy = fan_ctrl_policy_f2b; - arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_f2b); - } - else { - policy = fan_ctrl_policy_b2f; - arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_b2f); - } - } } - - /* Get current fan speed - */ - fd = open(FAN_SPEED_CTRL_PATH, O_RDONLY); - if (fd == -1){ - AIM_LOG_ERROR("Unable to open fan speed control node (%s)", FAN_SPEED_CTRL_PATH); - return ONLP_STATUS_E_INTERNAL; - } - - len = read(fd, buf, sizeof(buf)); - close(fd); - if (len <= 0) { - AIM_LOG_ERROR("Unable to read fan speed from (%s)", FAN_SPEED_CTRL_PATH); - return ONLP_STATUS_E_INTERNAL; - } - cur_duty_cycle = atoi(buf); - - - /* Decision 2: If no matched fan speed is found from the policy, - * use FAN_DUTY_CYCLE_MIN as default speed - */ - for (i = 0; i < arr_size; i++) { - if (policy[i].duty_cycle != cur_duty_cycle) - continue; - - break; - } - - if (i == arr_size) { - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), policy[0].duty_cycle); - } - - /* Get current temperature - */ - if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(2), &thermal_1) != ONLP_STATUS_OK || - onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(3), &thermal_2) != ONLP_STATUS_OK || - onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(4), &thermal_3) != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to read thermal status"); - return ONLP_STATUS_E_INTERNAL; - } - temp = thermal_1.mcelsius + thermal_2.mcelsius + thermal_3.mcelsius; - - - /* Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature - */ - new_duty_cycle = cur_duty_cycle; - - if ((temp >= policy[i].temp_up_adjust) && (i != (arr_size-1))) { - new_duty_cycle = policy[i+1].duty_cycle; - } - else if ((temp <= policy[i].temp_down_adjust) && (i != 0)) { - new_duty_cycle = policy[i-1].duty_cycle; - } - - if (new_duty_cycle == cur_duty_cycle) { - /* Duty cycle does not change, just return */ - return ONLP_STATUS_OK; - } - - return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), new_duty_cycle); + pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + return 0; } -int -onlp_sysi_platform_manage_leds(void) +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) { - return ONLP_STATUS_E_UNSUPPORTED; + aim_free(pi->cpld_versions); } - diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/thermali.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/thermali.c index 94f5353c..fb7e2d03 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/onlp/builds/src/module/src/thermali.c @@ -1,23 +1,8 @@ /************************************************************ - * + * thermali.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * * Thermal Sensor Platform Implementation. @@ -37,42 +22,38 @@ } \ } while(0) -enum onlp_thermal_id -{ - THERMAL_RESERVED = 0, - THERMAL_CPU_CORE, - THERMAL_1_ON_MAIN_BROAD, - THERMAL_2_ON_MAIN_BROAD, - THERMAL_3_ON_MAIN_BROAD, - THERMAL_1_ON_PSU1, - THERMAL_1_ON_PSU2, -}; - -static char* devfiles__[] = /* must map with onlp_thermal_id */ +static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */ { "reserved", - NULL, /* CPU_CORE files */ - "/sys/bus/i2c/devices/3-0048*temp1_input", - "/sys/bus/i2c/devices/3-0049*temp1_input", - "/sys/bus/i2c/devices/3-004a*temp1_input", - "/sys/bus/i2c/devices/3-004b*temp1_input", - "/sys/bus/i2c/devices/11-005b*psu_temp1_input", - "/sys/bus/i2c/devices/10-0058*psu_temp1_input", + INV_CTMP_PREFIX"/temp2_%s", + INV_CTMP_PREFIX"/temp3_%s", + INV_CTMP_PREFIX"/temp4_%s", + INV_CTMP_PREFIX"/temp5_%s", + INV_PSOC_PREFIX"/temp1_input", + INV_PSOC_PREFIX"/temp2_input", + INV_PSOC_PREFIX"/temp3_input", + INV_PSOC_PREFIX"/temp4_input", + INV_PSOC_PREFIX"/temp5_input", + INV_PSOC_PREFIX"/thermal_psu1", + INV_PSOC_PREFIX"/thermal_psu2", }; -static char* cpu_coretemp_files[] = - { - "/sys/devices/platform/coretemp.0*temp2_input", - "/sys/devices/platform/coretemp.0*temp3_input", - "/sys/devices/platform/coretemp.0*temp4_input", - "/sys/devices/platform/coretemp.0*temp5_input", - NULL, - }; - /* Static values */ -static onlp_thermal_info_t linfo[] = { +static onlp_thermal_info_t linfo[THERMAL_MAX] = { { }, /* Not used */ - { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "CPU Core 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_4), "CPU Core 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_LAST), "CPU Core 3", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, @@ -92,6 +73,10 @@ static onlp_thermal_info_t linfo[] = { ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS @@ -99,7 +84,7 @@ static onlp_thermal_info_t linfo[] = { { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS - } + }, }; /* @@ -132,10 +117,16 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) /* Set the onlp_oid_hdr_t and capabilities */ *info = linfo[local_id]; - if(local_id == THERMAL_CPU_CORE) { - int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); - return rv; - } + if(local_id >= THERMAL_CPU_CORE_FIRST && local_id <= THERMAL_CPU_CORE_LAST) { + char desc[32], *dp = &desc[0]; + int rv = onlp_file_read_str(&dp, devfiles__[local_id], "label"); + if (rv > 0) { + memset (info->hdr.description, 0, ONLP_OID_DESC_SIZE); + strncpy(info->hdr.description, dp, rv); + } + /* Set the onlp_oid_hdr_t and capabilities */ + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id], "input"); + } return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]); } diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/platform-config/r0/src/python/x86_64_inventec_d7032q28b_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/platform-config/r0/src/python/x86_64_inventec_d7032q28b_r0/__init__.py index 62c0e953..c60a6a32 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/platform-config/r0/src/python/x86_64_inventec_d7032q28b_r0/__init__.py +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7032q28b/platform-config/r0/src/python/x86_64_inventec_d7032q28b_r0/__init__.py @@ -5,11 +5,16 @@ class OnlPlatform_x86_64_inventec_d7032q28b_r0(OnlPlatformInventec, OnlPlatformPortConfig_32x100): PLATFORM='x86-64-inventec-d7032q28b-r0' MODEL="X86-D7032Q28B" - SYS_OBJECT_ID="7032.28" + SYS_OBJECT_ID=".7032.1" def baseconfig(self): os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0") self.insmod('inv_platform') self.insmod('inv_psoc') self.insmod('inv_cpld') + self.new_i2c_device('inv_eeprom', 0x53, 0) + self.insmod('inv_eeprom') + self.insmod('swps') + self.insmod('vpd') + self.insmod('inv_pthread') return True diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/.gitignore new file mode 100644 index 00000000..2afbde34 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/.gitignore @@ -0,0 +1,2 @@ +*x86*64*inventec*d7054q28b*.mk +onlpdump.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/Makefile index 5ebf3b73..b49967f2 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/Makefile +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/Makefile @@ -1,5 +1,5 @@ KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 -KMODULES := $(wildcard *.c) +KMODULES := src VENDOR := inventec BASENAME := x86-64-inventec-d7054q28b ARCH := x86_64 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/Makefile new file mode 100644 index 00000000..c3bb6302 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/Makefile @@ -0,0 +1,8 @@ +obj-m += inv_platform.o +obj-m += inv_cpld.o +obj-m += inv_psoc.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o transceiver.o inv_mux.o +obj-m += vpd.o +vpd-objs := inv_vpd.o onie_tlvinfo.o +obj-m += inv_pthread.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_cpld.c similarity index 98% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_cpld.c rename to packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_cpld.c index 683ffa0f..21874f8c 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_cpld.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_cpld.c @@ -15,8 +15,6 @@ #include #include -//#include "I2CHostCommunication.h" - #define USE_SMBUS 1 /* definition */ @@ -162,7 +160,6 @@ 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; @@ -329,8 +326,6 @@ 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; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..a0f5ce34 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.c @@ -0,0 +1,281 @@ +#include +#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 = "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; + mod_dsc = "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; + mod_dsc = "Hedera force mode"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + 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; + mod_dsc = "Normal mode :48"; + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_69_PAC9548: + 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; + mod_dsc = "Normal mode :69"; + 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__); +} +EXPORT_SYMBOL(clean_mux_gpio); + + +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; +} +EXPORT_SYMBOL(reset_mux_gpio); + + +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; +} +EXPORT_SYMBOL(init_mux_gpio); + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..429754a8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_mux.h @@ -0,0 +1,36 @@ +#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) + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_platform.c similarity index 85% rename from packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_platform.c rename to packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_platform.c index ea269700..a11a29d6 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/inv_platform.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_platform.c @@ -1,5 +1,4 @@ #include -//#include #include #include #include @@ -7,12 +6,6 @@ #include #include -//#include -//#include - -//#include -//#define IO_EXPAND_BASE 64 -//#define IO_EXPAND_NGPIO 16 struct inv_i2c_board_info { int ch; @@ -76,9 +69,6 @@ static struct pca954x_platform_mode mux_modes_0_6[] = { {.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, @@ -154,24 +144,6 @@ static struct inv_i2c_board_info i2cdev_list[] = { }; -///////////////////////////////////////////////////////////////////////////////////////// -#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; @@ -181,18 +153,6 @@ static int __init inv_platform_init(void) 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 "I2CHostCommunication.h" - #define IMPLEMENT_IPMI_CODE 1 int USE_IPMI=0; -//================================= + #if IMPLEMENT_IPMI_CODE #include #include @@ -54,7 +52,6 @@ static struct ipmi_recv_msg halt_recv_msg = { .done = dummy_recv_free }; #endif -//================================= #define USE_SMBUS 1 @@ -122,7 +119,6 @@ struct __attribute__ ((__packed__)) psoc_layout { 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) @@ -159,7 +155,7 @@ static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) int ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) { - int rv=0,i; + int rv=0; struct ipmi_system_interface_addr addr; uint8_t _data[data_length]; struct kernel_ipmi_msg msg; @@ -167,10 +163,6 @@ int ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, if(!mutex_trylock(&ipmi_mutex)) return 0; -// for (i=0,rv=1; i +#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); +} + +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]; + +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" ); +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +}; +#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) { + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..6c0e8960 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.c @@ -0,0 +1,2945 @@ +/************************************************************************* + * + * inv_swps.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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_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); +} + +static ssize_t +show_attr_eeprom(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_eeprom, + 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); +} + +/* ========== 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(eeprom, S_IRUGO, show_attr_eeprom, 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); + +/* ========== 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: + 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 + + 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_eeprom) < 0) { + err_attr = "dev_attr_eeprom"; + 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; + } + if (device_create_file(device_p, &dev_attr_eeprom) < 0) { + err_attr = "dev_attr_eeprom"; + 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: + 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: + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..9ca645bc --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_swps.h @@ -0,0 +1,752 @@ +/************************************************************************* + * + * inv_swps.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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.3" +#define SWP_LICENSE "GPL" + +#define SWPS_KERN_VER_AF_3_10 (1) + +/* 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 */ +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_CYPRESS_GA2 + +/* 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) +#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" }, +}; + + +/* ========================================== + * 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_NAB, { {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 */ + }, + {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 + + +#endif /* INV_SWPS_H */ + + + + + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..7e81636e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.c @@ -0,0 +1,354 @@ +/************************************************************************* + * + * inv_vpd.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +static int +__swp_match(struct device *dev, +#ifdef VPD_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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..95676bfa --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/inv_vpd.h @@ -0,0 +1,64 @@ +/************************************************************************* + * + * inv_vpd.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_ENTRY_SIZE (17) +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +#define VPD_KERN_VER_AF_3_10 (1) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.c new file mode 100644 index 00000000..3ef271ac --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.c @@ -0,0 +1,1700 @@ +/************************************************************************* + * + * io_expander.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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; + + +/* ========== 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) */ + }, +}; + + +/* ========== 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; + + 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_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->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; + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + 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: + 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; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +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; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +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__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +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; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +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; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + + +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; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +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"); + 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; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + + + +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.h new file mode 100644 index 00000000..d57dfe15 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/io_expander.h @@ -0,0 +1,185 @@ +/************************************************************************* + * + * io_expander.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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) + +/* 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[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_bitmap_s map_hard_rs0[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[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 (*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/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..303ffde7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,820 @@ +#include +#include +#include +#include +//#include +#include + +//#include +//#include +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +#if 0 +static unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} +#else +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} +#endif + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %d\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %d\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} +EXPORT_SYMBOL(read_eeprom); + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} +EXPORT_SYMBOL(prog_eeprom); + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} +EXPORT_SYMBOL(tlvinfo_decode_tlv); + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} +EXPORT_SYMBOL(tlvinfo_delete_tlv); + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} +EXPORT_SYMBOL(tlvinfo_add_tlv); + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} +#if 0 +int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf) +{ + int tlv_end; + int curr_tlv; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int iFind = 0; + + if( !is_valid_tlvinfo_header(eeprom_hdr) ) { + printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n"); + return -1; + } + + curr_tlv = sizeof(tlvinfo_header_t); + tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while(curr_tlv < tlv_end){ + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv]; + if (!is_valid_tlv(eeprom_tlv)) { + printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n", + curr_tlv); + return -1; + } + + decode_tlv_value(eeprom_tlv, c_buf); + if( eeprom_tlv->type == i_offset){ + iFind = 1; + break; + } + curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + if( iFind == 0 ) + return -1; + else + return 0; +} +#endif diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..74f3c960 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); +//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.c new file mode 100644 index 00000000..6dc22861 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.c @@ -0,0 +1,8267 @@ +/************************************************************************* + * + * transceiver.c + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#include +#include +#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, + .addr_eeprom =0x50, .page_eeprom =-1, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + + +/* ========== 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); +} +EXPORT_SYMBOL(alarm_msg_2_user); + +/* ========== 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; +} +EXPORT_SYMBOL(lock_transvr_obj); + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + +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_eeprom(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_eeprom, + self->eeprom_map_p->page_eeprom, + self->eeprom_map_p->offset_eeprom, + self->eeprom_map_p->length_eeprom, + self->eeprom, + "_common_update_attr_eeprom", + 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; + } + if (_common_update_attr_eeprom(self, show_err) < 0) { + err_str = "_common_update_attr_eeprom"; + 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_eeprom(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, &_common_update_attr_eeprom, + "common_get_eeprom"); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + memset(buf, 0, self->eeprom_map_p->length_eeprom+1); + memcpy(buf, self->eeprom, self->eeprom_map_p->length_eeprom); + *(buf+self->eeprom_map_p->length_eeprom) = '\n'; + return self->eeprom_map_p->length_eeprom+1; +} + +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_eeprom = common_get_eeprom; + 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_eeprom = common_get_eeprom; + 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_eeprom = common_get_eeprom; + 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_eeprom = fake_get_str; + 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; +} +EXPORT_SYMBOL(create_transvr_obj); + +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; +} +EXPORT_SYMBOL(isolate_transvr_obj); + +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; +} +EXPORT_SYMBOL(resync_channel_tier_2); + +/* ----------------------------------------- + * 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) + */ + + +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.h new file mode 100644 index 00000000..7ab56d38 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/modules/builds/src/transceiver.h @@ -0,0 +1,811 @@ +/************************************************************************* + * + * transceiver.h + * + * 2018 Inventec Corporation + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of Inventec Corp. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to Inventec Corporation 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. + * + ************************************************************************/ + +#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_eeprom; int page_eeprom; int offset_eeprom; int length_eeprom; + 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]; + + uint8_t eeprom[256]; + + /* ========== 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_eeprom)(struct transvr_obj_s *self, char *buf_p); + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/lib/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/lib/.gitignore deleted file mode 100644 index 832440b4..00000000 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/lib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libonlp-x86-64-inventec-d7054q28b.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/.gitignore deleted file mode 100644 index 332e166f..00000000 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -x86_64_inventec_d7054q28b.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/fani.c index 25addc7f..0eb6bc37 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/fani.c @@ -1,36 +1,21 @@ /************************************************************ - * + * fani.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * * Fan Platform Implementation Defaults. * ***********************************************************/ +#include #include #include #include #include #include "platform_lib.h" -#define PREFIX_PATH_ON_MAIN_BOARD "/sys/bus/i2c/devices/2-0066/" -#define PREFIX_PATH_ON_PSU "/sys/bus/i2c/devices/" +#define FAN_GPI_ON_MAIN_BOARD INV_PSOC_PREFIX"/fan_gpi" #define MAX_FAN_SPEED 18000 #define MAX_PSU_FAN_SPEED 25500 @@ -38,41 +23,26 @@ #define PROJECT_NAME #define LEN_FILE_NAME 80 -#define FAN_RESERVED 0 -#define FAN_1_ON_MAIN_BOARD 1 -#define FAN_2_ON_MAIN_BOARD 2 -#define FAN_3_ON_MAIN_BOARD 3 -#define FAN_4_ON_MAIN_BOARD 4 -#define FAN_5_ON_MAIN_BOARD 5 -#define FAN_6_ON_MAIN_BOARD 6 -#define FAN_1_ON_PSU1 7 -#define FAN_1_ON_PSU2 8 - -enum fan_id { - FAN_1_ON_FAN_BOARD = 1, - FAN_2_ON_FAN_BOARD, - FAN_3_ON_FAN_BOARD, - FAN_4_ON_FAN_BOARD, - FAN_5_ON_FAN_BOARD, - FAN_1_ON_PSU_1, - FAN_1_ON_PSU_2, +static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_PSOC_PREFIX"/fan1_input", + INV_PSOC_PREFIX"/fan2_input", + INV_PSOC_PREFIX"/fan3_input", + INV_PSOC_PREFIX"/fan4_input", + INV_PSOC_PREFIX"/fan5_input", + INV_PSOC_PREFIX"/fan6_input", + INV_PSOC_PREFIX"/fan7_input", + INV_PSOC_PREFIX"/fan8_input", + INV_PSOC_PREFIX"/rpm_psu1", + INV_PSOC_PREFIX"/rpm_psu2", }; -#define _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) \ - { #prj"fan"#id"_present", #prj"fan"#id"_fault", #prj"fan"#id"_front_speed_rpm", \ - #prj"fan"#id"_direction", #prj"fan_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" } - -#define MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) - -#define MAKE_FAN_PATH_ON_PSU(folder) \ - {"", #folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ - "", #folder"/psu_fan1_duty_cycle_percentage", "" } - #define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ { \ { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ 0x0, \ - (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ 0, \ 0, \ ONLP_FAN_MODE_INVALID, \ @@ -82,14 +52,14 @@ enum fan_id { { \ { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ 0x0, \ - (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ 0, \ 0, \ ONLP_FAN_MODE_INVALID, \ } /* Static fan information */ -onlp_fan_info_t linfo[] = { +onlp_fan_info_t linfo[FAN_MAX] = { { }, /* Not used */ MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), @@ -97,6 +67,8 @@ onlp_fan_info_t linfo[] = { MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), MAKE_FAN_INFO_NODE_ON_PSU(1,1), MAKE_FAN_INFO_NODE_ON_PSU(2,1), }; @@ -108,78 +80,41 @@ onlp_fan_info_t linfo[] = { } \ } while(0) - static int _onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) { - int value, ret; + int value, ret; + char vstr[32], *vstrp = vstr, **vp = &vstrp; - /* get fan present status - */ - ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + memset(vstr, 0, 32); + /* get fan present status */ + ret = onlp_file_read_str(vp, FAN_GPI_ON_MAIN_BOARD); if (ret < 0) { return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%x", &value); + if (value & (1 << (fid-1))) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + else { + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + } - if (value == 0) { - return ONLP_STATUS_OK; - } - info->status |= ONLP_FAN_STATUS_PRESENT; - - - /* get fan fault status (turn on when any one fails) - */ - ret = onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid); + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); if (ret < 0) { return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; - if (value > 0) { - info->status |= ONLP_FAN_STATUS_FAILED; - } + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); - - /* get fan direction (both : the same) - */ - ret = onlp_file_read_int(&value, "%s""fan%d_direction", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - info->status |= value ? ONLP_FAN_STATUS_B2F : ONLP_FAN_STATUS_F2B; - - - /* get front fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - info->rpm = value; - - /* get rear fan speed - */ - ret = onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - /* take the min value from front/rear fan speed - */ - if (info->rpm > value) { - info->rpm = value; - } - - /* get speed percentage from rpm - */ - ret = onlp_file_read_int(&value, "%s""fan_max_speed_rpm", FAN_BOARD_PATH); - if (ret < 0) { - return ONLP_STATUS_E_INTERNAL; - } - - info->percentage = (info->rpm * 100)/value; - - return ONLP_STATUS_OK; + return ONLP_STATUS_OK; } @@ -212,33 +147,40 @@ _onlp_get_fan_direction_on_psu(void) static int -_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info) { - int val = 0; + int value, ret, index; + char vstr[32], *vstrp = vstr, **vp = &vstrp; - info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; - /* get fan direction - */ + /* get fan direction */ info->status |= _onlp_get_fan_direction_on_psu(); - /* get fan fault status - */ - if (psu_pmbus_info_get(pid, "psu_fan1_fault", &val) == ONLP_STATUS_OK) { - info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + if (info->status & ONLP_FAN_STATUS_FAILED) { + return ONLP_STATUS_OK; } - /* get fan speed - */ - if (psu_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { - info->rpm = val; - info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + index = ONLP_OID_ID_GET(info->hdr.id); + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); return ONLP_STATUS_OK; } - /* * This function will be called prior to all of onlp_fani_* functions. */ @@ -257,10 +199,9 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) local_id = ONLP_OID_ID_GET(id); *info = linfo[local_id]; - switch (local_id) { - case FAN_1_ON_PSU1: + case FAN_1_ON_PSU1: case FAN_1_ON_PSU2: rc = _onlp_fani_info_get_fan_on_psu(local_id, info); break; @@ -270,7 +211,9 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) case FAN_4_ON_MAIN_BOARD: case FAN_5_ON_MAIN_BOARD: case FAN_6_ON_MAIN_BOARD: - rc =_onlp_fani_info_get_fan(local_id, info); + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + rc = _onlp_fani_info_get_fan(local_id, info); break; default: rc = ONLP_STATUS_E_INVALID; @@ -305,15 +248,18 @@ onlp_fani_percentage_set(onlp_oid_t id, int p) switch (fid) { - case FAN_1_ON_PSU_1: - return psu_pmbus_info_set(PSU1_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_PSU_2: - return psu_pmbus_info_set(PSU2_ID, "psu_fan1_duty_cycle_percentage", p); - case FAN_1_ON_FAN_BOARD: - case FAN_2_ON_FAN_BOARD: - case FAN_3_ON_FAN_BOARD: - case FAN_4_ON_FAN_BOARD: - case FAN_5_ON_FAN_BOARD: + case FAN_1_ON_PSU1: + return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p); + case FAN_1_ON_PSU2: + return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p); + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: path = FAN_NODE(fan_duty_cycle_percentage); break; default: diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/ledi.c index 1a907343..a695afda 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/ledi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/ledi.c @@ -1,38 +1,21 @@ /************************************************************ - * + * ledi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include #include #include +#include #include #include #include #include "platform_lib.h" -#define prefix_path "/sys/class/leds/inventec_d7054q28b_led::" #define filename "brightness" #define VALIDATE(_id) \ @@ -42,18 +25,16 @@ } \ } while(0) -/* LED related data - */ -enum onlp_led_id +static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */ { - LED_RESERVED = 0, - LED_DIAG, - LED_LOC, - LED_FAN, - LED_PSU1, - LED_PSU2 + "reserved", + INV_CPLD_PREFIX"/%s_led", + INV_PSOC_PREFIX"/fan_led_%s1", + INV_PSOC_PREFIX"/fan_led_%s2", + INV_PSOC_PREFIX"/fan_led_%s3", + INV_PSOC_PREFIX"/fan_led_%s4", }; - + enum led_light_mode { LED_MODE_OFF = 0, LED_MODE_GREEN, @@ -75,15 +56,14 @@ typedef struct led_light_mode_map { } led_light_mode_map_t; led_light_mode_map_t led_map[] = { -{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, -{LED_DIAG, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, -{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED}, -{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, -{LED_LOC, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, -{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, -{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, -{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} + {LED_SYS, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_SYS, LED_MODE_RED, ONLP_LED_MODE_RED}, + {LED_FAN1,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN2,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN3,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN4,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, }; static char last_path[][10] = /* must map with onlp_led_id */ @@ -99,51 +79,41 @@ static char last_path[][10] = /* must map with onlp_led_id */ /* * Get the information for the given LED OID. */ -static onlp_led_info_t linfo[] = +static onlp_led_info_t linfo[LED_MAX] = { { }, /* Not used */ { - { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 1 (DIAG LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_SYS), "Chassis LED (SYSTEM LED)", 0 }, ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 2 (LOC LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN1), "Fan LED 1 (FAN1 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_BLUE, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 3 (FAN LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN2), "Fan LED 2 (FAN2 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 4 (PSU1 LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN3), "Fan LED 3 (FAN3 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, { - { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 }, + { ONLP_LED_ID_CREATE(LED_FAN4), "Fan LED 4 (FAN4 LED)", 0 }, ONLP_LED_STATUS_PRESENT, - ONLP_LED_CAPS_AUTO, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', }, }; -static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) -{ - int i, nsize = sizeof(led_map)/sizeof(led_map[0]); - - for (i = 0; i < nsize; i++) - { - if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) - { - return led_map[i].onlp_led_mode; - } - } - - return 0; -} - static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) { int i, nsize = sizeof(led_map)/sizeof(led_map[0]); @@ -168,41 +138,113 @@ onlp_ledi_init(void) /* * Diag LED Off */ - onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF); + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_SYS), ONLP_LED_MODE_OFF); return ONLP_STATUS_OK; } +int onlp_chassis_led_read(char *pathp, char *buf, size_t len) +{ + FILE * fp; + + fp = fopen (pathp, "r"); + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + if( fgets (buf, len, fp) == NULL ) { + perror("Error fgets operation"); + } + fclose(fp); + + return(0); +} + int onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) { - int local_id; - char data[2] = {0}; - char fullpath[50] = {0}; + int local_id, gret = 0, rret = 0; + char fullpath_grn[50] = {0}; + char fullpath_red[50] = {0}; + int gvalue = 0, rvalue = 0; + char buf[32] = {0}; VALIDATE(id); local_id = ONLP_OID_ID_GET(id); /* get fullpath */ - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + switch (local_id) { + case LED_SYS: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + gret = onlp_chassis_led_read(fullpath_grn, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + gvalue = 1; + } + + rret = onlp_chassis_led_read(fullpath_red, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + rvalue = 1; + } + if (gret < 0 && rret < 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = -1; + rvalue = -1; + } + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + if (onlp_file_read_int(&gvalue, fullpath_grn) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = 0; + } + if (onlp_file_read_int(&rvalue, fullpath_red) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + rvalue = 0; + } + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + gvalue = -1; + rvalue = -1; + break; + } - /* Set the onlp_oid_hdr_t and capabilities */ + /* Set the onlp_oid_hdr_t and capabilities */ *info = linfo[ONLP_OID_ID_GET(id)]; - /* Set LED mode */ - if (onlp_file_read_string(fullpath, data, sizeof(data), 0) != 0) { - DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); - return ONLP_STATUS_E_INTERNAL; + if (gvalue == 1 && rvalue == 0) { + info->mode = ONLP_LED_MODE_GREEN; + info->status |= ONLP_LED_STATUS_ON; } - - info->mode = driver_to_onlp_led_mode(local_id, atoi(data)); - - /* Set the on/off status */ - if (info->mode != ONLP_LED_MODE_OFF) { - info->status |= ONLP_LED_STATUS_ON; + else + if (gvalue == 0 && rvalue == 1) { + info->mode = ONLP_LED_MODE_RED; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 1 && rvalue == 1) { + info->mode = ONLP_LED_MODE_ORANGE; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 0) { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_ON; + } + else { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_FAILED; } - return ONLP_STATUS_OK; } @@ -242,7 +284,20 @@ onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) VALIDATE(id); local_id = ONLP_OID_ID_GET(id); - sprintf(fullpath, "%s%s/%s", prefix_path, last_path[local_id], filename); + switch (local_id) { + case LED_SYS: + sprintf(fullpath, "%s%s/%s", INV_CPLD_PREFIX, last_path[local_id], filename); + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath, "%s%s/%s", INV_PSOC_PREFIX, last_path[local_id], filename); + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + return ONLP_STATUS_E_INTERNAL; + } if (onlp_file_write_int(onlp_to_driver_led_mode(local_id, mode), fullpath, NULL) != 0) { diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.c index 9e4c5e06..ab185ab6 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.c @@ -1,27 +1,10 @@ /************************************************************ - * + * platform_lib.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include @@ -62,8 +45,8 @@ int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_l return ret; } -#define I2C_PSU_MODEL_NAME_LEN 11 -#define I2C_PSU_FAN_DIR_LEN 3 +#define I2C_PSU_MODEL_NAME_LEN 32 +#define I2C_PSU_FAN_DIR_LEN 8 #include psu_type_t get_psu_type(int id, char* modelname, int modelname_len) { @@ -79,7 +62,7 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } if(isspace(model_name[strlen(model_name)-1])) { - model_name[strlen(model_name)-1] = 0; + model_name[strlen(model_name)] = 0; } if (strncmp(model_name, "YM-2651Y", 8) == 0) { @@ -143,6 +126,14 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } } + if (strncmp(model_name, "DPS-150AB-10", 12) == 0) { + if (modelname) { + strncpy(modelname, model_name, 12); + } + + return PSU_TYPE_DC_12V_F2B; + } + return PSU_TYPE_UNKNOWN; } @@ -152,10 +143,14 @@ int psu_pmbus_info_get(int id, char *node, int *value) *value = 0; if (PSU1_ID == id) { - ret = onlp_file_read_int(value, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + ret = onlp_file_read_int(value, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + } + else + if (PSU2_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); } else { - ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + return ONLP_STATUS_E_INTERNAL; } if (ret < 0) { @@ -171,10 +166,10 @@ int psu_pmbus_info_set(int id, char *node, int value) switch (id) { case PSU1_ID: - sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + sprintf(path, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); break; case PSU2_ID: - sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + sprintf(path, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); break; default: return ONLP_STATUS_E_UNSUPPORTED; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.h index 69b8445d..5de2ffe8 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/platform_lib.h @@ -1,61 +1,105 @@ /************************************************************ - * + * platform_lib.h * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #ifndef __PLATFORM_LIB_H__ #define __PLATFORM_LIB_H__ #include "x86_64_inventec_d7054q28b_log.h" -#define CHASSIS_FAN_COUNT 6 -#define CHASSIS_THERMAL_COUNT 5 +#define SWPS_CYPRESS_GA2 (1) -#define PSU1_ID 1 -#define PSU2_ID 2 +#define ONLP_NODE_MAX_INT_LEN (8) +#define ONLP_NODE_MAX_PATH_LEN (64) -#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/11-005b/" -#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/10-0058/" +#define INV_CPLD_COUNT (1) +#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/" +#define INV_PSOC_PREFIX "/sys/bus/i2c/devices/0-0066/" +#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/" +#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/" + +#define CHASSIS_SFP_COUNT (54) + +/* + * Definitions of Chassis EEPROM + */ +#define EEPROM_NODE(node) INV_EPRM_PREFIX#node + + +/* + * Definitions of D7054Q28B device + */ +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE_FIRST, + THERMAL_CPU_CORE_2, + THERMAL_CPU_CORE_3, + THERMAL_CPU_CORE_4, + THERMAL_CPU_CORE_LAST, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, + THERMAL_MAX +}; +#define CHASSIS_THERMAL_COUNT (10) + +enum onlp_fan_id { + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_2_ON_MAIN_BOARD, + FAN_3_ON_MAIN_BOARD, + FAN_4_ON_MAIN_BOARD, + FAN_5_ON_MAIN_BOARD, + FAN_6_ON_MAIN_BOARD, + FAN_7_ON_MAIN_BOARD, + FAN_8_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2, + FAN_MAX +}; +#define CHASSIS_FAN_COUNT (8) + +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_SYS, + LED_FAN1, + LED_FAN2, + LED_FAN3, + LED_FAN4, + LED_MAX +}; +#define CHASSIS_LED_COUNT (1) + + +enum onlp_psu_id +{ + PSU_RESERVED = 0, + PSU1_ID, + PSU2_ID, + PSU_MAX +}; +#define CHASSIS_PSU_COUNT (2) + +#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX +#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX #define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node #define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node -#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/11-0053/" -#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/10-0050/" - -#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node -#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node - -#define FAN_BOARD_PATH "/sys/devices/platform/fan/" -#define FAN_NODE(node) FAN_BOARD_PATH#node - -#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0057/eeprom" - -int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); -int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); - -int psu_pmbus_info_get(int id, char *node, int *value); -int psu_pmbus_info_set(int id, char *node, int value); +#define PSU1_AC_HWMON_PREFIX INV_CPLD_PREFIX +#define PSU2_AC_HWMON_PREFIX INV_CPLD_PREFIX typedef enum psu_type { PSU_TYPE_UNKNOWN, @@ -70,6 +114,24 @@ typedef enum psu_type { psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +/* + * Definitions of FAN device + */ +#define FAN_BOARD_PATH INV_PSOC_PREFIX +#define FAN_NODE(node) FAN_BOARD_PATH#node + +/* + * Prototypes + */ +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_pmbus_info_set(int id, char *node, int value); + #define DEBUG_MODE 0 #if (DEBUG_MODE == 1) diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/psui.c index 8d12741e..70b19202 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/psui.c @@ -1,40 +1,24 @@ /************************************************************ - * + * psui.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include #include #include #include +#include #include "platform_lib.h" -#define PSU_STATUS_PRESENT 1 -#define PSU_STATUS_POWER_GOOD 1 - -#define PSU_NODE_MAX_INT_LEN 8 -#define PSU_NODE_MAX_PATH_LEN 64 +#define PSU_STATUS_PRESENT (0) +#define PSU_STATUS_POWER_GOOD (1) +#define PSU_STATUS_UNPOWERED (2) +#define PSU_STATUS_FAULT (4) +#define PSU_STATUS_UNINSTALLED (7) #define VALIDATE(_id) \ do { \ @@ -43,55 +27,50 @@ } \ } while(0) +static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_CPLD_PREFIX"/psu0", + INV_CPLD_PREFIX"/psu1", +}; + +static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_PSOC_PREFIX"/psoc_psu1_%s", + INV_PSOC_PREFIX"/psoc_psu2_%s", +}; + static int psu_status_info_get(int id, char *node, int *value) { int ret = 0; - char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; *value = 0; if (PSU1_ID == id) { - sprintf(node_path, "%s%s", PSU1_AC_HWMON_PREFIX, node); + sprintf(node_path, status_devfiles__[id]); } else if (PSU2_ID == id) { - sprintf(node_path, "%s%s", PSU2_AC_HWMON_PREFIX, node); + sprintf(node_path, status_devfiles__[id]); } - ret = onlp_file_read_int(value, node_path); + ret = onlp_file_read_str(vp, node_path); if (ret < 0) { AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); return ONLP_STATUS_E_INTERNAL; } - return ret; + if (!isdigit(*vstrp)) { + return ONLP_STATUS_E_INTERNAL; + } + *value = *vstrp - '0'; + return ONLP_STATUS_OK; } -static int -psu_ym2651_pmbus_info_get(int id, char *node, int *value) -{ - int ret = 0; - char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; - - *value = 0; - - if (PSU1_ID == id) { - sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); - } - else { - sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); - } - - ret = onlp_file_read_int(value, node_path); - - if (ret < 0) { - AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); - return ONLP_STATUS_E_INTERNAL; - } - - return ret; -} int onlp_psui_init(void) @@ -100,83 +79,101 @@ onlp_psui_init(void) } static int -psu_ym2651_info_get(onlp_psu_info_t* info) +psu_module_info_get(int id, onlp_psu_info_t* info) { - int val = 0; - int index = ONLP_OID_ID_GET(info->hdr.id); + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + int value = 0; - if (info->status & ONLP_PSU_STATUS_FAILED) { - return ONLP_STATUS_OK; + info->caps |= ONLP_PSU_CAPS_DC12; + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path); + } + else { + info->mvout = value; + info->caps |= ONLP_PSU_CAPS_VOUT; } - /* Set the associated oid_table */ - info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); - info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); - - /* Read voltage, current and power */ - if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { - info->mvout = val; - info->caps |= ONLP_PSU_CAPS_VOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path); + } + else { + info->miout = value; + info->caps |= ONLP_PSU_CAPS_IOUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { - info->miout = val; - info->caps |= ONLP_PSU_CAPS_IOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path); + } + else { + info->mpout = value; + info->caps |= ONLP_PSU_CAPS_POUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { - info->mpout = val; - info->caps |= ONLP_PSU_CAPS_POUT; - } - - return ONLP_STATUS_OK; -} - -#include -#define DC12V_750_REG_TO_CURRENT(low, high) (((low << 4 | high >> 4) * 20 * 1000) / 754) -#define DC12V_750_REG_TO_VOLTAGE(low, high) ((low << 4 | high >> 4) * 25) - -static int -psu_dc12v_750_info_get(onlp_psu_info_t* info) -{ - int pid = ONLP_OID_ID_GET(info->hdr.id); - int bus = (PSU1_ID == pid) ? 11 : 10; - int iout_low, iout_high; - int vout_low, vout_high; - - /* Set capability - */ - info->caps = ONLP_PSU_CAPS_DC12; - - if (info->status & ONLP_PSU_STATUS_FAILED) { - return ONLP_STATUS_OK; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path); + } + else { + info->mvin = value; + info->caps |= ONLP_PSU_CAPS_VIN; } - /* Get current - */ - iout_low = onlp_i2c_readb(bus, 0x6f, 0x0, ONLP_I2C_F_FORCE); - iout_high = onlp_i2c_readb(bus, 0x6f, 0x1, ONLP_I2C_F_FORCE); - - if ((iout_low >= 0) && (iout_high >= 0)) { - info->miout = DC12V_750_REG_TO_CURRENT(iout_low, iout_high); - info->caps |= ONLP_PSU_CAPS_IOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path); + } + else { + info->miin = value; + info->caps |= ONLP_PSU_CAPS_IIN; } - /* Get voltage - */ - vout_low = onlp_i2c_readb(bus, 0x6f, 0x2, ONLP_I2C_F_FORCE); - vout_high = onlp_i2c_readb(bus, 0x6f, 0x3, ONLP_I2C_F_FORCE); - - if ((vout_low >= 0) && (vout_high >= 0)) { - info->mvout = DC12V_750_REG_TO_VOLTAGE(vout_low, vout_high); - info->caps |= ONLP_PSU_CAPS_VOUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path); + } + else { + info->mpin = value; + info->caps |= ONLP_PSU_CAPS_PIN; } - /* Get power based on current and voltage - */ - if ((info->caps & ONLP_PSU_CAPS_IOUT) && (info->caps & ONLP_PSU_CAPS_VOUT)) { - info->mpout = (info->miout * info->mvout) / 1000; - info->caps |= ONLP_PSU_CAPS_POUT; + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "model"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->model, *vp, ret-1); + } + else { + //AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->model, "N/A", 3); + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "serial"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->serial, *vp, ret-1); + } + else { + AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->serial, "N/A", 3); } return ONLP_STATUS_OK; @@ -189,10 +186,24 @@ static onlp_psu_info_t pinfo[] = { { }, /* Not used */ { - { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + { + ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1) + } + }, }, { - { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + { + ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2) + } + }, } }; @@ -202,7 +213,6 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) int val = 0; int ret = ONLP_STATUS_OK; int index = ONLP_OID_ID_GET(id); - psu_type_t psu_type; VALIDATE(id); @@ -210,63 +220,27 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ /* Get the present state */ - if (psu_status_info_get(index, "psu_present", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) { + printf("Unable to read PSU(%d) node(psu)\r\n", index); + return ret; } - if (val != PSU_STATUS_PRESENT) { - info->status &= ~ONLP_PSU_STATUS_PRESENT; - return ONLP_STATUS_OK; + if (val == 0) { + info->status = ONLP_PSU_STATUS_PRESENT; } - info->status |= ONLP_PSU_STATUS_PRESENT; - - - /* Get power good status */ - if (psu_status_info_get(index, "psu_power_good", &val) != 0) { - printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + else + if (val == 1) { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ret; + } + else { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; } - if (val != PSU_STATUS_POWER_GOOD) { - info->status |= ONLP_PSU_STATUS_FAILED; - } - - - /* Get PSU type - */ - psu_type = get_psu_type(index, info->model, sizeof(info->model)); - - switch (psu_type) { - case PSU_TYPE_AC_F2B: - case PSU_TYPE_AC_B2F: - info->caps = ONLP_PSU_CAPS_AC; - ret = psu_ym2651_info_get(info); - break; - case PSU_TYPE_DC_48V_F2B: - case PSU_TYPE_DC_48V_B2F: - info->caps = ONLP_PSU_CAPS_DC48; - ret = psu_ym2651_info_get(info); - break; - case PSU_TYPE_DC_12V_F2B: - case PSU_TYPE_DC_12V_B2F: - case PSU_TYPE_DC_12V_FANLESS: - ret = psu_dc12v_750_info_get(info); - break; - case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ - info->status |= ONLP_PSU_STATUS_UNPLUGGED; - info->status &= ~ONLP_PSU_STATUS_FAILED; - ret = ONLP_STATUS_OK; - break; - default: - ret = ONLP_STATUS_E_UNSUPPORTED; - break; + if ((ret = psu_module_info_get(index, info)) != ONLP_STATUS_OK) { + printf("Unable to read PSU(%d) module information\r\n", index); } return ret; } - -int -onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) -{ - return ONLP_STATUS_E_UNSUPPORTED; -} - diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sfpi.c index 0b568114..36e7b170 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sfpi.c @@ -1,27 +1,10 @@ /************************************************************ - * + * sfpi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include @@ -34,19 +17,40 @@ #include #include "platform_lib.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; +static char sfp_node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; -#define MUX_START_INDEX 18 -#define NUM_OF_SFP_PORT 32 +#define NUM_OF_SFP_PORT (CHASSIS_SFP_COUNT) static const int sfp_mux_index[NUM_OF_SFP_PORT] = { - 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 +#ifdef SWPS_CYPRESS_GA1 +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, 51, 52, 53, 54, 55, 56, 57, +58, 59, 60, 61, 62, 63 +#endif +#ifdef SWPS_CYPRESS_GA2 +11, 10, 13, 12, 15, 14, 17, 16, +19, 18, 21, 20, 23, 22, 25, 24, +27, 26, 29, 28, 31, 30, 33, 32, +35, 34, 37, 36, 39, 38, 41, 40, +43, 42, 45, 44, 47, 46, 49, 48, +51, 50, 53, 52, 55, 54, 57, 56, +59, 58, 61, 60, 63, 62 +#endif +#ifdef SWPS_CYPRESS_BAI +11, 10, 13, 12, 15, 14, 17, 16, +19, 18, 21, 20, 23, 22, 25, 24, +27, 26, 29, 28, 31, 30, 33, 32, +35, 34, 37, 36, 39, 38, 41, 40, +43, 42, 45, 44, 47, 46, 49, 48, +51, 50, 53, 52, 55, 54, 57, 56, +59, 58, 61, 60, 63, 62 +#endif }; -#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]+MUX_START_INDEX) +#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]) static int sfp_node_read_int(char *node_path, int *value, int data_len) @@ -67,9 +71,7 @@ sfp_node_read_int(char *node_path, int *value, int data_len) static char* sfp_get_port_path(int port, char *node_name) { - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-0050/%s", - FRONT_PORT_TO_MUX_INDEX(port), - node_name); + sprintf(sfp_node_path, "/sys/class/swps/port%d/%s", port, node_name); return sfp_node_path; } @@ -90,7 +92,7 @@ int onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) { /* - * Ports {0, 32} + * Ports {0, 54} */ int p; AIM_BITMAP_CLR_ALL(bmap); @@ -111,66 +113,76 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - + char* path = sfp_get_port_path(port, "present"); if (sfp_node_read_int(path, &present, 0) != 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - + if (present == 0) { + present = 1; + } + else + if (present == 1) { + present = 0; + } + else { + AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port); + return ONLP_STATUS_E_INTERNAL; + } return present; } int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[4]; - char* path; - FILE* fp; + uint32_t presence_all[2] = {0}; + int port, ret, index; - path = sfp_get_port_path(0, "sfp_is_present_all"); - fp = fopen(path, "r"); + for (port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) { + if (port == 32) { + index = 1; + } - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; + ret = onlp_sfpi_is_present(port); + if (ret == 1) { + presence_all[index] |= (1<= 0; i--) { - presence_all <<= 8; - presence_all |= bytes[i]; - } - /* Populate bitmap */ - for(i = 0; presence_all; i++) { - AIM_BITMAP_MOD(dst, i, (presence_all & 1)); - presence_all >>= 1; - } + for(port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) { + if (port == 32) { + index = 1; + } + AIM_BITMAP_MOD(dst, port, (presence_all[index] & 1)); + presence_all[index] >>= 1; + } return ONLP_STATUS_OK; } int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - int len = 0; +#if 1 + int bus = FRONT_PORT_TO_MUX_INDEX(port); + memset(data, 0, 256); + /* Read eeprom information into data[] */ + if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0) + { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#else + char* path; + int len = 0; /* * Read the SFP eeprom into data[] * @@ -178,15 +190,21 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) * Return OK if eeprom is read */ memset(data, 0, 256); - - if (onlp_file_read((uint8_t*)data, 256, &len, path) < 0) { + path = sfp_get_port_path(port, "eeprom"); + if (onlp_file_read(&data[0], 256, &len, path) < 0) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } - +#endif return ONLP_STATUS_OK; } +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return onlp_sfpi_eeprom_read( port, data); +} + int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) { diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sysi.c index 421aa41c..b13cc6bf 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/sysi.c @@ -1,27 +1,10 @@ /************************************************************ - * + * sysi.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * - * - * ***********************************************************/ #include #include @@ -38,19 +21,12 @@ #include "platform_lib.h" -#define NUM_OF_THERMAL_ON_MAIN_BROAD CHASSIS_THERMAL_COUNT -#define NUM_OF_FAN_ON_MAIN_BROAD CHASSIS_FAN_COUNT -#define NUM_OF_PSU_ON_MAIN_BROAD 2 -#define NUM_OF_LED_ON_MAIN_BROAD 5 +#define NUM_OF_CPLD INV_CPLD_COUNT -#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/" -#define NUM_OF_CPLD 3 -static char arr_cplddev_name[NUM_OF_CPLD][10] = -{ - "4-0060", - "5-0062", - "6-0064" -}; +#define NUM_OF_THERMAL_ON_MAIN_BROAD (CHASSIS_THERMAL_COUNT) +#define NUM_OF_FAN_ON_MAIN_BROAD (CHASSIS_FAN_COUNT) +#define NUM_OF_PSU_ON_MAIN_BROAD (CHASSIS_PSU_COUNT) +#define NUM_OF_LED_ON_MAIN_BROAD (CHASSIS_LED_COUNT) const char* onlp_sysi_platform_get(void) @@ -62,7 +38,7 @@ int onlp_sysi_onie_data_get(uint8_t** data, int* size) { uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(onlp_file_read(rdata, 256, size, EEPROM_NODE(eeprom)) == ONLP_STATUS_OK) { if(*size == 256) { *data = rdata; return ONLP_STATUS_OK; @@ -74,27 +50,6 @@ onlp_sysi_onie_data_get(uint8_t** data, int* size) return ONLP_STATUS_E_INTERNAL; } -int -onlp_sysi_platform_info_get(onlp_platform_info_t* pi) -{ - int i, v[NUM_OF_CPLD]={0}; - for (i=0; i < NUM_OF_CPLD; i++) { - v[i] = 0; - if(onlp_file_read_int(v+i, "%s%s/version", PREFIX_PATH_ON_CPLD_DEV, arr_cplddev_name[i]) < 0) { - return ONLP_STATUS_E_INTERNAL; - } - } - pi->cpld_versions = aim_fstrdup("%d.%d.%d", v[0], v[1], v[2]); - return 0; -} - -void -onlp_sysi_platform_info_free(onlp_platform_info_t* pi) -{ - aim_free(pi->cpld_versions); -} - - int onlp_sysi_oids_get(onlp_oid_t* table, int max) { @@ -129,167 +84,27 @@ onlp_sysi_oids_get(onlp_oid_t* table, int max) return 0; } -typedef struct fan_ctrl_policy { - int duty_cycle; - int temp_down_adjust; /* The boundary temperature to down adjust fan speed */ - int temp_up_adjust; /* The boundary temperature to up adjust fan speed */ -} fan_ctrl_policy_t; - -fan_ctrl_policy_t fan_ctrl_policy_f2b[] = { -{32, 0, 174000}, -{38, 170000, 182000}, -{50, 178000, 190000}, -{63, 186000, 0} -}; - -fan_ctrl_policy_t fan_ctrl_policy_b2f[] = { -{32, 0, 140000}, -{38, 135000, 150000}, -{50, 145000, 160000}, -{69, 155000, 0} -}; - -#define FAN_DUTY_CYCLE_MAX 100 -#define FAN_SPEED_CTRL_PATH "/sys/bus/i2c/devices/2-0066/fan_duty_cycle_percentage" - -/* - * 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 - */ -int -onlp_sysi_platform_manage_fans(void) +static char *arr_cplddev_version[NUM_OF_CPLD] = { - int i = 0, arr_size, temp; - fan_ctrl_policy_t *policy; - int cur_duty_cycle, new_duty_cycle; - onlp_thermal_info_t thermal_1, thermal_2, thermal_3; + INV_CPLD_PREFIX"/version", +}; - int fd, len; - char buf[10] = {0}; - - /* Get each fan status - */ - for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) - { - onlp_fan_info_t fan_info; - - if (onlp_fan_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD]={0}; + for (i=0; i < NUM_OF_CPLD; i++) { + v[i] = 0; + if(onlp_file_read_int(v+i, arr_cplddev_version[i]) < 0) { return ONLP_STATUS_E_INTERNAL; } - - /* Decision 1: Set fan as full speed if any fan is failed. - */ - if (fan_info.status & ONLP_FAN_STATUS_FAILED) { - AIM_LOG_ERROR("Fan(%d) is not working, set the other fans as full speed\r\n", i); - return onlp_fan_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); - } - - /* Decision 1.1: Set fan as full speed if any fan is not present. - */ - if (!(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { - AIM_LOG_ERROR("Fan(%d) is not present, set the other fans as full speed\r\n", i); - return onlp_fan_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_CYCLE_MAX); - } - - /* Get fan direction (Only get the first one since all fan direction are the same) - */ - if (i == 1) { - if (fan_info.status & ONLP_FAN_STATUS_F2B) { - policy = fan_ctrl_policy_f2b; - arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_f2b); - } - else { - policy = fan_ctrl_policy_b2f; - arr_size = AIM_ARRAYSIZE(fan_ctrl_policy_b2f); - } - } } - - /* Get current fan speed - */ - fd = open(FAN_SPEED_CTRL_PATH, O_RDONLY); - if (fd == -1){ - AIM_LOG_ERROR("Unable to open fan speed control node (%s)", FAN_SPEED_CTRL_PATH); - return ONLP_STATUS_E_INTERNAL; - } - - len = read(fd, buf, sizeof(buf)); - close(fd); - if (len <= 0) { - AIM_LOG_ERROR("Unable to read fan speed from (%s)", FAN_SPEED_CTRL_PATH); - return ONLP_STATUS_E_INTERNAL; - } - cur_duty_cycle = atoi(buf); - - - /* Decision 2: If no matched fan speed is found from the policy, - * use FAN_DUTY_CYCLE_MIN as default speed - */ - for (i = 0; i < arr_size; i++) { - if (policy[i].duty_cycle != cur_duty_cycle) - continue; - - break; - } - - if (i == arr_size) { - return onlp_fan_percentage_set(ONLP_FAN_ID_CREATE(1), policy[0].duty_cycle); - } - - /* Get current temperature - */ - if (onlp_thermal_info_get(ONLP_THERMAL_ID_CREATE(2), &thermal_1) != ONLP_STATUS_OK || - onlp_thermal_info_get(ONLP_THERMAL_ID_CREATE(3), &thermal_2) != ONLP_STATUS_OK || - onlp_thermal_info_get(ONLP_THERMAL_ID_CREATE(4), &thermal_3) != ONLP_STATUS_OK) { - AIM_LOG_ERROR("Unable to read thermal status"); - return ONLP_STATUS_E_INTERNAL; - } - temp = thermal_1.mcelsius + thermal_2.mcelsius + thermal_3.mcelsius; - - - /* Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature - */ - new_duty_cycle = cur_duty_cycle; - - if ((temp >= policy[i].temp_up_adjust) && (i != (arr_size-1))) { - new_duty_cycle = policy[i+1].duty_cycle; - } - else if ((temp <= policy[i].temp_down_adjust) && (i != 0)) { - new_duty_cycle = policy[i-1].duty_cycle; - } - - if (new_duty_cycle == cur_duty_cycle) { - /* Duty cycle does not change, just return */ - return ONLP_STATUS_OK; - } - - return onlp_fan_percentage_set(ONLP_FAN_ID_CREATE(1), new_duty_cycle); + pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + return 0; } -int -onlp_sysi_platform_manage_leds(void) +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) { - return ONLP_STATUS_E_UNSUPPORTED; + aim_free(pi->cpld_versions); } - diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/thermali.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/thermali.c index 94f5353c..e5d573a2 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/thermali.c +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/onlp/builds/src/module/src/thermali.c @@ -1,23 +1,8 @@ /************************************************************ - * + * thermali.c * - * Copyright 2014 Big Switch Networks, Inc. - * Copyright 2014 Accton Technology Corporation. + * Copyright 2018 Inventec Technology Corporation. * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html - * - * 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. - * - * ************************************************************ * * Thermal Sensor Platform Implementation. @@ -37,42 +22,45 @@ } \ } while(0) -enum onlp_thermal_id -{ - THERMAL_RESERVED = 0, - THERMAL_CPU_CORE, - THERMAL_1_ON_MAIN_BROAD, - THERMAL_2_ON_MAIN_BROAD, - THERMAL_3_ON_MAIN_BROAD, - THERMAL_1_ON_PSU1, - THERMAL_1_ON_PSU2, -}; - -static char* devfiles__[] = /* must map with onlp_thermal_id */ +static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */ { "reserved", - NULL, /* CPU_CORE files */ - "/sys/bus/i2c/devices/3-0048*temp1_input", - "/sys/bus/i2c/devices/3-0049*temp1_input", - "/sys/bus/i2c/devices/3-004a*temp1_input", - "/sys/bus/i2c/devices/3-004b*temp1_input", - "/sys/bus/i2c/devices/11-005b*psu_temp1_input", - "/sys/bus/i2c/devices/10-0058*psu_temp1_input", + INV_CTMP_PREFIX"/temp1_%s", + INV_CTMP_PREFIX"/temp2_%s", + INV_CTMP_PREFIX"/temp3_%s", + INV_CTMP_PREFIX"/temp4_%s", + INV_CTMP_PREFIX"/temp5_%s", + INV_PSOC_PREFIX"/temp1_input", + INV_PSOC_PREFIX"/temp2_input", + INV_PSOC_PREFIX"/temp3_input", + INV_PSOC_PREFIX"/temp4_input", + INV_PSOC_PREFIX"/temp5_input", + INV_PSOC_PREFIX"/thermal_psu1", + INV_PSOC_PREFIX"/thermal2_psu1", + INV_PSOC_PREFIX"/thermal_psu2", + INV_PSOC_PREFIX"/thermal2_psu2", }; -static char* cpu_coretemp_files[] = - { - "/sys/devices/platform/coretemp.0*temp2_input", - "/sys/devices/platform/coretemp.0*temp3_input", - "/sys/devices/platform/coretemp.0*temp4_input", - "/sys/devices/platform/coretemp.0*temp5_input", - NULL, - }; - /* Static values */ -static onlp_thermal_info_t linfo[] = { +static onlp_thermal_info_t linfo[THERMAL_MAX] = { { }, /* Not used */ - { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "Physical id 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_2), "CPU Core 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_4), "CPU Core 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_LAST), "CPU Core 3", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, @@ -92,13 +80,25 @@ static onlp_thermal_info_t linfo[] = { ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS } }; @@ -132,10 +132,16 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) /* Set the onlp_oid_hdr_t and capabilities */ *info = linfo[local_id]; - if(local_id == THERMAL_CPU_CORE) { - int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); - return rv; - } + if(local_id >= THERMAL_CPU_CORE_FIRST && local_id <= THERMAL_CPU_CORE_LAST) { + char desc[32], *dp = &desc[0]; + int rv = onlp_file_read_str(&dp, devfiles__[local_id], "label"); + if (rv > 0) { + memset (info->hdr.description, 0, ONLP_OID_DESC_SIZE); + strncpy(info->hdr.description, dp, rv); + } + /* Set the onlp_oid_hdr_t and capabilities */ + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id], "input"); + } return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]); } diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/platform-config/r0/src/python/x86_64_inventec_d7054q28b_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/platform-config/r0/src/python/x86_64_inventec_d7054q28b_r0/__init__.py index b88a70fa..b10895ef 100644 --- a/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/platform-config/r0/src/python/x86_64_inventec_d7054q28b_r0/__init__.py +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7054q28b/platform-config/r0/src/python/x86_64_inventec_d7054q28b_r0/__init__.py @@ -2,14 +2,19 @@ from onl.platform.base import * from onl.platform.inventec import * class OnlPlatform_x86_64_inventec_d7054q28b_r0(OnlPlatformInventec, - OnlPlatformPortConfig_32x100): + OnlPlatformPortConfig_48x25_6x100): PLATFORM='x86-64-inventec-d7054q28b-r0' MODEL="X86-D7054Q28B" - SYS_OBJECT_ID="7054.28" + SYS_OBJECT_ID=".7054.1" def baseconfig(self): - os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0") + os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko") self.insmod('inv_platform') self.insmod('inv_psoc') self.insmod('inv_cpld') + self.new_i2c_device('inv_eeprom', 0x53, 0) + self.insmod('inv_eeprom') + self.insmod('swps') + self.insmod('vpd') + # self.insmod('inv_pthread') return True diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/.gitignore new file mode 100644 index 00000000..c25c4f5b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/.gitignore @@ -0,0 +1,2 @@ +*x86*64*inventec*d7264q28b*.mk +onlpdump.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/PKG.yml new file mode 100644 index 00000000..546fbdb3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d7264q28b ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/.gitignore b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/Makefile new file mode 100644 index 00000000..a6644096 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := inventec +BASENAME := x86-64-inventec-d7264q28b +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/Makefile new file mode 100644 index 00000000..fe1036a3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/Makefile @@ -0,0 +1,8 @@ +#obj-m += gpio-ich.o +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o inv_mux.o transceiver.o +obj-m += vpd.o +vpd-objs := inv_vpd.o onie_tlvinfo.o +obj-m += inv_pthread.o diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/gpio-ich.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/gpio-ich.c new file mode 100644 index 00000000..70304220 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/gpio-ich.c @@ -0,0 +1,548 @@ +/* + * 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 +#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))); +} + +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; + chip->dev = &ichx_priv.dev->dev; + + /* 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, +}; + +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; + 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; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_cpld.c new file mode 100644 index 00000000..42401d62 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.c new file mode 100644 index 00000000..e7ca5259 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.c @@ -0,0 +1,272 @@ +#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: + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.h new file mode 100644 index 00000000..a21a5e23 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_mux.h @@ -0,0 +1,37 @@ +#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) + +/* 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_platform.c new file mode 100644 index 00000000..720a4cd2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/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", (s32)(temp) ); + + 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 = (u16)temp; + + 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(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)); + +//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, + + //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, + + //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) +{ + if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);} + if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev); + sysfs_remove_group(&hwmon_dev->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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_pthread.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_pthread.c new file mode 100644 index 00000000..9faf33e7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_pthread.c @@ -0,0 +1,1207 @@ +/***************************** + 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); +} + +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]; + +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" ); +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +}; +#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 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 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(&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/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) { + 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 = 0; + + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.c new file mode 100644 index 00000000..eeeb829f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.c @@ -0,0 +1,2943 @@ +#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, 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, + __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_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); +} + +static ssize_t +show_attr_eeprom(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_eeprom, + 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); +} + +/* ========== 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(eeprom, S_IRUGO, show_attr_eeprom, 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); + +/* ========== 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: + 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 = secquoia_ioexp_layout; + port_layout = secquoia_port_layout; + ioexp_total = ARRAY_SIZE(secquoia_ioexp_layout); + port_total = ARRAY_SIZE(secquoia_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; + } + 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; + } + if (device_create_file(device_p, &dev_attr_eeprom) < 0) { + err_attr = "eeprom"; + 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: + 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: + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.h new file mode 100644 index 00000000..60435ce3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_swps.h @@ -0,0 +1,896 @@ +#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.5" +#define SWP_LICENSE "GPL" + +#define SWPS_KERN_VER_AF_3_10 (1) + +/* 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) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_SEQUOIA_GA + +/* 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) +#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" }, +}; + + +/* ========================================== + * 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_FORCE_HEDERA; + +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 + + +#endif /* INV_SWPS_H */ + + + + + + + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.c new file mode 100644 index 00000000..2075fd4e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.c @@ -0,0 +1,332 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_vpd.h" +#include "onie_tlvinfo.h" + +static int vpd_major; +static struct class *vpd_class_p = NULL; +static char cEeprom[SYS_EEPROM_MAX_SIZE]; +static DEFINE_MUTEX(vpd_mutex); + +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; +} + +static +int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf) +{ + int iRet; + + read_eeprom( pi2c_client, cEeprom); + iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf); + return iRet; +} + +static +int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, const char *c_buf) +{ + int iErr = 0; + + if (read_eeprom(pi2c_client, cEeprom)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + return -1; + } + + if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) { + } + if (c_buf) { + if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) { + printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__); + iErr = -1; + } else { + iErr = prog_eeprom(pi2c_client,cEeprom); + } + } + return iErr; +} + +static struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(vpd_class_p, + NULL, + name, + __swp_match); + return dev; +} + +static ssize_t +store_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + char *pChar; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + + //-strip 0x0a in the last byte. + for (iLen = 0, pChar = (char*)buf_p; + iLen < 255 && *pChar != 0; + iLen++, pChar++) ; + if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a) + *(pChar - 1) = 0; + //- + + iErr = write_vpd_data( pi2c_client, iOffset, buf_p); + + mutex_unlock(&vpd_mutex); + return count; +} + +static ssize_t +show_attr_vpd(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct i2c_client *pi2c_client = dev_get_drvdata(dev_p); + struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p); + int iOffset = attr->index; + int iErr , iLen; + + if (!pi2c_client){ + return -ENODEV; + } + mutex_lock(&vpd_mutex); + iErr = get_vpd_data( pi2c_client, iOffset, buf_p); + mutex_unlock(&vpd_mutex); + + if( iErr <= 0 ) + iLen = 0; + else + iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p); + + return iLen; +} + +/* ================= Vpd attribute ======================== + */ +static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME ); +static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER ); +static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER ); +static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE ); +static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE ); +static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION ); +static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION ); +static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME ); +static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION ); +static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE ); +static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME ); +static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY ); +static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME ); +static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION ); +static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG ); +static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT ); +static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 ); + +static void +clean_vpd_common(void) +{ + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(VPD_DEVICE); + if (device_p){ + dev_num = MKDEV(vpd_major, 1); + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); + } + VPD_DEBUG("%s: done.\n", __func__); +} + + +static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={ + { &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"}, + { &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"}, + { &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"}, + { &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"}, + { &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"}, + { &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"}, + { &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"}, + { &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"}, + { &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"}, + { &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"}, + { &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"}, + { &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"}, + { &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"}, + { &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"}, + { &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"}, + { &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"}, + { &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"}, +}; + +static int +register_vpd_attr(struct device *device_p){ + + char *err_attr = NULL; + int i; + + for( i = 0 ; i adapter = adap; + vpd_i2c_client->addr = VPD_I2C_ADDR; + + device_p = device_create(vpd_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + vpd_i2c_client, /* void *private_data */ + VPD_DEVICE); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_vpd_device_1; + } + if (register_vpd_attr(device_p) < 0) { + err_msg = "register_vpd_attr fail"; + goto err_register_vpd_device_2; + } + return 0; + +err_register_vpd_device_2: + device_unregister(device_p); + device_destroy(vpd_class_p, dev_num); +err_register_vpd_device_1: + kfree(vpd_i2c_client); + vpd_i2c_client = NULL; +err_register_vpd_device: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + +static int +register_vpd_module(void) +{ + dev_t vpd_devt = 0; + + if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){ + VPD_WARN("Allocate VPD MAJOR failure! \n"); + goto err_register_vpd_module; + } + vpd_major = MAJOR(vpd_devt); + + /* Create class object */ + vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS); + if (IS_ERR(vpd_class_p)) { + VPD_ERR("Create class failure! \n"); + goto err_register_vpd_module_1; + } + return 0; + +err_register_vpd_module_1: + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_register_vpd_module: + return -1; +} + + +static int +init_vpd_common(void) +{ + char *err_msg = "ERR"; + + if (register_vpd_device() < 0) { + err_msg = "register_vpd_device fail"; + goto err_init_vpd_common; + } + return 0; + +err_init_vpd_common: + VPD_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +vpd_module_init(void) +{ + if (register_vpd_module() < 0){ + goto err_vpd_module_init; + } + if (init_vpd_common() < 0){ + goto err_vpd_module_init_1; + } + VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION); + return 0; + +err_vpd_module_init_1: + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); +err_vpd_module_init: + VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION); + return -1; +} + + +static void __exit +vpd_module_exit(void) +{ + clean_vpd_common(); + class_unregister(vpd_class_p); + class_destroy(vpd_class_p); + unregister_chrdev_region(MKDEV(vpd_major, 0), 1); + VPD_INFO("Remove Inventec vpd module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(VPD_AUTHOR); +MODULE_DESCRIPTION(VPD_DESC); +MODULE_VERSION(VPD_VERSION); +MODULE_LICENSE(VPD_LICENSE); + +module_init(vpd_module_init); +module_exit(vpd_module_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.h new file mode 100644 index 00000000..58c7fe33 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/inv_vpd.h @@ -0,0 +1,46 @@ +#ifndef INV_VPD_H +#define INV_VPD_H + +#define EEPROM_CLASS "eeprom" +#define VPD_DEVICE "vpd" +#define VPD_AUTHOR "Neil " +#define VPD_DESC "Inventec eeprom vpd driver" +#define VPD_VERSION "1.0.0" +#define VPD_LICENSE "GPL" + +#define VPD_ENTRY_SIZE (17) +#define VPD_I2C_BUS (0) +#define VPD_I2C_ADDR (0x53) + +struct register_attr { +struct device_attribute *attr; +char * errmsg; +}; + +struct vpd_device_attribute{ + struct device_attribute dev_attr; + int index; +}; + +#define to_vpd_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct vpd_device_attribute, dev_attr) + +#define VPD_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ + struct vpd_device_attribute vpd_dev_attr_##_name \ + = VPD_ATTR(_name, _mode, _show, _store, _index) + +#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args) +#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args) +#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args) + +#ifdef DEBUG_VPD +# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args) +#else +# define VPD_DEBUG(fmt, args...) +#endif + +#endif /* INV_VPD_H */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/io_expander.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/io_expander.c new file mode 100644 index 00000000..231884f3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/io_expander.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/io_expander.h new file mode 100644 index 00000000..4e39fcef --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.c new file mode 100644 index 00000000..aaa3d507 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.c @@ -0,0 +1,815 @@ +#include +#include +#include +#include +//#include +#include + +//#include +//#include +#include "onie_tlvinfo.h" + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read = 0; + +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len); +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len); + +static inline int is_multicast_ether_addr(const u_int8_t *addr) +{ + return 0x01 & addr[0]; +} + +static inline int is_zero_ether_addr(const u_int8_t *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +static inline int is_valid_ether_addr(const u_int8_t *addr) +{ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +#if 0 +static unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} +#else +static unsigned long crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static unsigned long crc32(unsigned char const *buf, unsigned int size) +{ + unsigned char *p = (unsigned char*)buf; + unsigned long crc = 0; + + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} +#endif + +static int set_bytes(char *buf, const char *string, int * converted_accum) +{ + char *p = (char *) string; + int i; + uint byte; + + if (!p) { + printk("ERROR: NULL string passed in.\n"); + return -1; + } + /* Convert string to bytes */ + for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0); + i++) { + while ((*p == ' ') || (*p == '\t') || (*p == ',') || + (*p == ';')) { + p++; + } + if (*p != 0) { + if (!isdigit(*p)) { + printk("ERROR: Non-digit found in byte string: (%s)\n", string); + return -1; + } + byte = strtoul(p, &p, 0); + if (byte >= 256) { + printk("ERROR: The value specified is greater than 255: (%u) " \ + "in string: %s\n", byte, string); + return -1; + } + buf[i] = byte & 0xFF; + } + } + if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) { + printk("ERROR: Trying to assign too many bytes " + "(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string); + return -1; + } + *converted_accum = i; + return 0; +} + +/* + * set_date + * + * Validates the format of the data string + * + * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss) + * and validates that the format is correct. If so the string is copied + * to the supplied buffer. + */ +static int set_date(char *buf, const char *string) +{ + int i; + + if (!string) { + printk("ERROR: NULL date string passed in.\n"); + return -1; + } + if (strlen(string) != 19) { + printk("ERROR: Date strlen() != 19 -- %zd\n", strlen(string)); + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string); + return -1; + } + for (i = 0; string[i] != 0; i++) { + switch (i) { + case 2: + case 5: + if (string[i] != '/') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 10: + if (string[i] != ' ') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + case 13: + case 16: + if (string[i] != ':') { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + default: + if (!isdigit(string[i])) { + printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", + string); + return -1; + } + break; + } + } + strcpy(buf, string); + return 0; +} + +/* + * is_valid_tlv + * + * Perform basic sanity checks on a TLV field. The TLV is pointed to + * by the parameter provided. + * 1. The type code is not reserved (0x00 or 0xFF) + */ +static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) +{ + return((tlv->type != 0x00) && (tlv->type != 0xFF)); +} + +/* + * set_mac + * + * Converts a string MAC address into a binary buffer. + * + * This function takes a pointer to a MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number). + * The string format is verified and then converted to binary and + * stored in a buffer. + */ +static int set_mac(char *buf, const char *string) +{ + char *p = (char *) string; + int i; + int err = 0; + char *end; + + if (!p) { + printk("ERROR: NULL mac addr string passed in.\n"); + return -1; + } + if (strlen(p) != 17) { + printk("ERROR: MAC address strlen() != 17 -- %zd\n", strlen(p)); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + for (i = 0; i < 17; i++) { + if ((i % 3) == 2) { + if (p[i] != ':') { + err++; + printk("ERROR: mac: p[%i] != :, found: `%c'\n", + i, p[i]); + break; + } + continue; + } else if (!isxdigit(p[i])) { + err++; + printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n", + i, p[i]); + break; + } + } + if (err != 0) { + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + /* Convert string to binary */ + for (i = 0, p = (char *)string; i < 6; i++) { + buf[i] = p ? strtoul(p, &end, 16) : 0; + if (p) { + p = (*end) ? end + 1 : end; + } + } + if (!is_valid_ether_addr((char *)buf)) { + printk("ERROR: MAC address must not be 00:00:00:00:00:00, " + "a multicast address or FF:FF:FF:FF:FF:FF.\n"); + printk("ERROR: Bad MAC address format: %s\n", string); + return -1; + } + return 0; +} + +/* + * is_valid_tlvinfo_header + * + * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM + * data pointed to by the parameter: + * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo" + * 2. Version byte is 1 + * 3. Total length bytes contain value which is less than or equal + * to the allowed maximum (2048-11) + * + */ +static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) +{ + int max_size = TLV_TOTAL_LEN_MAX; + return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && + (hdr->version == TLV_INFO_VERSION) && + (be16_to_cpu(hdr->totallen) <= max_size) ); +} + +/* + * decode_tlv_value + * + * Decode a single TLV value into a string. + + * The validity of EEPROM contents and the TLV field have been verified + * prior to calling this function. + */ +#define DECODE_NAME_MAX 20 + +static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value) +{ + int i; + + switch (tlv->type) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_MANUF_DATE: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + memcpy(value, tlv->value, tlv->length); + value[tlv->length] = 0; + break; + case TLV_CODE_MAC_BASE: + snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3], tlv->value[4], tlv->value[5]); + break; + case TLV_CODE_DEVICE_VERSION: + snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]); + break; + case TLV_CODE_MAC_SIZE: + snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]); + break; + case TLV_CODE_VENDOR_EXT: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + case TLV_CODE_CRC_32: + snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X", + tlv->value[0], tlv->value[1], tlv->value[2], + tlv->value[3]); + break; + default: + value[0] = 0; + for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); + i++) { + snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]); + } + break; + } + +} + +/* + * is_checksum_valid + * + * Validate the checksum in the provided TlvInfo EEPROM data. First, + * verify that the TlvInfo header is valid, then make sure the last + * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data + * and compare it to the value stored in the EEPROM CRC-32 TLV. + */ +static bool is_checksum_valid(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + unsigned int stored_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return(FALSE); + } + + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { + return(FALSE); + } + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | + (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]); + + //printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc); + //return(calc_crc == stored_crc); + return 1; +} + +/* + * update_crc + * + * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then + * one is added. This function should be called after each update to the + * EEPROM structure, to make sure the CRC is always correct. + */ +static void update_crc(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + // Is the eeprom header valid? + if (!is_valid_tlvinfo_header(eeprom_hdr)) { + return; + } + // Is the last TLV a CRC? + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - + (sizeof(tlvinfo_tlv_t) + 4)]; + if (eeprom_crc->type != TLV_CODE_CRC_32) { + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) > + TLV_TOTAL_LEN_MAX) { + return; + } + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + + be16_to_cpu( + eeprom_hdr->totallen)]; + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + 4); + eeprom_crc->type = TLV_CODE_CRC_32; + } + eeprom_crc->length = 4; + + // Calculate the checksum + calc_crc = crc32((void *)eeprom, + sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen) - 4); + + eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF; + eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF; + eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF; + eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF; +} + +/* + * show_eeprom + * + * Display the contents of the EEPROM + */ + +/* + * read_eeprom + * + * Read the EEPROM into memory, if it hasn't already been read. + */ +int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom) +{ + int ret; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[ + sizeof(tlvinfo_header_t)]; + + if (has_been_read) + return 0; + + /* Read the header */ + ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t)); + /* If the header was successfully read, read the TLVs */ + if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) { + ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t), + be16_to_cpu(eeprom_hdr->totallen)); + } + // If the contents are invalid, start over with default contents + if(!is_valid_tlvinfo_header(eeprom_hdr)) + printk(KERN_ERR + "Notice: Invalid TLV header found. Using default contents--1.\n"); + if(!is_checksum_valid(eeprom)) + printk(KERN_ERR + "Notice: Invalid TLV checksum found. Using default contents--2.\n"); + if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){ + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); + } + has_been_read = 1; + + return ret; +} + +/* + * prog_eeprom + * Write the EEPROM data from CPU memory to the hardware. + */ +int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom) +{ + int ret = 0; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + int eeprom_len; + + eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len); + if (ret) { + printk("Programming failed.\n"); + return -1; + } + has_been_read = 0; + return 0; +} + +/* + * tlvinfo_find_tlv + * + * This function finds the TLV with the supplied code in the EERPOM. + * An offset from the beginning of the EEPROM is returned in the + * eeprom_index parameter if the TLV is found. + */ +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, + int *eeprom_index) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int eeprom_end; + + // Make sure the EEPROM contents are valid + if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) { + return(FALSE); + } + // Search through the TLVs, looking for the first one which matches the + // supplied type code. + *eeprom_index = sizeof(tlvinfo_header_t); + eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + + while (*eeprom_index < eeprom_end) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; + if (!is_valid_tlv(eeprom_tlv)) { + return(FALSE); + } + if (eeprom_tlv->type == tcode) { + return(TRUE); + } + *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + return(FALSE); +} + +/* + * tlvinfo_decode_tlv + * + * This function finds the TLV with the supplied code in the EERPOM + * and decodes the value into the buffer provided. + */ +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value) +{ + int eeprom_index; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then decode it + + if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + decode_tlv_value(eeprom_tlv, value); + return TRUE; + } + + return FALSE; +} + +/* + * tlvinfo_delete_tlv + * + * This function deletes the TLV with the specified type code from the + * EEPROM. + */ +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code) +{ + int eeprom_index; + int tlength; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + + // Find the TLV and then move all following TLVs "forward" + if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength], + sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) - + eeprom_index - tlength); + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) - + tlength); + update_crc(eeprom); + return(TRUE); + } + return(FALSE); +} + +/* + * tlvinfo_add_tlv + * + * This function adds a TLV to the EEPROM, converting the value (a string) to + * the format in which it will be stored in the EEPROM. + */ +#define MAX_TLV_VALUE_LEN 256 +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int new_tlv_len = 0; + u_int32_t value; + char data[MAX_TLV_VALUE_LEN]; + int eeprom_index; + int max_size = TLV_TOTAL_LEN_MAX; + + // Encode each TLV type into the format to be stored in the EERPOM + switch (tcode) { + case TLV_CODE_PRODUCT_NAME: + case TLV_CODE_PART_NUMBER: + case TLV_CODE_SERIAL_NUMBER: + case TLV_CODE_LABEL_REVISION: + case TLV_CODE_PLATFORM_NAME: + case TLV_CODE_ONIE_VERSION: + case TLV_CODE_MANUF_NAME: + case TLV_CODE_MANUF_COUNTRY: + case TLV_CODE_VENDOR_NAME: + case TLV_CODE_DIAG_VERSION: + case TLV_CODE_SERVICE_TAG: + strncpy(data, strval, MAX_TLV_VALUE_LEN); + + if( strlen(strval) >= MAX_TLV_VALUE_LEN ) + new_tlv_len = MAX_TLV_VALUE_LEN; + else + new_tlv_len = strlen(strval); + + break; + case TLV_CODE_DEVICE_VERSION: + value = strtoul(strval, NULL, 0); + if (value >= 256) { + printk("ERROR: Device version must be 255 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = value & 0xFF; + new_tlv_len = 1; + break; + case TLV_CODE_MAC_SIZE: + value = strtoul(strval, NULL, 0); + if (value >= 65536) { + printk("ERROR: MAC Size must be 65535 or less. Value " \ + "supplied: %u", value); + return(FALSE); + } + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + new_tlv_len = 2; + break; + case TLV_CODE_MANUF_DATE: + if (set_date(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 19; + break; + case TLV_CODE_MAC_BASE: + if (set_mac(data, strval) != 0) { + return(FALSE); + } + new_tlv_len = 6; + break; + case TLV_CODE_CRC_32: + printk("WARNING: The CRC TLV is set automatically and cannot be set " \ + "manually.\n"); + return(FALSE); + case TLV_CODE_VENDOR_EXT: + default: + if (set_bytes(data, strval, &new_tlv_len) != 0 ) { + return(FALSE); + } + break; + } + + // Is there room for this TLV? + if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + + new_tlv_len) > max_size) { + printk("ERROR: There is not enough room in the EERPOM to save data.\n"); + return(FALSE); + } + + // Add TLV at the end, overwriting CRC TLV if it exists + if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) { + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + - sizeof(tlvinfo_tlv_t) - 4); + } else { + eeprom_index = sizeof(tlvinfo_header_t) + + be16_to_cpu(eeprom_hdr->totallen); + } + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; + eeprom_tlv->type = tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, data, new_tlv_len); + + // Update the total length and calculate (add) a new CRC-32 TLV + eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) + + sizeof(tlvinfo_tlv_t) + new_tlv_len); + update_crc(eeprom); + + return(TRUE); +} + +/* + * read_sys_eeprom - read the hwinfo from i2c EEPROM + */ +int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len) +{ + int iRet = 0; + int i = 0; + unsigned char ucBuf[2]; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET + offset; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[0] = (usAddr & 0xFF00) >> 8; + ucBuf[1] = (usAddr & 0x00FF); + + iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]); + if( iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data read error\n"); + return -1; + } + + *c = i2c_smbus_read_byte(pi2c_client); + c++; usAddr++; + } + return 0; +} + +/* + * write_sys_eeprom - write the hwinfo to i2c EEPROM + */ +int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len) +{ + int iRet = 0; + int i = 0; + u_int8_t *c; + unsigned short usAddr = SYS_EEPROM_OFFSET; + unsigned char ucBuf[3]; + + c = eeprom_data; + for (i = 0; i < len; i++) { + ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ; + ucBuf[ 1 ] = (usAddr & 0x00FF); + ucBuf[ 2 ] = *c; + + iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1])); + if (iRet < 0 ){ + printk(KERN_ERR"Error!! VPD data write error . \n"); + return -1; + } + + c++; usAddr++; + msleep_interruptible(10); + } + + return 0; +} + +void update_eeprom_header(u_int8_t *eeprom) +{ + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen = cpu_to_be16(0); + update_crc(eeprom); +} +#if 0 +int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf) +{ + int tlv_end; + int curr_tlv; + tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t * eeprom_tlv; + int iFind = 0; + + if( !is_valid_tlvinfo_header(eeprom_hdr) ) { + printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n"); + return -1; + } + + curr_tlv = sizeof(tlvinfo_header_t); + tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); + while(curr_tlv < tlv_end){ + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv]; + if (!is_valid_tlv(eeprom_tlv)) { + printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n", + curr_tlv); + return -1; + } + + decode_tlv_value(eeprom_tlv, c_buf); + if( eeprom_tlv->type == i_offset){ + iFind = 1; + break; + } + curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; + } + + if( iFind == 0 ) + return -1; + else + return 0; +} +#endif diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.h new file mode 100644 index 00000000..da0a0759 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/onie_tlvinfo.h @@ -0,0 +1,150 @@ +/* + * The Definition of the TlvInfo EEPROM format can be found at onie.org or + * github.com/onie + */ +#include +#define strtoul simple_strtoul + +#define FALSE 0 +#define TRUE (!FALSE) +#define MAX_STRING_SIZE 128 +/* + * Tlvinf header: Layout of the header for the TlvInfo format + * + * See the end of this file for details of this eeprom format + */ +struct __attribute__ ((__packed__)) tlvinfo_header_s { + char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ + u_int8_t version; /* 0x08 Structure version */ + u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */ +}; +typedef struct tlvinfo_header_s tlvinfo_header_t; + +// Header Field Constants +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +/* + * TlvInfo TLV: Layout of a TLV field + */ +struct __attribute__ ((__packed__)) tlvinfo_tlv_s { + u_int8_t type; + u_int8_t length; + u_int8_t value[0]; +}; +typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; + +/* Maximum length of a TLV value in bytes */ +#define TLV_VALUE_MAX_LEN 255 + +/** + * The TLV Types. + * + * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c + */ +#define TLV_CODE_PRODUCT_NAME 0x21 +#define TLV_CODE_PART_NUMBER 0x22 +#define TLV_CODE_SERIAL_NUMBER 0x23 +#define TLV_CODE_MAC_BASE 0x24 +#define TLV_CODE_MANUF_DATE 0x25 +#define TLV_CODE_DEVICE_VERSION 0x26 +#define TLV_CODE_LABEL_REVISION 0x27 +#define TLV_CODE_PLATFORM_NAME 0x28 +#define TLV_CODE_ONIE_VERSION 0x29 +#define TLV_CODE_MAC_SIZE 0x2A +#define TLV_CODE_MANUF_NAME 0x2B +#define TLV_CODE_MANUF_COUNTRY 0x2C +#define TLV_CODE_VENDOR_NAME 0x2D +#define TLV_CODE_DIAG_VERSION 0x2E +#define TLV_CODE_SERVICE_TAG 0x2F +#define TLV_CODE_VENDOR_EXT 0xFD +#define TLV_CODE_CRC_32 0xFE + +/* + * Struct for displaying the TLV codes and names. + */ +struct tlv_code_desc { + u_int8_t m_code; + char* m_name; +}; + +/* + * List of TLV codes and names. + */ +static const struct tlv_code_desc tlv_code_list[] = { + { TLV_CODE_PRODUCT_NAME , "Product Name"}, + { TLV_CODE_PART_NUMBER , "Part Number"}, + { TLV_CODE_SERIAL_NUMBER , "Serial Number"}, + { TLV_CODE_MAC_BASE , "Base MAC Address"}, + { TLV_CODE_MANUF_DATE , "Manufacture Date"}, + { TLV_CODE_DEVICE_VERSION , "Device Version"}, + { TLV_CODE_LABEL_REVISION , "Label Revision"}, + { TLV_CODE_PLATFORM_NAME , "Platform Name"}, + { TLV_CODE_ONIE_VERSION , "Loader Version"}, + { TLV_CODE_MAC_SIZE , "MAC Addresses"}, + { TLV_CODE_MANUF_NAME , "Manufacturer"}, + { TLV_CODE_MANUF_COUNTRY , "Country Code"}, + { TLV_CODE_VENDOR_NAME , "Vendor Name"}, + { TLV_CODE_DIAG_VERSION , "Diag Version"}, + { TLV_CODE_SERVICE_TAG , "Service Tag"}, + { TLV_CODE_VENDOR_EXT , "Vendor Extension"}, + { TLV_CODE_CRC_32 , "CRC-32"}, +}; + +static inline const char* tlv_type2name(u_int8_t type) +{ + char* name = "Unknown"; + int i; + + for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) { + if (tlv_code_list[i].m_code == type) { + name = tlv_code_list[i].m_name; + break; + } + } + return name; +} + +/* + * The max decode value is currently for the 'raw' type or the 'vendor + * extension' type, both of which have the same decode format. The + * max decode string size is computed as follows: + * + * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 + * + */ +#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1) + + +/* + * Each platform must define the following platform-specific macros + * in sys_eeprom_platform.h: + * SYS_EEPROM_SIZE: size of usable eeprom + * SYS_EEPROM_I2C_DEVICE: i2c-bus + * SYS_EEPROM_I2C_ADDR: address on the bus + * The following may also be defined in sys_eeprom_platform.h, else + * the defaults with take over: + * SYS_EEPROM_MAX_SIZE: Total size of the eeprom + * SYS_EEPROM_OFFSET: offset from where the ONIE header starts + */ +#define SYS_EEPROM_MAX_SIZE 2048 +#define SYS_EEPROM_OFFSET 0 +#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE +#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0" +#define SYS_EEPROM_I2C_ADDR 0x53 + +#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE) + #error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE +#endif + +// Access functions to onie_tlvinfo +void show_eeprom(u_int8_t *eeprom); +int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom); +int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom); +void update_eeprom_header(u_int8_t *eeprom); +bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index); +bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code); +bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval); +bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value); +//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.c new file mode 100644 index 00000000..12f7254c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.c @@ -0,0 +1,8248 @@ +#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, + .addr_eeprom =0x50, .page_eeprom =-1, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + +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, + .addr_eeprom =0x50, .page_eeprom =0, .offset_eeprom =0, .length_eeprom =256, +}; + + +/* ========== 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_eeprom(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_eeprom, + self->eeprom_map_p->page_eeprom, + self->eeprom_map_p->offset_eeprom, + self->eeprom_map_p->length_eeprom, + self->eeprom, + "_common_update_attr_eeprom", + 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_eeprom(self, show_err) < 0) { + err_str = "_common_update_attr_eeprom"; + 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_eeprom(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, &_common_update_attr_eeprom, + "common_get_eeprom"); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + memset(buf, 0, self->eeprom_map_p->length_eeprom+1); + memcpy(buf, self->eeprom, self->eeprom_map_p->length_eeprom); + *(buf+self->eeprom_map_p->length_eeprom) = '\n'; + return self->eeprom_map_p->length_eeprom+1; +} + +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_eeprom = common_get_eeprom; + 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_eeprom = common_get_eeprom; + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.h new file mode 100644 index 00000000..405512a0 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/src/transceiver.h @@ -0,0 +1,795 @@ +#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_eeprom; int page_eeprom; int offset_eeprom; int length_eeprom; + 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]; + + uint8_t eeprom[256]; + + /* ========== 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_eeprom)(struct transvr_obj_s *self, char *buf_p); + 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/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/PKG.yml new file mode 100644 index 00000000..99e7eb21 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d7264q28b ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/lib/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/lib/Makefile new file mode 100644 index 00000000..60b70c30 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-inventec-d7264q28b +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_inventec_d7264q28b onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-inventec-d7264q28b.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/onlpdump/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..6b23d82f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_inventec_d7264q28b onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/.module b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/.module new file mode 100644 index 00000000..b6938470 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_inventec_d7264q28b diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/Makefile new file mode 100644 index 00000000..9d95a6d7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_inventec_d7264q28b +AUTOMODULE := x86_64_inventec_d7264q28b +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..89b55369 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_inventec_d7264q28b Autogeneration +# +############################################################################### +x86_64_inventec_d7264q28b_AUTO_DEFS := module/auto/x86_64_inventec_d7264q28b.yml +x86_64_inventec_d7264q28b_AUTO_DIRS := module/inc/x86_64_inventec_d7264q28b module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/x86_64_inventec_d7264q28b.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/x86_64_inventec_d7264q28b.yml new file mode 100644 index 00000000..cf45d51c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/auto/x86_64_inventec_d7264q28b.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_inventec_d7264q28b Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB +- x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_inventec_d7264q28b_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_inventec_d7264q28b_config + + portingmacro: + x86_64_inventec_d7264q28b: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b.x b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b.x new file mode 100644 index 00000000..09dac21c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_config.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_config.h new file mode 100644 index 00000000..8523ce03 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d7264q28b Configuration Header + * + * @addtogroup x86_64_inventec_d7264q28b-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d7264q28b_CONFIG_H__ +#define __x86_64_inventec_d7264q28b_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_inventec_d7264q28b_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING +#define x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT +#define x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB +#define x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI +#define x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_inventec_d7264q28b_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_inventec_d7264q28b_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_inventec_d7264q28b_config_settings table. */ +extern x86_64_inventec_d7264q28b_config_settings_t x86_64_inventec_d7264q28b_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_inventec_d7264q28b_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_inventec_d7264q28b_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_inventec_d7264q28b_porting.h" + +#endif /* __x86_64_inventec_d7264q28b_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_dox.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_dox.h new file mode 100644 index 00000000..fdeb9989 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_inventec_d7264q28b Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d7264q28b_DOX_H__ +#define __x86_64_inventec_d7264q28b_DOX_H__ + +/** + * @defgroup x86_64_inventec_d7264q28b x86_64_inventec_d7264q28b - x86_64_inventec_d7264q28b Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_inventec_d7264q28b-x86_64_inventec_d7264q28b Public Interface + * @defgroup x86_64_inventec_d7264q28b-config Compile Time Configuration + * @defgroup x86_64_inventec_d7264q28b-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_inventec_d7264q28b_DOX_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_porting.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_porting.h new file mode 100644 index 00000000..791687a8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/inc/x86_64_inventec_d7264q28b/x86_64_inventec_d7264q28b_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d7264q28b Porting Macros. + * + * @addtogroup x86_64_inventec_d7264q28b-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d7264q28b_PORTING_H__ +#define __x86_64_inventec_d7264q28b_PORTING_H__ + + +/* */ +#if x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_inventec_d7264q28b_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_inventec_d7264q28b_MALLOC GLOBAL_MALLOC + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_MALLOC malloc + #else + #error The macro x86_64_inventec_d7264q28b_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_FREE + #if defined(GLOBAL_FREE) + #define x86_64_inventec_d7264q28b_FREE GLOBAL_FREE + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_FREE free + #else + #error The macro x86_64_inventec_d7264q28b_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_inventec_d7264q28b_MEMSET GLOBAL_MEMSET + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_MEMSET memset + #else + #error The macro x86_64_inventec_d7264q28b_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_inventec_d7264q28b_MEMCPY GLOBAL_MEMCPY + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_MEMCPY memcpy + #else + #error The macro x86_64_inventec_d7264q28b_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_inventec_d7264q28b_STRNCPY GLOBAL_STRNCPY + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_STRNCPY strncpy + #else + #error The macro x86_64_inventec_d7264q28b_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_inventec_d7264q28b_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_VSNPRINTF vsnprintf + #else + #error The macro x86_64_inventec_d7264q28b_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_inventec_d7264q28b_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_SNPRINTF snprintf + #else + #error The macro x86_64_inventec_d7264q28b_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d7264q28b_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_inventec_d7264q28b_STRLEN GLOBAL_STRLEN + #elif x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d7264q28b_STRLEN strlen + #else + #error The macro x86_64_inventec_d7264q28b_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_inventec_d7264q28b_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..76c9f035 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_inventec_d7264q28b_INCLUDES := -I $(THIS_DIR)inc +x86_64_inventec_d7264q28b_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_inventec_d7264q28b_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d7264q28b ucli:x86_64_inventec_d7264q28b + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..03165b91 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_inventec_d7264q28b_ucli.c + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/debug.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..e34cb3b5 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_inventec_d7264q28b_int.h" + +#if x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_inventec_d7264q28b_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..45fe2b53 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/fani.c @@ -0,0 +1,275 @@ +/************************************************************ + * fani.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define FAN_GPI_ON_MAIN_BOARD INV_PSOC_PREFIX"/fan_gpi" + +#define MAX_FAN_SPEED 18000 +#define MAX_PSU_FAN_SPEED 25500 + +#define PROJECT_NAME +#define LEN_FILE_NAME 80 + +static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_PSOC_PREFIX"/fan1_input", + INV_PSOC_PREFIX"/fan2_input", + INV_PSOC_PREFIX"/fan3_input", + INV_PSOC_PREFIX"/fan4_input", + INV_PSOC_PREFIX"/fan5_input", + INV_PSOC_PREFIX"/fan6_input", + INV_PSOC_PREFIX"/fan7_input", + INV_PSOC_PREFIX"/fan8_input", + INV_PSOC_PREFIX"/rpm_psu1", + INV_PSOC_PREFIX"/rpm_psu2", +}; + +#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[FAN_MAX] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + memset(vstr, 0, 32); + /* get fan present status */ + ret = onlp_file_read_str(vp, FAN_GPI_ON_MAIN_BOARD); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%x", &value); + if (value & (1 << (fid-1))) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + else { + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + } + + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + + return ONLP_STATUS_OK; +} + + +static uint32_t +_onlp_get_fan_direction_on_psu(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) { + continue; + } + + if (PSU_TYPE_AC_F2B == psu_type) { + return ONLP_FAN_STATUS_F2B; + } + else { + return ONLP_FAN_STATUS_B2F; + } + } + + return 0; +} + + +static int +_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info) +{ + int value, ret, index; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + info->status |= ONLP_FAN_STATUS_PRESENT; + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan direction */ + info->status |= _onlp_get_fan_direction_on_psu(); + + if (info->status & ONLP_FAN_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + index = ONLP_OID_ID_GET(info->hdr.id); + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + /* get front fan speed */ + memset(vstr, 0, 32); + ret = onlp_file_read_str(vp, devfiles__[fid]); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + sscanf(*vp, "%d", &value); + info->rpm = value; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0; + + snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA"); + snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA"); + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + rc = _onlp_fani_info_get_fan_on_psu(local_id, info); + break; + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + rc = _onlp_fani_info_get_fan(local_id, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + switch (fid) + { + case FAN_1_ON_PSU1: + return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p); + case FAN_1_ON_PSU2: + return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p); + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + path = FAN_NODE(fan_duty_cycle_percentage); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, path, NULL) != 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..a695afda --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,308 @@ +/************************************************************ + * ledi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define filename "brightness" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_CPLD_PREFIX"/%s_led", + INV_PSOC_PREFIX"/fan_led_%s1", + INV_PSOC_PREFIX"/fan_led_%s2", + INV_PSOC_PREFIX"/fan_led_%s3", + INV_PSOC_PREFIX"/fan_led_%s4", +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_BLUE, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { + {LED_SYS, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_SYS, LED_MODE_RED, ONLP_LED_MODE_RED}, + {LED_FAN1,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN2,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN3,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN4,LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +}; + +static char last_path[][10] = /* must map with onlp_led_id */ +{ + "reserved", + "diag", + "loc", + "fan", + "psu1", + "psu2" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[LED_MAX] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_SYS), "Chassis LED (SYSTEM LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN1), "Fan LED 1 (FAN1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN2), "Fan LED 2 (FAN2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN3), "Fan LED 3 (FAN3 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, + { + { ONLP_LED_ID_CREATE(LED_FAN4), "Fan LED 4 (FAN4 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED, + ONLP_LED_MODE_ON, '0', + }, +}; + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + /* + * Diag LED Off + */ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_SYS), ONLP_LED_MODE_OFF); + + return ONLP_STATUS_OK; +} + +int onlp_chassis_led_read(char *pathp, char *buf, size_t len) +{ + FILE * fp; + + fp = fopen (pathp, "r"); + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + if( fgets (buf, len, fp) == NULL ) { + perror("Error fgets operation"); + } + fclose(fp); + + return(0); +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id, gret = 0, rret = 0; + char fullpath_grn[50] = {0}; + char fullpath_red[50] = {0}; + int gvalue = 0, rvalue = 0; + char buf[32] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + switch (local_id) { + case LED_SYS: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + gret = onlp_chassis_led_read(fullpath_grn, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + gvalue = 1; + } + + rret = onlp_chassis_led_read(fullpath_red, buf, 32); + if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') { + rvalue = 1; + } + if (gret < 0 && rret < 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = -1; + rvalue = -1; + } + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath_grn, devfiles__[local_id], "grn"); + sprintf(fullpath_red, devfiles__[local_id], "red"); + + /* Set LED mode */ + if (onlp_file_read_int(&gvalue, fullpath_grn) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + gvalue = 0; + } + if (onlp_file_read_int(&rvalue, fullpath_red) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + rvalue = 0; + } + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + gvalue = -1; + rvalue = -1; + break; + } + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + if (gvalue == 1 && rvalue == 0) { + info->mode = ONLP_LED_MODE_GREEN; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 1) { + info->mode = ONLP_LED_MODE_RED; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 1 && rvalue == 1) { + info->mode = ONLP_LED_MODE_ORANGE; + info->status |= ONLP_LED_STATUS_ON; + } + else + if (gvalue == 0 && rvalue == 0) { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_ON; + } + else { + info->mode = ONLP_LED_MODE_OFF; + info->status |= ONLP_LED_STATUS_FAILED; + } + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int local_id; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + switch (local_id) { + case LED_SYS: + sprintf(fullpath, "%s%s/%s", INV_CPLD_PREFIX, last_path[local_id], filename); + break; + case LED_FAN1: + case LED_FAN2: + case LED_FAN3: + case LED_FAN4: + sprintf(fullpath, "%s%s/%s", INV_PSOC_PREFIX, last_path[local_id], filename); + break; + default: + DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id); + return ONLP_STATUS_E_INTERNAL; + } + + if (onlp_file_write_int(onlp_to_driver_led_mode(local_id, mode), fullpath, NULL) != 0) + { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..5b3dd1a4 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_inventec_d7264q28b +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..ab185ab6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,184 @@ +/************************************************************ + * platform_lib.c + * + * Copyright 2018 Inventec Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define PSU_NODE_MAX_PATH_LEN 64 + +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + return onlp_file_read((uint8_t*)buffer, buf_size, &data_len, "%s", filename); +} + +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 32 +#define I2C_PSU_FAN_DIR_LEN 8 +#include +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + char fan_dir[I2C_PSU_FAN_DIR_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name); + + if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if(isspace(model_name[strlen(model_name)-1])) { + model_name[strlen(model_name)] = 0; + } + + if (strncmp(model_name, "YM-2651Y", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F; + } + } + + if (strncmp(model_name, "YM-2651V", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_DC_48V_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_DC_48V_B2F; + } + } + + if (strncmp(model_name, "PSU-12V-750", 11) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); + } + + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir); + if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", 3) == 0) { + return PSU_TYPE_DC_12V_F2B; + } + + if (strncmp(fan_dir, "B2F", 3) == 0) { + return PSU_TYPE_DC_12V_B2F; + } + + if (strncmp(fan_dir, "NON", 3) == 0) { + return PSU_TYPE_DC_12V_FANLESS; + } + } + + if (strncmp(model_name, "DPS-150AB-10", 12) == 0) { + if (modelname) { + strncpy(modelname, model_name, 12); + } + + return PSU_TYPE_DC_12V_F2B; + } + + return PSU_TYPE_UNKNOWN; +} + +int psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + *value = 0; + + if (PSU1_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + } + else + if (PSU2_ID == id) { + ret = onlp_file_read_int(value, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); + } + else { + return ONLP_STATUS_E_INTERNAL; + } + + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +int psu_pmbus_info_set(int id, char *node, int value) +{ + char path[PSU_NODE_MAX_PATH_LEN] = {0}; + + switch (id) { + case PSU1_ID: + sprintf(path, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID); + break; + case PSU2_ID: + sprintf(path, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + }; + + if (onlp_file_write_int(value, path, NULL) != 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..d5756322 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,142 @@ +/************************************************************ + * platform_lib.h + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_inventec_d7264q28b_log.h" + +#define ONLP_NODE_MAX_INT_LEN (8) +#define ONLP_NODE_MAX_PATH_LEN (64) + +#define INV_CPLD_COUNT (2) +#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/" +#define INV_CPLD2_PREFIX "/sys/bus/i2c/devices/0-0077/" +#define INV_PSOC_PREFIX "/sys/devices/virtual/hwmon/hwmon1/" +#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/" +#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/" + +#define CHASSIS_SFP_COUNT (64) + +/* + * Definitions of Chassis EEPROM + */ +#define EEPROM_NODE(node) INV_EPRM_PREFIX#node + + +/* + * Definitions of D7264Q28B device + */ +enum onlp_thermal_id { + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE_FIRST, + THERMAL_CPU_CORE_2, + THERMAL_CPU_CORE_3, + THERMAL_CPU_CORE_4, + THERMAL_CPU_CORE_LAST, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, + THERMAL_MAX +}; +#define CHASSIS_THERMAL_COUNT (10) + +enum onlp_fan_id { + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_2_ON_MAIN_BOARD, + FAN_3_ON_MAIN_BOARD, + FAN_4_ON_MAIN_BOARD, + FAN_5_ON_MAIN_BOARD, + FAN_6_ON_MAIN_BOARD, + FAN_7_ON_MAIN_BOARD, + FAN_8_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2, + FAN_MAX +}; +#define CHASSIS_FAN_COUNT (8) + +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_SYS, + LED_FAN1, + LED_FAN2, + LED_FAN3, + LED_FAN4, + LED_MAX +}; +#define CHASSIS_LED_COUNT (1) + +enum onlp_psu_id +{ + PSU_RESERVED = 0, + PSU1_ID, + PSU2_ID, + PSU_MAX +}; +#define CHASSIS_PSU_COUNT (2) + + +#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX +#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_HWMON_PREFIX INV_CPLD_PREFIX +#define PSU2_AC_HWMON_PREFIX INV_CPLD_PREFIX + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F, + PSU_TYPE_DC_48V_F2B, + PSU_TYPE_DC_48V_B2F, + PSU_TYPE_DC_12V_FANLESS, + PSU_TYPE_DC_12V_F2B, + PSU_TYPE_DC_12V_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + +/* + * Definitions of FAN device + */ +#define FAN_BOARD_PATH INV_PSOC_PREFIX +#define FAN_NODE(node) FAN_BOARD_PATH#node + +/* + * Prototypes + */ +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_pmbus_info_set(int id, char *node, int value); + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..70b19202 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/psui.c @@ -0,0 +1,246 @@ +/************************************************************ + * psui.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT (0) +#define PSU_STATUS_POWER_GOOD (1) +#define PSU_STATUS_UNPOWERED (2) +#define PSU_STATUS_FAULT (4) +#define PSU_STATUS_UNINSTALLED (7) + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_CPLD_PREFIX"/psu0", + INV_CPLD_PREFIX"/psu1", +}; + +static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */ +{ + "reserved", + INV_PSOC_PREFIX"/psoc_psu1_%s", + INV_PSOC_PREFIX"/psoc_psu2_%s", +}; + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, status_devfiles__[id]); + } + else if (PSU2_ID == id) { + sprintf(node_path, status_devfiles__[id]); + } + + ret = onlp_file_read_str(vp, node_path); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); + return ONLP_STATUS_E_INTERNAL; + } + + if (!isdigit(*vstrp)) { + return ONLP_STATUS_E_INTERNAL; + } + *value = *vstrp - '0'; + return ONLP_STATUS_OK; +} + + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_module_info_get(int id, onlp_psu_info_t* info) +{ + int ret = 0; + char node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + char vstr[32], *vstrp = vstr, **vp = &vstrp; + int value = 0; + + info->caps |= ONLP_PSU_CAPS_DC12; + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path); + } + else { + info->mvout = value; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path); + } + else { + info->miout = value; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pout"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path); + } + else { + info->mpout = value; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "vin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path); + } + else { + info->mvin = value; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "iin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path); + } + else { + info->miin = value; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "pin"); + ret = onlp_file_read_int(&value, node_path); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path); + } + else { + info->mpin = value; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "model"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->model, *vp, ret-1); + } + else { + //AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->model, "N/A", 3); + } + + memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN); + sprintf(node_path, module_devfiles__[id], "serial"); + ret = onlp_file_read_str(vp, node_path); + if (ret > 0) { + strncpy(info->serial, *vp, ret-1); + } + else { + AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path); + strncpy(info->serial, "N/A", 3); + } + + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { + ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1) + } + }, + }, + { + { + ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0, + { + ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), + ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), + ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2) + } + }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) { + printf("Unable to read PSU(%d) node(psu)\r\n", index); + return ret; + } + + if (val == 0) { + info->status = ONLP_PSU_STATUS_PRESENT; + } + else + if (val == 1) { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ret; + } + else { + info->status = ONLP_PSU_STATUS_FAILED; + return ret; + } + + if ((ret = psu_module_info_get(index, info)) != ONLP_STATUS_OK) { + printf("Unable to read PSU(%d) module information\r\n", index); + } + + return ret; +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..f6fadfed --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,222 @@ +/************************************************************ + * sfpi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include + +#include /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +static char sfp_node_path[ONLP_NODE_MAX_PATH_LEN] = {0}; + +#define NUM_OF_SFP_PORT (CHASSIS_SFP_COUNT) +static const int sfp_mux_index[NUM_OF_SFP_PORT] = { +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, +45, 44, 43, 42, 49, 48, 47, 46, +53, 52, 51, 50, 57, 56, 55, 54, +61, 60, 59, 58, 65, 64, 63, 62, +69, 68, 67, 66, 73, 72, 71, 70 +}; + +#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]) + +static int +sfp_node_read_int(char *node_path, int *value, int data_len) +{ + int ret = 0; + *value = 0; + + ret = onlp_file_read_int(value, node_path); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path); + return ONLP_STATUS_E_INTERNAL; + } + + return ret; +} + +static char* +sfp_get_port_path(int port, char *node_name) +{ + sprintf(sfp_node_path, "/sys/class/swps/port%d/%s", port, node_name); + + return sfp_node_path; +} + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 64} + */ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 0; p < NUM_OF_SFP_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + char* path = sfp_get_port_path(port, "present"); + if (sfp_node_read_int(path, &present, 0) != 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (present == 0) { + present = 1; + } + else + if (present == 1) { + present = 0; + } + else { + AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port); + return ONLP_STATUS_E_INTERNAL; + } + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t presence_all[2] = {0}; + int port, ret, index; + + for (port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) { + if (port == 32) { + index = 1; + } + + ret = onlp_sfpi_is_present(port); + if (ret == 1) { + presence_all[index] |= (1<>= 1; + } + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ +#if 0 + int bus = FRONT_PORT_TO_MUX_INDEX(port); +printf("RYU: onlp_sfpi_eeprom_read(): port = %d, sfp_mux_index = %d\n", port, FRONT_PORT_TO_MUX_INDEX(port)); + memset(data, 0, 256); + /* Read eeprom information into data[] */ + if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0) + { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#else + char* path; + int len = 0; + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + memset(data, 0, 256); + path = sfp_get_port_path(port, "eeprom"); + if (onlp_file_read(&data[0], 256, &len, path) < 0) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } +#endif + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return onlp_sfpi_eeprom_read( port, data); +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = FRONT_PORT_TO_MUX_INDEX(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..1dc8e1b0 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,111 @@ +/************************************************************ + * sysi.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "x86_64_inventec_d7264q28b_int.h" +#include "x86_64_inventec_d7264q28b_log.h" + +#include "platform_lib.h" + +#define NUM_OF_CPLD INV_CPLD_COUNT + +#define NUM_OF_THERMAL_ON_MAIN_BROAD (CHASSIS_THERMAL_COUNT) +#define NUM_OF_FAN_ON_MAIN_BROAD (CHASSIS_FAN_COUNT) +#define NUM_OF_PSU_ON_MAIN_BROAD (CHASSIS_PSU_COUNT) +#define NUM_OF_LED_ON_MAIN_BROAD (CHASSIS_LED_COUNT) + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-inventec-d7264q28b-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + if(onlp_file_read(rdata, 256, size, EEPROM_NODE(eeprom)) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 4 Thermal sensors on the chassis */ + for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 4 Fans on the chassis */ + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +static char *arr_cplddev_version[NUM_OF_CPLD] = +{ + INV_CPLD_PREFIX"/version", + INV_CPLD2_PREFIX"/version", +}; + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int i, v[NUM_OF_CPLD]={0}; + for (i=0; i < NUM_OF_CPLD; i++) { + v[i] = 0; + if(onlp_file_read_int(v+i, arr_cplddev_version[i]) < 0) { + return ONLP_STATUS_E_INTERNAL; + } + } + pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]); + return 0; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/thermali.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/thermali.c new file mode 100644 index 00000000..e5d573a2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,147 @@ +/************************************************************ + * thermali.c + * + * Copyright 2018 Inventec Technology Corporation. + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */ +{ + "reserved", + INV_CTMP_PREFIX"/temp1_%s", + INV_CTMP_PREFIX"/temp2_%s", + INV_CTMP_PREFIX"/temp3_%s", + INV_CTMP_PREFIX"/temp4_%s", + INV_CTMP_PREFIX"/temp5_%s", + INV_PSOC_PREFIX"/temp1_input", + INV_PSOC_PREFIX"/temp2_input", + INV_PSOC_PREFIX"/temp3_input", + INV_PSOC_PREFIX"/temp4_input", + INV_PSOC_PREFIX"/temp5_input", + INV_PSOC_PREFIX"/thermal_psu1", + INV_PSOC_PREFIX"/thermal2_psu1", + INV_PSOC_PREFIX"/thermal_psu2", + INV_PSOC_PREFIX"/thermal2_psu2", +}; + +/* Static values */ +static onlp_thermal_info_t linfo[THERMAL_MAX] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "Physical id 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_2), "CPU Core 0", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_4), "CPU Core 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_LAST), "CPU Core 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "Chassis Thermal Sensor 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "Chassis Thermal Sensor 2", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 3", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 4", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 5", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[local_id]; + + if(local_id >= THERMAL_CPU_CORE_FIRST && local_id <= THERMAL_CPU_CORE_LAST) { + char desc[32], *dp = &desc[0]; + int rv = onlp_file_read_str(&dp, devfiles__[local_id], "label"); + if (rv > 0) { + memset (info->hdr.description, 0, ONLP_OID_DESC_SIZE); + strncpy(info->hdr.description, dp, rv); + } + + /* Set the onlp_oid_hdr_t and capabilities */ + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id], "input"); + } + return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_config.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_config.c new file mode 100644 index 00000000..eb20c710 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(_x) +x86_64_inventec_d7264q28b_config_settings_t x86_64_inventec_d7264q28b_config_settings[] = +{ +#ifdef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_PORTING_STDLIB(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE(x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_inventec_d7264q28b_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d7264q28b_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_inventec_d7264q28b_config_STRINGIFY_VALUE +#undef __x86_64_inventec_d7264q28b_config_STRINGIFY_NAME + +const char* +x86_64_inventec_d7264q28b_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_inventec_d7264q28b_config_settings[i].name; i++) { + if(strcmp(x86_64_inventec_d7264q28b_config_settings[i].name, setting)) { + return x86_64_inventec_d7264q28b_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_inventec_d7264q28b_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_inventec_d7264q28b_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_inventec_d7264q28b_config_settings[i].name, x86_64_inventec_d7264q28b_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_enums.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_enums.c new file mode 100644 index 00000000..1f9d37df --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_int.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_int.h new file mode 100644 index 00000000..9eed2fa6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_inventec_d7264q28b Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d7264q28b_INT_H__ +#define __x86_64_inventec_d7264q28b_INT_H__ + +#include + + +#endif /* __x86_64_inventec_d7264q28b_INT_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.c new file mode 100644 index 00000000..45c4f1ab --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d7264q28b_log.h" +/* + * x86_64_inventec_d7264q28b log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_inventec_d7264q28b_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_inventec_d7264q28b_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_inventec_d7264q28b_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.h new file mode 100644 index 00000000..4572bc65 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d7264q28b_LOG_H__ +#define __x86_64_inventec_d7264q28b_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_inventec_d7264q28b +#include + +#endif /* __x86_64_inventec_d7264q28b_LOG_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_module.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_module.c new file mode 100644 index 00000000..64fb545e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d7264q28b_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_inventec_d7264q28b_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_inventec_d7264q28b_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_ucli.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_ucli.c new file mode 100644 index 00000000..58b62f50 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/onlp/builds/src/module/src/x86_64_inventec_d7264q28b_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_inventec_d7264q28b_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_inventec_d7264q28b_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d7264q28b) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_inventec_d7264q28b_ucli_module__ = + { + "x86_64_inventec_d7264q28b_ucli", + NULL, + x86_64_inventec_d7264q28b_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_inventec_d7264q28b_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_inventec_d7264q28b_ucli_module__); + n = ucli_node_create("x86_64_inventec_d7264q28b", NULL, &x86_64_inventec_d7264q28b_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d7264q28b")); + return n; +} + +#else +void* +x86_64_inventec_d7264q28b_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/PKG.yml new file mode 100644 index 00000000..c6c99462 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d7264q28b REVISION=r0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/lib/x86-64-inventec-d7264q28b-r0.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/lib/x86-64-inventec-d7264q28b-r0.yml new file mode 100644 index 00000000..fe6a4643 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/lib/x86-64-inventec-d7264q28b-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for d7264q28b +# +###################################################################### + +x86-64-inventec-d7264q28b-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/python/x86_64_inventec_d7264q28b_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/python/x86_64_inventec_d7264q28b_r0/__init__.py new file mode 100644 index 00000000..28678eca --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/platform-config/r0/src/python/x86_64_inventec_d7264q28b_r0/__init__.py @@ -0,0 +1,20 @@ +from onl.platform.base import * +from onl.platform.inventec import * + +class OnlPlatform_x86_64_inventec_d7264q28b_r0(OnlPlatformInventec, + OnlPlatformPortConfig_64x100): + PLATFORM='x86-64-inventec-d7264q28b-r0' + MODEL="X86-D7264Q28B" + SYS_OBJECT_ID="7264.28" + + def baseconfig(self): + os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko") + self.insmod('inv_platform') + self.insmod('inv_psoc') + self.insmod('inv_cpld') + self.new_i2c_device('inv_eeprom', 0x53, 0) + self.insmod('inv_eeprom') + self.insmod('swps') + self.insmod('vpd') + self.insmod('inv_pthread') + return True diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/PKG.yml new file mode 100644 index 00000000..73373296 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-mqm8700 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/PKG.yml new file mode 100644 index 00000000..0024bcd2 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-mlnx-mqm8700 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/Makefile new file mode 100644 index 00000000..765baa47 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-mlnx-mqm8700 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF mlnx_common x86_64_mlnx_mqm8700 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-mlnx-mqm8700.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -I$(mlnx_common_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700-r0.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700-r0.mk new file mode 100644 index 00000000..fac6eb51 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700-r0.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-mlnx-mqm8700-r0 module. +# +# Autogenerated 2015-12-23 23:45:22.249911 +# +############################################################################### +libonlp-x86-64-mlnx-mqm8700-r0_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700.mk new file mode 100644 index 00000000..ad59e890 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/libonlp-x86-64-mlnx-mqm8700.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-mlnx-mqm8700 module. +# +# Autogenerated 2016-10-13 22:58:39.095824 +# +############################################################################### +libonlp-x86-64-mlnx-mqm8700_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/x86_64_mlnx_mqm8700.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/x86_64_mlnx_mqm8700.mk new file mode 100644 index 00000000..3f2da271 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/lib/x86_64_mlnx_mqm8700.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the x86_64_mlnx_mqm8700 module. +# +# Autogenerated 2015-12-23 23:45:22.262891 +# +############################################################################### +x86_64_mlnx_mqm8700_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..58b6ac82 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp mlnx_common x86_64_mlnx_mqm8700 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/onlpdump.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/onlpdump.mk new file mode 100644 index 00000000..77d7d005 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/onlpdump/onlpdump.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the onlpdump module. +# +# Autogenerated 2016-10-13 22:58:37.393320 +# +############################################################################### +onlpdump_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/.module b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/.module new file mode 100644 index 00000000..88444c31 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_mlnx_mqm8700 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/Makefile new file mode 100644 index 00000000..de4fbe78 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_mlnx_mqm8700 +AUTOMODULE := x86_64_mlnx_mqm8700 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/README b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/README new file mode 100644 index 00000000..cc54e7d0 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_mlnx_mqm8700 README +# +############################################################################### + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/make.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..aefe42e8 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_mlnx_mqm8700 Autogeneration +# +############################################################################### +x86_64_mlnx_mqm8700_AUTO_DEFS := module/auto/x86_64_mlnx_mqm8700.yml +x86_64_mlnx_mqm8700_AUTO_DIRS := module/inc/x86_64_mlnx_mqm8700 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/x86_64_mlnx_mqm8700.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/x86_64_mlnx_mqm8700.yml new file mode 100644 index 00000000..c0bf4ddd --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/auto/x86_64_mlnx_mqm8700.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_mlnx_mqm8700 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_mlnx_mqm8700_CONFIG_PORTING_STDLIB +- X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_MLNX_MQM8700_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_mlnx_mqm8700_config + + portingmacro: + x86_64_mlnx_mqm8700: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700.x b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700.x new file mode 100644 index 00000000..7b17366e --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_config.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_config.h new file mode 100644 index 00000000..a94542fd --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_mlnx_mqm8700 Configuration Header + * + * @addtogroup x86_64_mlnx_mqm8700-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_MLNX_MQM8700_CONFIG_H__ +#define __X86_64_MLNX_MQM8700_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_MLNX_MQM8700_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING +#define X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT +#define X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB +#define X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI +#define X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_mlnx_mqm8700_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_mlnx_mqm8700_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_mlnx_mqm8700_config_settings table. */ +extern x86_64_mlnx_mqm8700_config_settings_t x86_64_mlnx_mqm8700_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_mlnx_mqm8700_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_mlnx_mqm8700_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_mlnx_mqm8700_porting.h" + +#endif /* __X86_64_MLNX_MQM8700_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_dox.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_dox.h new file mode 100644 index 00000000..454bfb64 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_mlnx_mqm8700 Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_MLNX_MQM8700_DOX_H__ +#define __X86_64_MLNX_MQM8700_DOX_H__ + +/** + * @defgroup x86_64_mlnx_mqm8700 x86_64_mlnx_mqm8700 - x86_64_mlnx_mqm8700 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_mlnx_mqm8700-x86_64_mlnx_mqm8700 Public Interface + * @defgroup x86_64_mlnx_mqm8700-config Compile Time Configuration + * @defgroup x86_64_mlnx_mqm8700-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_MLNX_MQM8700_DOX_H__ */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_porting.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_porting.h new file mode 100644 index 00000000..d7e87576 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/inc/x86_64_mlnx_mqm8700/x86_64_mlnx_mqm8700_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_mlnx_mqm8700 Porting Macros. + * + * @addtogroup x86_64_mlnx_mqm8700-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_MLNX_MQM8700_PORTING_H__ +#define __X86_64_MLNX_MQM8700_PORTING_H__ + + +/* */ +#if X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_MLNX_MQM8700_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_MLNX_MQM8700_MALLOC GLOBAL_MALLOC + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_MALLOC malloc + #else + #error The macro X86_64_MLNX_MQM8700_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_FREE + #if defined(GLOBAL_FREE) + #define X86_64_MLNX_MQM8700_FREE GLOBAL_FREE + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_FREE free + #else + #error The macro X86_64_MLNX_MQM8700_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_MLNX_MQM8700_MEMSET GLOBAL_MEMSET + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_MEMSET memset + #else + #error The macro X86_64_MLNX_MQM8700_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_MLNX_MQM8700_MEMCPY GLOBAL_MEMCPY + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_MEMCPY memcpy + #else + #error The macro X86_64_MLNX_MQM8700_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_MLNX_MQM8700_STRNCPY GLOBAL_STRNCPY + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_STRNCPY strncpy + #else + #error The macro X86_64_MLNX_MQM8700_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_MLNX_MQM8700_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_VSNPRINTF vsnprintf + #else + #error The macro X86_64_MLNX_MQM8700_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_MLNX_MQM8700_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_SNPRINTF snprintf + #else + #error The macro X86_64_MLNX_MQM8700_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_MLNX_MQM8700_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_MLNX_MQM8700_STRLEN GLOBAL_STRLEN + #elif X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB == 1 + #define X86_64_MLNX_MQM8700_STRLEN strlen + #else + #error The macro X86_64_MLNX_MQM8700_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_MLNX_MQM8700_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/make.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..c85531db --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_mlnx_mqm8700_INCLUDES := -I $(THIS_DIR)inc +x86_64_mlnx_mqm8700_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_mlnx_mqm8700_DEPENDMODULE_ENTRIES := init:x86_64_mlnx_mqm8700 ucli:x86_64_mlnx_mqm8700 + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..e4172517 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_mlnx_mqm8700_ucli.c + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/fani.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..852142e4 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/fani.c @@ -0,0 +1,107 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" +#include "mlnx_common/mlnx_common.h" + +#define FAN_RESERVED 0 +#define FAN_1_ON_MAIN_BOARD 1 +#define FAN_2_ON_MAIN_BOARD 2 +#define FAN_3_ON_MAIN_BOARD 3 +#define FAN_4_ON_MAIN_BOARD 4 +#define FAN_5_ON_MAIN_BOARD 5 +#define FAN_6_ON_MAIN_BOARD 6 +#define FAN_7_ON_MAIN_BOARD 7 +#define FAN_8_ON_MAIN_BOARD 8 +#define FAN_9_ON_MAIN_BOARD 9 +#define FAN_10_ON_MAIN_BOARD 10 +#define FAN_11_ON_MAIN_BOARD 11 +#define FAN_12_ON_MAIN_BOARD 12 +#define FAN_1_ON_PSU1 13 +#define FAN_1_ON_PSU2 14 + +#define FIRST_PSU_FAN_ID 13 + +static int min_fan_speed[CHASSIS_FAN_COUNT+1] = {0}; +static int max_fan_speed[CHASSIS_FAN_COUNT+1] = {0}; + +static fan_path_T fan_path[] = /* must map with onlp_fan_id */ +{ + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_RESERVED), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_1_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_2_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_3_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_4_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_5_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_6_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_7_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_8_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_9_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_10_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_11_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_12_ON_MAIN_BOARD), + MAKE_FAN_PATH_ON_PSU(1 ,1), + MAKE_FAN_PATH_ON_PSU(2, 1) +}; + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(9), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(10), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(11), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(12), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1) +}; + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + mlnx_platform_info_t* mlnx_platform_info = get_platform_info(); + mlnx_platform_info->min_fan_speed = min_fan_speed; + mlnx_platform_info->max_fan_speed = max_fan_speed; + mlnx_platform_info->finfo = finfo; + mlnx_platform_info->fan_fnames = fan_path; + mlnx_platform_info->fan_type = FAN_TYPE_NO_EEPROM; + mlnx_platform_info->fan_per_module = 2; + mlnx_platform_info->first_psu_fan_id = FIRST_PSU_FAN_ID; + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/ledi.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..2e4224dd --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,117 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include + +static char* file_names[] = /* must map with onlp_led_id */ +{ + "reserved", + "status", + "fan1", + "fan2", + "fan3", + "fan4", + "fan5", + "fan6", + "psu", +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_SYSTEM), "Chassis LED 1 (SYSTEM LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN1), "Chassis LED 2 (FAN1 (1-2) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN2), "Chassis LED 3 (FAN2 (3-4) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN3), "Chassis LED 4 (FAN3 (5-6) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN4), "Chassis LED 5 (FAN5 (7-8) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN5), "Chassis LED 6 (FAN5 (9-10) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN6), "Chassis LED 7 (FAN6 (11-12) )", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU_T3), "Chassis LED 8 (PSU LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO, + }, +}; + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + /* + * ONLPD calls it too early before all BSP insfrastructure is set + */ + mlnx_platform_info_t* mlnx_platform_info = get_platform_info(); + mlnx_platform_info->linfo = linfo; + mlnx_platform_info->led_fnames = file_names; + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/make.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..8dd3e0f9 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_mlnx_mqm8700 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..fd26ee65 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,39 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_mlnx_mqm8700_log.h" + +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_TOTAL_FAN_COUNT 14 +#define CHASSIS_TOTAL_THERMAL_COUNT 8 +#define CHASSIS_FAN_COUNT (CHASSIS_TOTAL_FAN_COUNT - CHASSIS_PSU_COUNT) +#define CHASSIS_THERMAL_COUNT (CHASSIS_TOTAL_THERMAL_COUNT - CHASSIS_PSU_COUNT) +#define CPLD_COUNT 3 +#define SFP_PORT_COUNT 32 +#define CHASSIS_LED_COUNT 8 + +#endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/sysi.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..677f64b0 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,64 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_mlnx_mqm8700_int.h" +#include "x86_64_mlnx_mqm8700_log.h" + +#define ONL_PLATFORM_NAME "x86-64-mlnx-mqm8700-r0" + +int mc_get_platform_info(mlnx_platform_info_t* mlnx_platform) +{ + strncpy(mlnx_platform->onl_platform_name, ONL_PLATFORM_NAME, PLATFORM_NAME_MAX_LEN); + mlnx_platform->sfp_num = SFP_PORT_COUNT; + mlnx_platform->led_num = CHASSIS_LED_COUNT; + mlnx_platform->psu_num = CHASSIS_PSU_COUNT; + mlnx_platform->fan_num = CHASSIS_FAN_COUNT; + mlnx_platform->thermal_num = CHASSIS_THERMAL_COUNT; + mlnx_platform->cpld_num = CPLD_COUNT; + mlnx_platform->psu_fixed = false; + mlnx_platform->fan_fixed = false; + mlnx_platform->psu_type = PSU_TYPE_2; + mlnx_platform->led_type = LED_TYPE_3; + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_config.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_config.c new file mode 100644 index 00000000..033e2e16 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(_x) #_x +#define __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(_x) __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(_x) +x86_64_mlnx_mqm8700_config_settings_t x86_64_mlnx_mqm8700_config_settings[] = +{ +#ifdef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_INCLUDE_LOGGING(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_PORTING_STDLIB(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_INCLUDE_UCLI(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_MLNX_MQM8700_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_VALUE +#undef __X86_64_MLNX_MQM8700_CONFIG_STRINGIFY_NAME + +const char* +x86_64_mlnx_mqm8700_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_mlnx_mqm8700_config_settings[i].name; i++) { + if(strcmp(x86_64_mlnx_mqm8700_config_settings[i].name, setting)) { + return x86_64_mlnx_mqm8700_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_mlnx_mqm8700_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_mlnx_mqm8700_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_mlnx_mqm8700_config_settings[i].name, x86_64_mlnx_mqm8700_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_enums.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_enums.c new file mode 100644 index 00000000..195e3b13 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_int.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_int.h new file mode 100644 index 00000000..66b0794c --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_mlnx_mqm8700 Internal Header + * + *****************************************************************************/ +#ifndef __X86_64_MLNX_MQM8700_INT_H__ +#define __X86_64_MLNX_MQM8700_INT_H__ + +#include + + +#endif /* __X86_64_MLNX_MQM8700_INT_H__ */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.c new file mode 100644 index 00000000..a2b106e6 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_mlnx_mqm8700_log.h" +/* + * x86_64_mlnx_mqm8700 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_MLNX_MQM8700_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_MLNX_MQM8700_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_MLNX_MQM8700_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.h b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.h new file mode 100644 index 00000000..0b528889 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __X86_64_MLNX_MQM8700_LOG_H__ +#define __X86_64_MLNX_MQM8700_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_mlnx_mqm8700 +#include + +#endif /* __X86_64_MLNX_MQM8700_LOG_H__ */ diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_module.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_module.c new file mode 100644 index 00000000..83b1eae9 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_mlnx_mqm8700_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_mlnx_mqm8700_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_mlnx_mqm8700_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_ucli.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_ucli.c new file mode 100644 index 00000000..8909f39a --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/module/src/x86_64_mlnx_mqm8700_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_mlnx_mqm8700_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_mlnx_mqm8700_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_mlnx_mqm8700) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_mlnx_mqm8700_ucli_module__ = + { + "x86_64_mlnx_mqm8700_ucli", + NULL, + x86_64_mlnx_mqm8700_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_mlnx_mqm8700_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_mlnx_mqm8700_ucli_module__); + n = ucli_node_create("x86_64_mlnx_mqm8700", NULL, &x86_64_mlnx_mqm8700_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_mlnx_mqm8700")); + return n; +} + +#else +void* +x86_64_mlnx_mqm8700_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/x86_64_mlnx_mqm8700.mk b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/x86_64_mlnx_mqm8700.mk new file mode 100644 index 00000000..ec1d2eb6 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/onlp/builds/src/x86_64_mlnx_mqm8700.mk @@ -0,0 +1,13 @@ + +############################################################################### +# +# Inclusive Makefile for the x86_64_mlnx_mqm8700 module. +# +# Autogenerated 2015-12-23 23:45:56.754200 +# +############################################################################### +x86_64_mlnx_mqm8700_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(x86_64_mlnx_mqm8700_BASEDIR)/module/make.mk +include $(x86_64_mlnx_mqm8700_BASEDIR)/module/auto/make.mk +include $(x86_64_mlnx_mqm8700_BASEDIR)/module/src/make.mk + diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/PKG.yml new file mode 100644 index 00000000..6dd5281e --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-mqm8700 REVISION=r0 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/lib/x86-64-mlnx-mqm8700-r0.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/lib/x86-64-mlnx-mqm8700-r0.yml new file mode 100644 index 00000000..cedd2d49 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/lib/x86-64-mlnx-mqm8700-r0.yml @@ -0,0 +1,36 @@ +--- + +###################################################################### +# +# platform-config for Mellanox mqm8700 +# +###################################################################### + +x86-64-mlnx-mqm8700-r0: + + grub: + + serial: >- + --unit=0 + --speed=115200 + --word=8 + --parity=0 + --stop=1 + + kernel: + <<: *kernel-4-9 + + args: >- + nopat + console=ttyS0,115200n8 + rd_NO_MD + rd_NO_LUKS + acpi_enforce_resources=lax + acpi=noirq + i2c-ismt.enable=0 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/python/x86_64_mlnx_mqm8700_r0/__init__.py b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/python/x86_64_mlnx_mqm8700_r0/__init__.py new file mode 100644 index 00000000..99fc6c29 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-mqm8700/platform-config/r0/src/python/x86_64_mlnx_mqm8700_r0/__init__.py @@ -0,0 +1,17 @@ +from onl.platform.base import * +from onl.platform.mellanox import * + +class OnlPlatform_x86_64_mlnx_mqm8700_r0(OnlPlatformMellanox, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-mlnx-mqm8700-r0' + MODEL="MQM8700" + SYS_OBJECT_ID=".8700.1" + + def baseconfig(self): + # load modules + import os + # necessary if there are issues with the install + # os.system("/usr/bin/apt-get install") + os.system("/etc/mlnx/mlnx-hw-management start") + self.syseeprom_export(); + return True diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100/onlp/builds/src/module/src/sysi.c b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100/onlp/builds/src/module/src/sysi.c index d0c181e4..20703dd9 100644 --- a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100/onlp/builds/src/module/src/sysi.c @@ -37,13 +37,20 @@ #include "x86_64_mlnx_msn2100_log.h" #include +static const char* __ONL_PLATFORM_NAME = NULL; + #define ONL_PLATFORM_NAME "x86-64-mlnx-msn2100-r0" #define COMMAND_OUTPUT_BUFFER 256 int mc_get_platform_info(mlnx_platform_info_t* mlnx_platform) { - strncpy(mlnx_platform->onl_platform_name, ONL_PLATFORM_NAME, PLATFORM_NAME_MAX_LEN); + if (!__ONL_PLATFORM_NAME) { + strncpy(mlnx_platform->onl_platform_name, "x86-64-mlnx-msn2100-all", PLATFORM_NAME_MAX_LEN); + } + else { + strncpy(mlnx_platform->onl_platform_name, __ONL_PLATFORM_NAME, PLATFORM_NAME_MAX_LEN); + } mlnx_platform->sfp_num = SFP_PORT_COUNT; mlnx_platform->led_num = CHASSIS_LED_COUNT; mlnx_platform->psu_num = CHASSIS_PSU_COUNT; @@ -58,6 +65,29 @@ int mc_get_platform_info(mlnx_platform_info_t* mlnx_platform) return ONLP_STATUS_OK; } +int +onlp_sysi_platform_set(const char* platform) +{ + mlnx_platform_info_t* mlnx_platform; + + if(!strcmp(platform, "x86-64-mlnx-msn2100-r0")) { + __ONL_PLATFORM_NAME = "x86-64-mlnx_msn2100-r0"; + mlnx_platform = get_platform_info(); + mc_get_platform_info(mlnx_platform); + return ONLP_STATUS_OK; + } + if(!strcmp(platform, "x86-64-mlnx-msn2100b-r0")) { + __ONL_PLATFORM_NAME = "x86-64-mlnx_msn2100b-r0"; + mlnx_platform = get_platform_info(); + mc_get_platform_info(mlnx_platform); + return ONLP_STATUS_OK; + } + if(!strcmp(platform, "x86-64-mlnx-msn2100-all")) { + __ONL_PLATFORM_NAME = "x86-64-mlnx-msn2100-all"; + return ONLP_STATUS_OK; + } + return ONLP_STATUS_E_UNSUPPORTED; +} int onlp_sysi_init(void) diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/.gitignore b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/.gitignore new file mode 100644 index 00000000..3edba0a7 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/.gitignore @@ -0,0 +1,3 @@ +*x86-64*.mk +*x86_64*.mk +onlpdump.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/PKG.yml new file mode 100644 index 00000000..19bf5927 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-msn2100b diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/PKG.yml new file mode 100644 index 00000000..50f9595b --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-mlnx-msn2100b ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/lib/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/lib/Makefile new file mode 100644 index 00000000..c20febe4 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-mlnx-msn2100b +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF mlnx_common x86_64_mlnx_msn2100 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-mlnx-msn2100b.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -I$(mlnx_common_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/onlpdump/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..e913e64a --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp mlnx_common x86_64_mlnx_msn2100 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_CFLAGS += -I$(mlnx_common_BASEDIR)/module/inc +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/Makefile b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/Makefile new file mode 100644 index 00000000..dc1e7b86 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/PKG.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/PKG.yml new file mode 100644 index 00000000..03b0a322 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-msn2100b REVISION=r0 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/lib/x86-64-mlnx-msn2100b-r0.yml b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/lib/x86-64-mlnx-msn2100b-r0.yml new file mode 100644 index 00000000..a94740c0 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/lib/x86-64-mlnx-msn2100b-r0.yml @@ -0,0 +1,36 @@ +--- + +###################################################################### +# +# platform-config for Mellanox 2100B +# +###################################################################### + +x86-64-mlnx-msn2100b-r0: + + grub: + + serial: >- + --unit=0 + --speed=115200 + --word=8 + --parity=0 + --stop=1 + + kernel: + <<: *kernel-4-9 + + args: >- + nopat + console=ttyS0,115200n8 + rd_NO_MD + rd_NO_LUKS + acpi_enforce_resources=lax + acpi=noirq + i2c-ismt.enable=0 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/python/x86_64_mlnx_msn2000b_r0/__init__.py b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/python/x86_64_mlnx_msn2000b_r0/__init__.py new file mode 100644 index 00000000..16824352 --- /dev/null +++ b/packages/platforms/mellanox/x86-64/x86-64-mlnx-msn2100b/platform-config/r0/src/python/x86_64_mlnx_msn2000b_r0/__init__.py @@ -0,0 +1,17 @@ +from onl.platform.base import * +from onl.platform.mellanox import * + +class OnlPlatform_x86_64_mlnx_msn2100b_r0(OnlPlatformMellanox, + OnlPlatformPortConfig_32x40): + PLATFORM='x86-64-mlnx-msn2100b-r0' + MODEL="MSN2100B" + SYS_OBJECT_ID=".2100.2" + + def baseconfig(self): + # load modules + import os + # necessary if there are issues with the install + # os.system("/usr/bin/apt-get install") + os.system("/etc/mlnx/mlnx-hw-management start") + self.syseeprom_export(); + return True diff --git a/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py b/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py index 96061bb8..ce64a2e9 100755 --- a/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py +++ b/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py @@ -4,4 +4,4 @@ from onl.platform.base import * class OnlPlatformNetberg(OnlPlatformBase): MANUFACTURER='Netberg' - PRIVATE_ENTERPRISE_NUMBER=47294 + PRIVATE_ENTERPRISE_NUMBER=50424 diff --git a/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c b/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c index fa3e711e..2f2f09eb 100755 --- a/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c +++ b/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c @@ -25,8 +25,11 @@ enum platform_type { #define W83795ADG_VENDOR_ID 0x5CA3 #define W83795ADG_CHIP_ID 0x79 -#define W83795ADG_TEMP_COUNT 2 -#define W83795ADG_FAN_COUNT 8 +#define W83795ADG_NUM2 2 +#define W83795ADG_NUM8 8 + +#define W83795ADG_TEMP_COUNT 4 +#define W83795ADG_FAN_COUNT 10 #define W83795ADG_FAN_SPEED_FACTOR 1350000 /* 1.35 * 10^6 */ #define W83795ADG_FAN_POLES_NUMBER 4 #define W83795ADG_VSEN_COUNT 7 @@ -44,6 +47,7 @@ enum platform_type { /* Bank 0*/ #define W83795ADG_REG_CONFIG 0x01 /* Configuration Register */ #define W83795ADG_REG_TEMP_CTRL2 0x05 /* Temperature Monitoring Control Register */ +#define W83795ADG_REG_FANIN_CTRL2 0x07 /* FANIN CTRL2. FANIN Monitoring Control Register */ #define W83795ADG_REG_VSEN1 0x10 /* VSEN1 voltage readout high byte */ #define W83795ADG_REG_VSEN2 0x11 /* VSEN2 voltage readout high byte */ #define W83795ADG_REG_VSEN3 0x12 /* VSEN3 voltage readout high byte */ @@ -87,6 +91,8 @@ enum platform_type { #define CPLD_REG_LED 0x44 /* FAN LED */ +#define CPLD_REG_MUX 0x4A /* I2C MUX control Register */ + /* 9548 Channel Index */ #define PCA9548_CH00 0 #define PCA9548_CH01 1 @@ -195,6 +201,7 @@ typedef enum /* QSFP */ #define QSFP_COUNT 64 #define QSFP_DATA_SIZE 256 +#define SFP_COPPER_DATA_SIZE 512 #define EEPROM_DATA_SIZE 256 @@ -203,7 +210,9 @@ typedef struct unsigned char tempLow2HighThreshold[3]; unsigned char tempHigh2LowThreshold[3]; unsigned char fanDutySet[3]; -} fanControlTable_t; + unsigned int fanSpeed[3]; + unsigned int inSet[W83795ADG_VSEN_COUNT][3]; +} ControlTable_t; static int w83795adg_hardware_monitor_probe(struct i2c_client *client, const struct i2c_device_id *id); static int w83795adg_hardware_monitor_detect(struct i2c_client *client, struct i2c_board_info *info); @@ -310,9 +319,10 @@ SFP_PORT_DATA_t sfpPortData_78F[] = { static struct i2c_client qsfpDataA0_client; static struct i2c_client qsfpDataA2_client; +static struct i2c_client SfpCopperData_client; /* i2c bus 0 */ -static struct i2c_client pca9535pwr_client; +static struct i2c_client pca9535pwr_client_bus0; static struct i2c_client cpld_client; static struct i2c_client pca9548_client_bus0; static struct i2c_client pca9535_client_bus0[4]; @@ -324,15 +334,15 @@ static struct i2c_client psu_mcu_client_bus0; /* i2c bus 1 */ static struct i2c_client pca9548_client[4]; -static struct i2c_client pca9535pwr_client_bus1[6]; +static struct i2c_client pca9535pwr_client[6]; static struct i2c_client eeprom_client; -static struct i2c_client eeprom_client_2; static struct i2c_client psu_eeprom_client; static struct i2c_client psu_mcu_client; static unsigned int FanErr[W83795ADG_FAN_COUNT] = {0}; static unsigned int FanDir = 0; +static unsigned int FanDir2 = 0; static unsigned int isBMCSupport = 0; static unsigned int platformBuildRev = 0xffff; @@ -344,9 +354,12 @@ static char platformPsuABS = 0; unsigned int SFPPortAbsStatus[QSFP_COUNT]; unsigned int SFPPortRxLosStatus[QSFP_COUNT]; +unsigned int SFPPortTxFaultStatus[QSFP_COUNT]; char SFPPortDataValid[QSFP_COUNT]; char SFPPortTxDisable[QSFP_COUNT]; +static struct i2c_client cpld_client_bus1; + struct i2c_bus0_hardware_monitor_data { struct device *hwmon_dev; struct attribute_group hwmon_group; @@ -405,16 +418,27 @@ struct i2c_bus1_hardware_monitor_data { unsigned short qsfpPortAbsStatus[4]; char qsfpPortDataA0[QSFP_COUNT][QSFP_DATA_SIZE]; char qsfpPortDataA2[QSFP_COUNT][QSFP_DATA_SIZE]; + char SfpCopperPortData[QSFP_COUNT][SFP_COPPER_DATA_SIZE]; unsigned short qsfpPortDataValid[4]; unsigned short sfpPortTxDisable[3]; unsigned short sfpPortRateSelect[3]; unsigned short sfpPortRxLosStatus[4]; + unsigned short sfpPortTxFaultStatus[4]; unsigned short fanAbs[2]; unsigned short fanDir[2]; unsigned short systemLedStatus; unsigned short frontLedStatus; + unsigned char sfpPortDataValidAst[64]; + unsigned char sfpPortAbsRxLosStatus[24]; + unsigned char qsfpPortAbsStatusAst[16]; + unsigned char sfpPortRateSelectAst[12]; + unsigned char sfpPortTxDisableAst[6]; + + char qsfpPortTxDisableData[QSFP_COUNT]; + char qsfpPortTxDisableDataUpdate[QSFP_COUNT]; + struct i2c_client *sfpPortClient[QSFP_COUNT]; }; /* Addresses to scan */ @@ -441,51 +465,140 @@ static struct i2c_driver w83795adg_hardware_monitor_driver = { }; /* Front to Back */ -static fanControlTable_t fanControlTable[] = +static ControlTable_t ControlTable[] = { /* Huracan */ { - {77, 95, 105}, /* temperature threshold (going to up) */ - {72, 77, 95}, /* temperature threshold (going to down) */ - {0x6C, 0x9E, 0xFF} /* fan rpm : 8000, 12000, 16000 */ + {77, 95, 105}, /* temperature threshold (going to up) */ + {72, 77, 95}, /* temperature threshold (going to down) */ + {0x6C, 0x9E, 0xFF}, /* fan duty */ + {8000, 12000, 16000}, /* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ }, /* Sesto */ { - {85, 95, 100}, /* temperature threshold (going to up) */ - {71, 85, 95}, /* temperature threshold (going to down) */ - {0x73, 0xCC, 0xFF} /* fan rpm : 9000, 14000, 16000 */ + {85, 95, 100}, /* temperature threshold (going to up) */ + {71, 85, 95}, /* temperature threshold (going to down) */ + {0x73, 0xCC, 0xFF}, /* fan duty */ + {9000, 14000, 16000}, /* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ }, /* NC2X */ { - {62, 70, 85}, /* temperature threshold (going to up) */ - {58, 66, 70}, /* temperature threshold (going to down) */ - {0x70, 0xB7, 0xFF} /* fan rpm : 8000, 13000, 16000 */ + {62, 70, 85}, /* temperature threshold (going to up) */ + {58, 66, 70}, /* temperature threshold (going to down) */ + {0x70, 0xB7, 0xFF}, /* fan duty */ + {8000, 13000, 16000}, /* fan rpm */ + { + {970, 1250,1275}, /* vsen1 */ + {0}, /* vsen2 */ + {0}, /* vsen3 */ + {970, 1000,1030}, /* vsen4 */ + {1710,1800,1890}, /* vsen5 */ + {0}, /* rsvd */ + {1187,1250,1312}, /* vsen7 */ + }, + }, + /* Asterion */ + { + {70, 75, 80}, /* temperature threshold (going to up) */ + {60, 65, 70}, /* temperature threshold (going to down) */ + {0x8B, 0xD1, 0xFF}, /* fan duty */ + {12000, 18000, 22000},/* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ } }; /* Back to Front */ -static fanControlTable_t fanControlTable_B2F[] = +static ControlTable_t ControlTable_B2F[] = { /* Huracan */ { - {70, 77, 105}, /* temperature threshold (going to up) */ - {60, 70, 77}, /* temperature threshold (going to down) */ - {0x6C, 0xC7, 0xFF} /* fan rpm : 8000, 14000, 16000 */ + {70, 77, 105}, /* temperature threshold (going to up) */ + {60, 70, 77}, /* temperature threshold (going to down) */ + {0x6C, 0xC7, 0xFF}, /* fan duty */ + {8000, 14000, 16000}, /* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ }, /* Sesto */ { - {71, 81, 105}, /* temperature threshold (going to up) */ - {64, 81, 88}, /* temperature threshold (going to down) */ - {0x73, 0xCC, 0xFF} /* fan rpm : 9000, 14000, 16000 */ + {71, 81, 105}, /* temperature threshold (going to up) */ + {64, 81, 88}, /* temperature threshold (going to down) */ + {0x73, 0xCC, 0xFF}, /* fan duty */ + {9000, 14000, 16000}, /* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ }, /* NC2X */ { - {58, 63, 80}, /* temperature threshold (going to up) */ - {54, 60, 63}, /* temperature threshold (going to down) */ - {0x6F, 0xB7, 0xFF} /* fan rpm : 8000, 13000, 16000 */ + {58, 63, 80}, /* temperature threshold (going to up) */ + {54, 60, 63}, /* temperature threshold (going to down) */ + {0x6F, 0xB7, 0xFF}, /* fan duty */ + {8000, 13000, 16000}, /* fan rpm */ + { + {970, 1250,1275}, /* vsen1 */ + {0}, /* vsen2 */ + {0}, /* vsen3 */ + {970, 1000,1030}, /* vsen4 */ + {1710,1800,1890}, /* vsen5 */ + {0}, /* rsvd */ + {1187,1250,1312}, /* vsen7 */ + }, + }, + /* Asterion */ + { + {70, 75, 80}, /* temperature threshold (going to up) */ + {60, 65, 70}, /* temperature threshold (going to down) */ + {0x8B, 0xD1, 0xFF}, /* fan duty */ + {12000, 18000, 22000},/* fan rpm */ + {{0}}, /* (fixme) HW_monitoring_ONL.pdf */ } }; +static const ControlTable_t *get_platform_control_table(void) +{ + const ControlTable_t *cTable; + + switch(platformModelId) + { + default: + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + if (FanDir != 0) + cTable = &(ControlTable[0]); + else + cTable = &(ControlTable_B2F[0]); + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + if (FanDir != 0) + cTable = &(ControlTable[1]); + else + cTable = &(ControlTable_B2F[1]); + break; + + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + if (FanDir != 0) + cTable = &(ControlTable[2]); + else + cTable = &(ControlTable_B2F[2]); + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + if (FanDir2 != 0) + cTable = &(ControlTable[3]); + else + cTable = &(ControlTable_B2F[3]); + break; + } + + return cTable; +} + #if 0 static int i2c_device_byte_write(const struct i2c_client *client, unsigned char command, unsigned char value) { @@ -508,6 +621,39 @@ static int i2c_device_byte_write(const struct i2c_client *client, unsigned char } #endif +#define BIT_INDEX(i) (1ULL << (i)) +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +enum port_sysfs_attributes { + PRESENT, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + EEPROM_A0_PAGE, + EEPROM_A2_PAGE, + SFP_COPPER, + LAST_ATTRIBUTE +}; + +static struct mutex portStatusLock; + static int i2c_device_word_write(const struct i2c_client *client, unsigned char command, unsigned short value) { unsigned int retry = 10; @@ -531,21 +677,8 @@ static int i2c_device_word_write(const struct i2c_client *client, unsigned char return ret; } -int qsfpDataRead(struct i2c_client *client, char *buf) +int eepromDataBlockRead(struct i2c_client *client, char *buf) { -#if 0 - unsigned int index; - int value; - - for (index=0; index> 8; + buf[index*2] = value & 0x00ff; + } + return 0; } int eepromDataRead(struct i2c_client *client, char *buf) @@ -584,7 +772,7 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) int MNTRTD, MNTTD; int i, fanErr; unsigned int cTemp, fanDuty, maxTemp, LastTemp = 0; - fanControlTable_t *fanTable; + const ControlTable_t *cTable; unsigned int fanCtrlDelay = 5; unsigned int fanSpeed; unsigned short port_status; @@ -601,6 +789,13 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) fanErr = 0; for (i=0; i= W83795ADG_NUM8) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + { + FanErr[i] = 0; + continue; + } + fanSpeed = 0; /* Choose W83795ADG bank 0 */ i2c_smbus_write_byte_data(client, W83795ADG_REG_BANK, 0x00); @@ -625,9 +820,9 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) if (data->hwRev == 0x00) /* Proto */ { if (fanErr == 1) - i2c_smbus_write_byte_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x80); + i2c_smbus_write_byte_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x80); else - i2c_smbus_write_byte_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x00); + i2c_smbus_write_byte_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x00); } else if (data->hwRev == 0x02) /* Beta */ { @@ -648,6 +843,10 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) /* Get Remote Temp */ for (i=0; i= W83795ADG_NUM2) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + break; + MNTRTD = (int) i2c_smbus_read_byte_data(client, (W83795ADG_REG_TR1+i)); MNTTD = (int) i2c_smbus_read_byte_data(client, W83795ADG_REG_VR_LSB); /* temperature is negative */ @@ -672,61 +871,37 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) maxTemp = data->macTemp; for (i=0; i= W83795ADG_NUM2) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + break; + if (data->remoteTempInt[i] > maxTemp) maxTemp = data->remoteTempInt[i]; } /* FAN Control */ - switch(platformModelId) - { - default: - case HURACAN_WITH_BMC: - case HURACAN_WITHOUT_BMC: - case HURACAN_A_WITH_BMC: - case HURACAN_A_WITHOUT_BMC: - if (FanDir != 0) - fanTable = &(fanControlTable[0]); - else - fanTable = &(fanControlTable_B2F[0]); - break; - - case SESTO_WITH_BMC: - case SESTO_WITHOUT_BMC: - if (FanDir != 0) - fanTable = &(fanControlTable[1]); - else - fanTable = &(fanControlTable_B2F[1]); - break; - - case NCIIX_WITH_BMC: - case NCIIX_WITHOUT_BMC: - if (FanDir != 0) - fanTable = &(fanControlTable[2]); - else - fanTable = &(fanControlTable_B2F[2]); - break; - } + cTable = get_platform_control_table(); if (fanErr) { - fanDuty = fanTable->fanDutySet[2]; + fanDuty = cTable->fanDutySet[2]; + LastTemp = 0; } else { fanDuty = 0; if (maxTemp > LastTemp) /* temp is going to up */ { - if (maxTemp < fanTable->tempLow2HighThreshold[0]) + if (maxTemp < cTable->tempLow2HighThreshold[0]) { - fanDuty = fanTable->fanDutySet[0]; + fanDuty = cTable->fanDutySet[0]; } - else if (maxTemp < fanTable->tempLow2HighThreshold[1]) + else if (maxTemp < cTable->tempLow2HighThreshold[1]) { - fanDuty = fanTable->fanDutySet[1]; + fanDuty = cTable->fanDutySet[1]; } - else if (maxTemp < fanTable->tempLow2HighThreshold[2]) + else if (maxTemp < cTable->tempLow2HighThreshold[2]) { - fanDuty = fanTable->fanDutySet[2]; + fanDuty = cTable->fanDutySet[2]; } else /* shutdown system */ { @@ -735,21 +910,21 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) } else if (maxTemp < LastTemp)/* temp is going to down */ { - if (maxTemp <= fanTable->tempHigh2LowThreshold[0]) + if (maxTemp <= cTable->tempHigh2LowThreshold[0]) { - fanDuty = fanTable->fanDutySet[0]; + fanDuty = cTable->fanDutySet[0]; } - else if (maxTemp <= fanTable->tempHigh2LowThreshold[1]) + else if (maxTemp <= cTable->tempHigh2LowThreshold[1]) { - fanDuty = fanTable->fanDutySet[1]; + fanDuty = cTable->fanDutySet[1]; } else { - fanDuty = fanTable->fanDutySet[2]; + fanDuty = cTable->fanDutySet[2]; } } + LastTemp = maxTemp; } - LastTemp = maxTemp; if ((fanDuty!=0)&&(data->fanDuty!=fanDuty)) { @@ -792,9 +967,11 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) { port_status = i2c_smbus_read_word_data(&(pca9535_client_bus0[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); port = ((j*2)+(i*8)); + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 0)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 1)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 2)==0); port++; + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 6)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 7)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 8)==0); } @@ -919,9 +1096,10 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) struct i2c_client *client = p; struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); int i, ret; - unsigned short value, fanErr; + unsigned short value, value2, fanErr, fanErr2; unsigned int step = 0; unsigned char qsfpPortData[QSFP_DATA_SIZE]; + unsigned char SfpCopperPortData[SFP_COPPER_DATA_SIZE]; unsigned short port_status; int j, port; @@ -944,7 +1122,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) /* QSFP Port */ for (i=0; i<2; i++) - data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); step = 1; break; @@ -964,7 +1142,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[0]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -976,8 +1159,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } } @@ -986,8 +1169,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<8; i++) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } @@ -1009,7 +1192,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<<(i-8))); if (ret>=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1021,8 +1209,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } } @@ -1031,8 +1219,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=8; i<16; i++) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } @@ -1054,7 +1242,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[2]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+16] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+16], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+16] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1066,8 +1259,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } } @@ -1076,8 +1269,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<8; i++) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } @@ -1099,7 +1292,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[3]), (1<<(i-8))); if (ret>=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+16] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+16], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+16] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1111,8 +1309,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } } @@ -1121,8 +1319,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=8; i<16; i++) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } @@ -1140,7 +1338,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); } /* FAN Status */ - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); data->fanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1245,7 +1443,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) /* SFP Port */ for (i=0; i<4; i++) - data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); /* Turn on PCA9548#1 channel 1 on I2C-bus1 */ ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortRxLosStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + for (i=0; i<3; i++) + data->sfpPortRxLosStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + + /* Turn on PCA9548#1 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortTxFaultStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); step = 1; break; @@ -1276,16 +1483,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[0], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[0], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1293,6 +1503,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1303,6 +1514,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1327,16 +1539,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[0], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[0], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1344,6 +1559,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1354,6 +1570,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1378,16 +1595,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[1], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[1], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+16][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1395,6 +1615,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1405,6 +1626,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1429,16 +1651,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[1], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[1], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+16][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1446,6 +1671,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1456,6 +1682,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1480,16 +1707,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[2], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[2], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+32][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1497,6 +1727,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1507,6 +1738,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1531,16 +1763,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[2], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[2], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+32][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1548,6 +1783,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1558,6 +1794,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1580,7 +1817,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[0]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+48] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+48], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+48] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+48][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1592,8 +1834,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+48][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+48][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[3], i); + data->qsfpPortTxDisableDataUpdate[i+48] = 1; } } } @@ -1602,8 +1844,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<6; i++) { memset(&(data->qsfpPortDataA0[i+48][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+48][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[3], i); + data->qsfpPortTxDisableDataUpdate[i+48] = 1; } } @@ -1625,7 +1867,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); /* FAN Status */ - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); data->fanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1722,11 +1964,13 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (j=0; j<4; j++) { - port_status = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + port_status = i2c_smbus_read_word_data(&(pca9535pwr_client[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); port = ((j*2)+40); + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 0)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 1)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 2)==0); port++; + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 6)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 7)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 8)==0); } @@ -1741,7 +1985,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) break; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); i2c_smbus_write_byte_data(client, 0, 0x00); step = 2; @@ -1795,11 +2039,11 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) if (ret < 0) break; - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); SFPPortAbsStatus[48] = (PCA9553_TEST_BIT(value, 9)==0); SFPPortAbsStatus[49] = (PCA9553_TEST_BIT(value, 4)==0); SFPPortAbsStatus[51] = (PCA9553_TEST_BIT(value, 14)==0); - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); SFPPortAbsStatus[50] = (PCA9553_TEST_BIT(value, 4)==0); SFPPortAbsStatus[52] = (PCA9553_TEST_BIT(value, 14)==0); SFPPortAbsStatus[53] = (PCA9553_TEST_BIT(value, 9)==0); @@ -1815,7 +2059,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1864,7 +2108,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, sfpPortData_78F[i].portMaskBitForPCA9548_2TO5); if ((SFPPortDataValid[i] == 0)||(i>=48)) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if ((i>=48)&&(data->qsfpPortTxDisableDataUpdate[i] == 1)) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1873,9 +2122,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) } if (i<48) { - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, 0x00); i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, 0x00); @@ -1884,6 +2136,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); + data->qsfpPortTxDisableDataUpdate[i] = 1; SFPPortDataValid[i] = 0; } } @@ -1898,6 +2152,345 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) case ASTERION_WITH_BMC: case ASTERION_WITHOUT_BMC: + switch (step) + { + case 0: + /* Turn on PCA9548#0 channel 0 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + if (ret < 0) + break; + + /* SFP Port 0~23, SFP Port - RXLOS */ + for (i = 0; i < 10; i++) + data->sfpPortAbsRxLosStatus[i] = i2c_smbus_read_byte_data(&(cpld_client_bus1), (0x20 + i)); + + data->sfpPortAbsRxLosStatus[10] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x30); + data->sfpPortAbsRxLosStatus[11] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x31); + + /* Turn on PCA9548#0 channel 1 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + if (ret < 0) + break; + + /* SFP Port 24~47, SFP Port - RXLOS */ + for (i = 0; i < 10; i++) + data->sfpPortAbsRxLosStatus[i + 12] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x20 + i); + + data->sfpPortAbsRxLosStatus[22] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x30); + data->sfpPortAbsRxLosStatus[23] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x31); + + /* Turn on PCA9548#0 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH02)); + if (ret < 0) + break; + + /* QSFP Port 48~63 */ + for (i = 0; i < 16; i++) + data->qsfpPortAbsStatusAst[i] = i2c_smbus_read_byte_data(&(cpld_client_bus1), (0x20 + i)); + + step = 1; + break; + + case 1: + /* Turn on PCA9548#0 channel 0 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + if (ret < 0) + break; + + for (i = 0; i < 12; i++) /* SFP 0,2,4 ... 22 */ + { + if ((data->sfpPortAbsRxLosStatus[i] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + (i * 2))); + + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[i * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[i * 2] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + memcpy(&(data->qsfpPortDataA2[i * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i * 2][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[i * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[i * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i * 2][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[i * 2] = 0; + } + } + + for (i = 0; i < 12; i++) /* SFP 1,3,5 ... 23 */ + { + if ((data->sfpPortAbsRxLosStatus[i] & 0x20) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x02 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[1 + (i * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[1 + (i * 2)] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[1 + (i * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[1 + (i * 2)][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[1 + (i * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[1 + (i * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[1 + (i * 2)][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[1 + (i * 2)] = 0; + } + } + + step = 2; + break; + + case 2: + /* Turn on PCA9548#0 channel 1 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + if (ret < 0) + break; + + for (i = 0; i < 12; i++) /* SFP 24,26,28 ... 46 */ + { + if ((data->sfpPortAbsRxLosStatus[i + 12] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[(i +12) * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[(i + 12) * 2] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[(i + 12) * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[(i + 12) * 2][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[(i + 12) * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[(i + 12) * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[(i + 12) * 2][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[(i + 12) * 2] = 0; + } + } + + for (i = 0; i < 12; i++) /* SFP 25,27,29 ... 47 */ + { + if ((data->sfpPortAbsRxLosStatus[i + 12] & 0x20) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x02 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[1 + ((i + 12) * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[1 + ((i + 12) * 2)] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[1 + ((i + 12) * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[1 + ((i + 12) * 2)][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[1 + ((i + 12) * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[1 + ((i + 12) * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[1 + ((i + 12) * 2)][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[1 + ((i + 12) * 2)] = 0; + } + } + + step = 3; + break; + + case 3: + /* Turn on PCA9548#0 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH02)); + if (ret < 0) + break; + + for (i = 0; i < 16; i++) /* QSFP 48~63 */ + { + if ((data->qsfpPortAbsStatusAst[i] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + i)); + if (ret >= 0) + { + if (data->qsfpPortTxDisableDataUpdate[48 + i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[48 + i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[48 + i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[48 + i][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[48 + i] = 1; + } + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[48 + i][0]), 0, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[48 + i] = 0; + data->qsfpPortTxDisableDataUpdate[48 + i] = 1; + } + } + + step = 4; + break; + + case 4: + /* Turn on PCA9548#0 channel 3 on I2C-bus1 : FAN Status */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH03)); + if (ret < 0) + break; + + value = 0xcccc; + fanErr = 0; + for (i = 0; i < W83795ADG_NUM8; i++) + { + if (FanErr[i] == 1) + fanErr |= (0x1 << i); + } + + if (fanErr & 0x03) + value |= 0x0001; + else + value |= 0x0002; + + if (fanErr & 0x0c) + value |= 0x0010; + else + value |= 0x0020; + + if (fanErr & 0x30) + value |= 0x0100; + else + value |= 0x0200; + + if (fanErr & 0xc0) + value |= 0x1000; + else + value |= 0x2000; + + ret = i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); + if (ret < 0) + break; + + /* FAN Status */ + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->fanAbs[0] = (value & 0x4444); + data->fanDir[0] = (value & 0x8888); + FanDir = data->fanDir[0]; + + fanErr2 = 0; + for (i = W83795ADG_NUM8; i < W83795ADG_FAN_COUNT; i++) + { + if (FanErr[i] == 1) + fanErr2 |= (0x1 << (i - 8)); + } + + if (fanErr2 & 0x03) + value2 = 0x0010; + else + value2 = 0x0020; + + ret = i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value2); + if (ret < 0) + break; + + /* FAN Status */ + value2 = i2c_smbus_read_word_data(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + + data->fanAbs[1] = (value2 & 0x0040); + data->fanDir[1] = (value2 & 0x0080); + FanDir2 = data->fanDir[1]; + + /* Turn on PCA9548#0 channel 4 on I2C-bus1 : System LED */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH04)); + if (ret < 0) + break; + + data->frontLedStatus |= 0x00ff; + if (fanErr == 0 && fanErr2 == 0) + data->frontLedStatus &= (~0x0010); /* FAN_LED_G# */ + else + data->frontLedStatus &= (~0x0020); /* FAN_LED_Y# */ + + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + if (platformPsuPG & 0x04) /* PSU1_PG_LDC Power Goodasserted */ + data->frontLedStatus &= (~0x0001); /* PSU1_LED_G# */ + else + data->frontLedStatus &= (~0x0002); /* PSU1_LED_Y# */ + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + if (platformPsuPG & 0x08) /* PSU2_PG_LDC Power Goodasserted */ + data->frontLedStatus &= (~0x0004); /* PSU2_LED_G# */ + else + data->frontLedStatus &= (~0x0008); /* PSU2_LED_Y# */ + } + + switch (data->systemLedStatus) + { + default: + case 0: /* Booting */ + break; + + case 1: /* Critical*/ + data->frontLedStatus &= (~0x0080); /* SYS_LED_Y# */ + break; + + case 2: /* Normal */ + data->frontLedStatus &= (~0x0040); /* SYS_LED_G# */ + break; + } + + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + + step = 0; + break; + + default: + step = 0; + break; + } + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x33, 0x00); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x33, 0xff); break; default: @@ -1960,10 +2553,27 @@ static ssize_t show_psu_pg_sen(struct device *dev, struct device_attribute *deva value = data->psuPG; mutex_unlock(&data->lock); - if (attr->index == 0) - value &= 0x08; - else - value &= 0x10; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (attr->index == 0) + value &= 0x04; + else + value &= 0x08; + } + break; + + default: + { + if (attr->index == 0) + value &= 0x08; + else + value &= 0x10; + } + break; + } return sprintf(buf, "%d\n", value?1:0); } @@ -2183,8 +2793,6 @@ static ssize_t set_rov(struct device *dev, struct device_attribute *devattr, con { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -2219,6 +2827,8 @@ static ssize_t set_rov(struct device *dev, struct device_attribute *devattr, con case SESTO_WITH_BMC: case SESTO_WITHOUT_BMC: + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: { /* - 4'b0000 = 1.2000V -> 0x47 @@ -2322,6 +2932,46 @@ static ssize_t show_voltage_sen(struct device *dev, struct device_attribute *dev return sprintf(buf, "%d.%03d\n", (voltage/VOL_MONITOR_UNIT), (voltage%VOL_MONITOR_UNIT)); } +/* lm-sensors */ +static ssize_t show_temp_lm_sensors(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 i2c_bus0_hardware_monitor_data *data = i2c_get_clientdata(client); + + if (data->remoteTempIsPositive[attr->index]==1) + return sprintf(buf, "%u\n", data->remoteTempInt[attr->index] * 1000 + data->remoteTempDecimal[attr->index]); + else + return sprintf(buf, "-%u\n", data->remoteTempInt[attr->index] * 1000 + data->remoteTempDecimal[attr->index]); +} + +static ssize_t show_mac_temp_lm_sensors(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus0_hardware_monitor_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%u\n", data->macTemp * 1000); +} + +static ssize_t show_in_lm_sensors(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 i2c_bus0_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned int MNTVSEN, MNTV; + unsigned int voltage; + + mutex_lock(&data->lock); + MNTVSEN = data->vSen[attr->index]; + MNTV = data->vSenLsb[attr->index]; + mutex_unlock(&data->lock); + + voltage = ((MNTVSEN << 2) + ((MNTV & 0xC0) >> 6)); + voltage *= ((2*VOL_MONITOR_UNIT)/VOL_MONITOR_UNIT); + + return sprintf(buf, "%u\n", (voltage/VOL_MONITOR_UNIT) * 1000 + voltage%VOL_MONITOR_UNIT); +} + static DEVICE_ATTR(mac_temp, S_IWUSR | S_IRUGO, show_mac_temp, set_mac_temp); static DEVICE_ATTR(chip_info, S_IRUGO, show_chip_info, NULL); static DEVICE_ATTR(board_build_rev, S_IRUGO, show_board_build_revision, NULL); @@ -2363,6 +3013,8 @@ static SENSOR_DEVICE_ATTR(fan10_duty, S_IRUGO, show_fan_duty, NULL, 9); static SENSOR_DEVICE_ATTR(remote_temp1, S_IRUGO, show_remote_temp, NULL, 0); static SENSOR_DEVICE_ATTR(remote_temp2, S_IRUGO, show_remote_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(remote_temp3, S_IRUGO, show_remote_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(remote_temp4, S_IRUGO, show_remote_temp, NULL, 3); static SENSOR_DEVICE_ATTR(vsen1, S_IRUGO, show_voltage_sen, NULL, 0); static SENSOR_DEVICE_ATTR(vsen2, S_IRUGO, show_voltage_sen, NULL, 1); @@ -2371,6 +3023,134 @@ static SENSOR_DEVICE_ATTR(vsen4, S_IRUGO, show_voltage_sen, NULL, 3); static SENSOR_DEVICE_ATTR(vsen5, S_IRUGO, show_voltage_sen, NULL, 4); static SENSOR_DEVICE_ATTR(vsen7, S_IRUGO, show_voltage_sen, NULL, 6); +/* lm-sensors compatible feature/subfeature names */ +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_rpm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_rpm, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_rpm, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_rpm, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_rpm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_rpm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_rpm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_rpm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_fan_rpm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_fan_rpm, NULL, 9); + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_lm_sensors, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_lm_sensors, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_lm_sensors, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_lm_sensors, NULL, 3); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_mac_temp_lm_sensors, NULL, 4); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_lm_sensors, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_lm_sensors, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_lm_sensors, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_lm_sensors, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in_lm_sensors, NULL, 4); +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in_lm_sensors, NULL, 6); + +/* fan min/max */ + +static ssize_t show_fan_minmax_lm_sensors(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + const ControlTable_t *cTable = get_platform_control_table(); + + return sprintf(buf, "%u\n", attr->index < 100 ? cTable->fanSpeed[0] : cTable->fanSpeed[2]); +} + +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_min, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 9); + +static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 100); +static SENSOR_DEVICE_ATTR(fan2_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 101); +static SENSOR_DEVICE_ATTR(fan3_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 102); +static SENSOR_DEVICE_ATTR(fan4_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 103); +static SENSOR_DEVICE_ATTR(fan5_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 104); +static SENSOR_DEVICE_ATTR(fan6_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 105); +static SENSOR_DEVICE_ATTR(fan7_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 106); +static SENSOR_DEVICE_ATTR(fan8_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 107); +static SENSOR_DEVICE_ATTR(fan9_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 108); +static SENSOR_DEVICE_ATTR(fan10_max, S_IRUGO, show_fan_minmax_lm_sensors, NULL, 109); + +/* temp min/max */ + +static ssize_t show_temp_minmax_lm_sensors(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + const ControlTable_t *cTable = get_platform_control_table(); + unsigned int temp; + + if (attr->index < 100) + temp = cTable->tempLow2HighThreshold[0]; + else + temp = cTable->tempLow2HighThreshold[2]; + + return sprintf(buf, "%u\n", temp * 1000); +} + +static ssize_t show_mac_temp_minmax_lm_sensors(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + unsigned int temp; + + if (attr->index < 100) + temp = 0; + else + temp = 120; + + return sprintf(buf, "%u\n", temp * 1000); +} + +static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 3); +static SENSOR_DEVICE_ATTR(temp10_min, S_IRUGO, show_mac_temp_minmax_lm_sensors, NULL, 4); + +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 100); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 101); +static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 102); +static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_minmax_lm_sensors, NULL, 103); +static SENSOR_DEVICE_ATTR(temp10_max, S_IRUGO, show_mac_temp_minmax_lm_sensors, NULL, 104); + +/* voltage min/max */ + +static ssize_t show_in_minmax_lm_sensors(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + const ControlTable_t *cTable = get_platform_control_table(); + unsigned int in; + + if (attr->index < 100) + in = cTable->inSet[attr->index][0]; + else + in = cTable->inSet[attr->index - 100][2]; + + return sprintf(buf, "%u\n", in); +} + +static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 4); +static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO, show_in_minmax_lm_sensors, NULL, 6); + +static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 100); +static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 101); +static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 102); +static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 103); +static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 104); +static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO, show_in_minmax_lm_sensors, NULL, 106); + static struct attribute *i2c_bus0_hardware_monitor_attr[] = { &dev_attr_mac_temp.attr, &dev_attr_chip_info.attr, @@ -2415,6 +3195,63 @@ static struct attribute *i2c_bus0_hardware_monitor_attr[] = { &sensor_dev_attr_vsen3.dev_attr.attr, &sensor_dev_attr_vsen4.dev_attr.attr, + /* lm-sensors */ + &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_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + + &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, + + /* min */ + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan5_min.dev_attr.attr, + &sensor_dev_attr_fan6_min.dev_attr.attr, + &sensor_dev_attr_fan7_min.dev_attr.attr, + &sensor_dev_attr_fan8_min.dev_attr.attr, + + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp10_min.dev_attr.attr, + + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + + /* max */ + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan2_max.dev_attr.attr, + &sensor_dev_attr_fan3_max.dev_attr.attr, + &sensor_dev_attr_fan4_max.dev_attr.attr, + &sensor_dev_attr_fan5_max.dev_attr.attr, + &sensor_dev_attr_fan6_max.dev_attr.attr, + &sensor_dev_attr_fan7_max.dev_attr.attr, + &sensor_dev_attr_fan8_max.dev_attr.attr, + + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp10_max.dev_attr.attr, + + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + NULL }; @@ -2462,6 +3299,63 @@ static struct attribute *i2c_bus0_hardware_monitor_attr_nc2x[] = { &sensor_dev_attr_vsen5.dev_attr.attr, &sensor_dev_attr_vsen7.dev_attr.attr, + /* lm-sensors */ + &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_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + + /* min */ + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan5_min.dev_attr.attr, + &sensor_dev_attr_fan6_min.dev_attr.attr, + &sensor_dev_attr_fan7_min.dev_attr.attr, + &sensor_dev_attr_fan8_min.dev_attr.attr, + + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp10_min.dev_attr.attr, + + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in7_min.dev_attr.attr, + + /* max */ + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan2_max.dev_attr.attr, + &sensor_dev_attr_fan3_max.dev_attr.attr, + &sensor_dev_attr_fan4_max.dev_attr.attr, + &sensor_dev_attr_fan5_max.dev_attr.attr, + &sensor_dev_attr_fan6_max.dev_attr.attr, + &sensor_dev_attr_fan7_max.dev_attr.attr, + &sensor_dev_attr_fan8_max.dev_attr.attr, + + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp10_max.dev_attr.attr, + + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in7_max.dev_attr.attr, + NULL }; @@ -2507,12 +3401,83 @@ static struct attribute *i2c_bus0_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_remote_temp1.dev_attr.attr, &sensor_dev_attr_remote_temp2.dev_attr.attr, + &sensor_dev_attr_remote_temp3.dev_attr.attr, + &sensor_dev_attr_remote_temp4.dev_attr.attr, &sensor_dev_attr_vsen1.dev_attr.attr, &sensor_dev_attr_vsen2.dev_attr.attr, &sensor_dev_attr_vsen3.dev_attr.attr, &sensor_dev_attr_vsen4.dev_attr.attr, + /* lm-sensors */ + &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_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_temp10_input.dev_attr.attr, + + &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, + + /* min */ + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan5_min.dev_attr.attr, + &sensor_dev_attr_fan6_min.dev_attr.attr, + &sensor_dev_attr_fan7_min.dev_attr.attr, + &sensor_dev_attr_fan8_min.dev_attr.attr, + &sensor_dev_attr_fan9_min.dev_attr.attr, + &sensor_dev_attr_fan10_min.dev_attr.attr, + + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp10_min.dev_attr.attr, + + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + + /* max */ + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan2_max.dev_attr.attr, + &sensor_dev_attr_fan3_max.dev_attr.attr, + &sensor_dev_attr_fan4_max.dev_attr.attr, + &sensor_dev_attr_fan5_max.dev_attr.attr, + &sensor_dev_attr_fan6_max.dev_attr.attr, + &sensor_dev_attr_fan7_max.dev_attr.attr, + &sensor_dev_attr_fan8_max.dev_attr.attr, + &sensor_dev_attr_fan9_max.dev_attr.attr, + &sensor_dev_attr_fan10_max.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_temp10_max.dev_attr.attr, + + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + NULL }; @@ -2520,7 +3485,8 @@ static struct attribute *i2c_bus0_hardware_monitor_attr_asterion[] = { static ssize_t show_port_abs(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client_bus1[0])); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + struct i2c_bus1_hardware_monitor_data *dataAst = i2c_get_clientdata(&(cpld_client_bus1)); int rc = 0; switch(platformModelId) @@ -2530,6 +3496,34 @@ static ssize_t show_port_abs(struct device *dev, struct device_attribute *devatt rc = ((SFPPortAbsStatus[attr->index]==1)&&(SFPPortDataValid[attr->index]==1)); break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortAbsAst = 0, index = 0, bit = 0; + unsigned char sfpPortDataValidAst = 0; + + if (attr->index < 48) + { + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 5 : 1); + mutex_lock(&dataAst->lock); + qsfpPortAbsAst = dataAst->sfpPortAbsRxLosStatus[index]; + sfpPortDataValidAst = dataAst->sfpPortDataValidAst[attr->index]; + mutex_unlock(&dataAst->lock); + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, bit) ? 0 : 1)&&sfpPortDataValidAst); + } + else + { + index = (attr->index % 48); + mutex_lock(&dataAst->lock); + qsfpPortAbsAst = dataAst->qsfpPortAbsStatusAst[index]; + sfpPortDataValidAst = dataAst->sfpPortDataValidAst[attr->index]; + mutex_unlock(&dataAst->lock); + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, 1) ? 0 : 1)&&sfpPortDataValidAst); + } + } + break; + default: { unsigned short qsfpPortAbs=0, index=0, bit=0; @@ -2552,7 +3546,7 @@ static ssize_t show_port_abs(struct device *dev, struct device_attribute *devatt static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client_bus1[0])); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); int rc = 0; switch(platformModelId) @@ -2576,6 +3570,20 @@ static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *deva } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortRxLos = 0, index = 0, bit = 0; + + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 4 : 0); + mutex_lock(&data->lock); + qsfpPortRxLos = data->sfpPortAbsRxLosStatus[index]; + mutex_unlock(&data->lock); + rc = (PCA9553_TEST_BIT(qsfpPortRxLos, bit) ? 1 : 0); + } + break; + default: break; } @@ -2586,8 +3594,7 @@ static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *deva static ssize_t show_port_data_a0(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 i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); unsigned char qsfpPortData[QSFP_DATA_SIZE]; ssize_t count = 0; @@ -2605,8 +3612,7 @@ static ssize_t show_port_data_a0(struct device *dev, struct device_attribute *de static ssize_t show_port_data_a2(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 i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA2_client); unsigned char qsfpPortData[QSFP_DATA_SIZE]; ssize_t count = 0; @@ -2621,6 +3627,24 @@ static ssize_t show_port_data_a2(struct device *dev, struct device_attribute *de return count; } +static ssize_t show_port_sfp_copper(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&SfpCopperData_client); + unsigned char SfpCopperPortData[SFP_COPPER_DATA_SIZE]; + ssize_t count = 0; + + memset(SfpCopperPortData, 0, SFP_COPPER_DATA_SIZE); + mutex_lock(&data->lock); + memcpy(SfpCopperPortData, &(data->SfpCopperPortData[attr->index][0]), SFP_COPPER_DATA_SIZE); + mutex_unlock(&data->lock); + + count = SFP_COPPER_DATA_SIZE; + memcpy(buf, (char *)SfpCopperPortData, SFP_COPPER_DATA_SIZE); + + return count; +} + static ssize_t show_fan_abs(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -2721,7 +3745,7 @@ static ssize_t show_eeprom(struct device *dev, struct device_attribute *devattr, case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - if ((platformBuildRev == 0x01)&&(platformHwRev == 0x03)) /* PVT */ + if (platformHwRev == 0x03) /* PVT */ { struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); @@ -2729,8 +3753,8 @@ static ssize_t show_eeprom(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->lock); /* Turn on PCA9548#1 channel 2 on I2C-bus1 */ i2c_smbus_write_byte(client, 0x04); - i2c_smbus_write_byte_data(&eeprom_client_2, 0x00, 0x00); - ret = eepromDataRead(&eeprom_client_2, &(eepromData[0])); + i2c_smbus_write_byte_data(&eeprom_client, 0x00, 0x00); + ret = eepromDataRead(&eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -2815,7 +3839,7 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva else /* Turn on PCA9548 channel 6 on I2C-bus1 */ i2c_smbus_write_byte(client, 0x40); - ret = qsfpDataRead(&psu_eeprom_client, &(eepromData[0])); + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -2835,7 +3859,7 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva else /* Turn on PCA9548#1 channel 6 on I2C-bus1 */ i2c_smbus_write_byte(&(pca9548_client[1]), 0x40); - ret = qsfpDataRead(&psu_eeprom_client, &(eepromData[0])); + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(&(pca9548_client[1]), 0x00); mutex_unlock(&data->lock); } @@ -2844,18 +3868,35 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + /* + Because the write ability of EEPROM with 0xAx address on I2C bus 0 (I801 bus) is blocked by BIOS, + it does not support I2C block read, it supports byte read only. + The PSUs will be moved to I2C bus 1 (iSMT bus) in PVT rev2. + */ + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - ret = qsfpDataRead(&psu_eeprom_client_bus0, &(eepromData[0])); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + ret = eepromDataByteRead(&psu_eeprom_client_bus0, &(eepromData[0])); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -2877,12 +3918,14 @@ static ssize_t show_psu_vout(struct device *dev, struct device_attribute *devatt struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); - unsigned short index = 0; + unsigned int index = 0; unsigned int valueV = 0; unsigned char valueN = 0; ssize_t count = 0; unsigned int temp = 0; unsigned int psu_present = 0; + unsigned char valueE = 0; + unsigned short valueY = 0; index = (attr->index&0x1); if (index&0x01) /* PSU 2 */ @@ -2944,36 +3987,86 @@ static ssize_t show_psu_vout(struct device *dev, struct device_attribute *devatt case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + valueN = i2c_smbus_read_byte_data(&psu_mcu_client, 0x20); + valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client, 0x8B); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - valueN = i2c_smbus_read_byte_data(&psu_mcu_client_bus0, 0x20); - valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8B); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + valueN = i2c_smbus_read_byte_data(&psu_mcu_client_bus0, 0x20); + valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8B); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; default: break; } - if (valueN & 0x10) + + if (valueN == 0xff) { - valueN = 0xF0 + (valueN & 0x0F); - valueN = (~valueN) +1; - temp = (unsigned int)(1<> 11); + valueE = valueV + 1; + temp = (unsigned int)(1 << valueE); + if (temp) + { + if (attr->index >= 100) + count = sprintf(buf, "%d\n", (valueY>>valueE)*1000 + ((valueY%temp)*1000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY>>valueE, ((valueY%temp)*10000)/temp); + } + } + else + { + valueN = (((valueV) >> 11) & 0x0F); + temp = (valueY*(1<index >= 100) + temp *= 1000; + count = sprintf(buf, "%d\n", temp); + } } else { - count = sprintf(buf, "%d\n", (valueV*(1<index >= 100) + count = sprintf(buf, "%d\n", valueV/temp*1000 + ((valueV%temp)*1000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueV/temp, ((valueV%temp)*10000)/temp); + } + } + else + { + temp = (valueV*(1<index >= 100) + temp *= 1000; + count = sprintf(buf, "%d\n", temp); + } } } else @@ -2989,7 +4082,7 @@ static ssize_t show_psu_iout(struct device *dev, struct device_attribute *devatt struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int valueY = 0; unsigned char valueN = 0; ssize_t count = 0; @@ -3054,18 +4147,30 @@ static ssize_t show_psu_iout(struct device *dev, struct device_attribute *devatt case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8C); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8C); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8C); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3079,12 +4184,20 @@ static ssize_t show_psu_iout(struct device *dev, struct device_attribute *devatt valueN = (~valueN) +1; temp = (unsigned int)(1<index >= 100) + count = sprintf(buf, "%d\n", valueY/temp*1000 + ((valueY%temp)*1000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY/temp, ((valueY%temp)*10000)/temp); + } } else { valueN = (((value) >> 11) & 0x0F); - count = sprintf(buf, "%d\n", (valueY*(1<index >= 100) + temp *= 1000; + count = sprintf(buf, "%d\n", temp); } } else @@ -3100,7 +4213,7 @@ static ssize_t show_psu_temp_1(struct device *dev, struct device_attribute *deva struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int valueY = 0; unsigned char valueN = 0; ssize_t count = 0; @@ -3165,18 +4278,30 @@ static ssize_t show_psu_temp_1(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8D); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8D); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8D); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3190,12 +4315,20 @@ static ssize_t show_psu_temp_1(struct device *dev, struct device_attribute *deva valueN = (~valueN) +1; temp = (unsigned int)(1<index >= 100) + count = sprintf(buf, "%d\n", valueY/temp*1000 + ((valueY%temp)*1000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY/temp, ((valueY%temp)*10000)/temp); + } } else { valueN = (((value) >> 11) & 0x0F); - count = sprintf(buf, "%d\n", (valueY*(1<index >= 100) + temp *= 1000; + count = sprintf(buf, "%d\n", temp); } } else @@ -3211,7 +4344,7 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int valueY = 0; unsigned char valueN = 0; ssize_t count = 0; @@ -3235,8 +4368,6 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -3276,21 +4407,37 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8E); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8E); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8E); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + break; + default: break; } @@ -3301,12 +4448,20 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva valueN = (~valueN) +1; temp = (unsigned int)(1<index >= 100) + count = sprintf(buf, "%d\n", valueY/temp*1000 + ((valueY%temp)*1000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY/temp, ((valueY%temp)*10000)/temp); + } } else { valueN = (((value) >> 11) & 0x0F); - count = sprintf(buf, "%d\n", (valueY*(1<index >= 100) + temp *= 1000; + count = sprintf(buf, "%d\n", temp); } } else @@ -3322,7 +4477,7 @@ static ssize_t show_psu_fan_speed(struct device *dev, struct device_attribute *d struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int temp = 0; unsigned int psu_present = 0; @@ -3384,18 +4539,30 @@ static ssize_t show_psu_fan_speed(struct device *dev, struct device_attribute *d case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x90); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x90); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x90); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3414,7 +4581,7 @@ static ssize_t show_psu_pout(struct device *dev, struct device_attribute *devatt struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int valueY = 0; unsigned char valueN = 0; ssize_t count = 0; @@ -3479,18 +4646,30 @@ static ssize_t show_psu_pout(struct device *dev, struct device_attribute *devatt case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x96); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x96); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x96); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3504,12 +4683,20 @@ static ssize_t show_psu_pout(struct device *dev, struct device_attribute *devatt valueN = (~valueN) +1; temp = (unsigned int)(1<index >= 100) + count = sprintf(buf, "%d\n", valueY/temp*1000000 + ((valueY%temp)*1000000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY/temp, ((valueY%temp)*10000)/temp); + } } else { valueN = (((value) >> 11) & 0x0F); - count = sprintf(buf, "%d\n", (valueY*(1<index >= 100) + temp *= 1000000; + count = sprintf(buf, "%d\n", temp); } } else @@ -3525,7 +4712,7 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); unsigned short value = 0; - unsigned short index = 0; + unsigned int index = 0; unsigned int valueY = 0; unsigned char valueN = 0; ssize_t count = 0; @@ -3549,8 +4736,6 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -3590,21 +4775,37 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x97); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x97); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x97); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + break; + default: break; } @@ -3615,12 +4816,20 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr valueN = (~valueN) +1; temp = (unsigned int)(1<index >= 100) + count = sprintf(buf, "%d\n", valueY/temp*1000000 + ((valueY%temp)*1000000)/temp); + else + count = sprintf(buf, "%d.%04d\n", valueY/temp, ((valueY%temp)*10000)/temp); + } } else { valueN = (((value) >> 11) & 0x0F); - count = sprintf(buf, "%d\n", (valueY*(1<index >= 100) + temp *= 1000000; + count = sprintf(buf, "%d\n", temp); } } else @@ -3715,7 +4924,6 @@ static ssize_t set_psu_power_off(struct device *dev, struct device_attribute *de case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); /* Setting the ON_OFF_CONFIG Command (02h) to type 9 (SW : turn-on/off by operation command). I2C Command: B2 02 19 59 @@ -3729,23 +4937,48 @@ static ssize_t set_psu_power_off(struct device *dev, struct device_attribute *de */ unsigned short cmd_data_2 = 0x2900; - mutex_lock(&data_bus0->lock); - if ((platformPsuABS&0x01)==0x00) /* PSU1 Present */ + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ { - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + mutex_lock(&data->lock); + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + /* Turn on PCA9548#0 channel 4 on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x10); + i2c_smbus_write_word_data(&psu_mcu_client, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client, 0x01, cmd_data_2); + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + /* Turn on PCA9548#0 channel 5 on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x20); + i2c_smbus_write_word_data(&psu_mcu_client, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client, 0x01, cmd_data_2); + } + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); } - if ((platformPsuABS&0x02)==0x00) /* PSU2 Present */ + else { - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + } + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); } - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); } break; @@ -3776,6 +5009,108 @@ static ssize_t set_system_led(struct device *dev, struct device_attribute *devat return count; } +static ssize_t show_fan_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned int temp; + unsigned int frontLedStatus; + + mutex_lock(&data->lock); + frontLedStatus = (unsigned int)data->frontLedStatus; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (!(frontLedStatus & 0x0010)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0020)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + break; + default: + { + if (!(frontLedStatus & 0x0008)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0004)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + break; + } + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", temp); +} + +static ssize_t show_psu_led(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 i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned int temp; + unsigned int frontLedStatus; + + mutex_lock(&data->lock); + frontLedStatus = (unsigned int)data->frontLedStatus; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (attr->index == 0) + { + if (!(frontLedStatus & 0x0001)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0002)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + else + { + if (!(frontLedStatus & 0x0004)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0008)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + } + break; + default: + { + if (attr->index == 0) + { + if (!(frontLedStatus & 0x0002)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0001)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + else + { + if (!(frontLedStatus & 0x0020)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0010)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + } + break; + } + + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", temp); +} + static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -3786,8 +5121,7 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute case SESTO_WITH_BMC: case SESTO_WITHOUT_BMC: { - struct i2c_client *client = to_i2c_client(dev); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); unsigned short index=0, bit=0; index = (attr->index/16); @@ -3805,6 +5139,19 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned short bit = 0; + + bit = (attr->index % 8); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortTxDisableAst[attr->index / 8], bit) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3816,14 +5163,17 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute static ssize_t set_port_tx_disable(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 i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_client *client, pca9548Client; + struct i2c_bus1_hardware_monitor_data *data; long temp; if (kstrtol(buf, 10, &temp)) return -EINVAL; temp = clamp_val(temp, 0, 1); + pca9548Client = pca9548_client[1]; + client = &pca9548Client; + data = i2c_get_clientdata(client); switch(platformModelId) { case SESTO_WITH_BMC: @@ -3840,7 +5190,7 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * else PCA9553_CLEAR_BIT(data->sfpPortTxDisable[index], bit); i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortTxDisable[index]); + i2c_device_word_write(&(pca9535pwr_client[index]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortTxDisable[index]); i2c_smbus_write_byte(&(pca9548_client[1]), 0x00); mutex_unlock(&data->lock); } @@ -3851,17 +5201,18 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * { unsigned short value = 0; + pca9548Client.addr = 0x70; SFPPortTxDisable[attr->index] = (temp&0x1); if ((attr->index/8) == 5) /* SFP+ 40~47 */ { mutex_lock(&data->lock); i2c_smbus_write_byte(client, sfpPortData_78F[attr->index].portMaskIOsForPCA9548_0); - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0); if (temp==1) PCA9553_SET_BIT(value, sfpPortData_78F[attr->index].portMaskBitForTxEnPin); else PCA9553_CLEAR_BIT(value, sfpPortData_78F[attr->index].portMaskBitForTxEnPin); - i2c_device_word_write(&(pca9535pwr_client_bus1[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); + i2c_device_word_write(&(pca9535pwr_client[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -3883,6 +5234,37 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned short index = 0, bit = 0; + + pca9548Client.addr = 0x72; + index = (attr->index / 8); + bit = (attr->index % 8); + + mutex_lock(&data->lock); + if (temp == 1) + PCA9553_SET_BIT(data->sfpPortTxDisableAst[index], bit); + else + PCA9553_CLEAR_BIT(data->sfpPortTxDisableAst[index], bit); + + if (index < 3) + { + i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + i2c_smbus_write_byte_data(&(cpld_client_bus1), (0x40 + index), data->sfpPortTxDisableAst[index]); + } + else + { + i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + i2c_smbus_write_byte_data(&(cpld_client_bus1), (0x40 + (index - 3)), data->sfpPortTxDisableAst[index]); + } + + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3912,6 +5294,20 @@ static ssize_t show_port_rate_select(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned short index = 0; + + index = (attr->index % 4); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortRateSelectAst[attr->index / 4], (index * 2)) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3950,15 +5346,15 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute switch(index) { case 0: - i2c_device_word_write(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); break; case 1: - i2c_device_word_write(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); + i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); break; case 2: - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); break; default: @@ -3968,15 +5364,15 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute switch(index) { case 0: - i2c_device_word_write(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); break; case 1: - i2c_device_word_write(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); + i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); break; case 2: - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); break; default: @@ -3987,6 +5383,97 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned short index = 0, bit = 0; + + index = (attr->index / 4); + bit = (attr->index % 4); + + mutex_lock(&data->lock); + if (attr->index >= 0 && attr->index < 24) + { + /* Turn on PCA9548#0 channel 0 on I2C-bus1 - RX_RS, TX_RS */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + + if (temp == 1) + { + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + else + { + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + + switch(index) + { + case 0: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x8, data->sfpPortRateSelectAst[index]); + break; + case 1: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x9, data->sfpPortRateSelectAst[index]); + break; + case 2: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x10, data->sfpPortRateSelectAst[index]); + break; + case 3: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x11, data->sfpPortRateSelectAst[index]); + break; + case 4: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x12, data->sfpPortRateSelectAst[index]); + break; + case 5: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x13, data->sfpPortRateSelectAst[index]); + break; + } + } + else + { + /* Turn on PCA9548#0 channel 1 on I2C-bus1 - RX_RS, TX_RS */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + + if (temp == 1) + { + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + else + { + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + + switch(index) + { + case 6: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x8, data->sfpPortRateSelectAst[index]); + break; + case 7: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x9, data->sfpPortRateSelectAst[index]); + break; + case 8: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x10, data->sfpPortRateSelectAst[index]); + break; + case 9: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x11, data->sfpPortRateSelectAst[index]); + break; + case 10: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x12, data->sfpPortRateSelectAst[index]); + break; + case 11: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x13, data->sfpPortRateSelectAst[index]); + break; + } + } + + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3994,8 +5481,62 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute return count; } +static ssize_t show_port_tx_fault(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int rc = 0; + + switch(platformModelId) + { + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned short index = 0, bit = 0; + + index = (attr->index / 16); + bit = (attr->index % 16); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortTxFaultStatus[index], bit) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + { + rc = (SFPPortTxFaultStatus[attr->index] ? 0 : 1); + } + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned char qsfpPortRxLos = 0, index = 0, bit = 0; + + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 7 : 3); + mutex_lock(&data->lock); + qsfpPortRxLos = data->sfpPortAbsRxLosStatus[index]; + mutex_unlock(&data->lock); + rc = (PCA9553_TEST_BIT(qsfpPortRxLos, bit) ? 1 : 0); + } + break; + + default: + break; + } + + + return sprintf(buf, "%d\n", rc); +} + static DEVICE_ATTR(eeprom, S_IRUGO, show_eeprom, NULL); static DEVICE_ATTR(system_led, S_IWUSR, NULL, set_system_led); +static DEVICE_ATTR(fan_led, S_IRUGO, show_fan_led, NULL); +static SENSOR_DEVICE_ATTR(psu1_led, S_IRUGO, show_psu_led, NULL, 0); +static SENSOR_DEVICE_ATTR(psu2_led, S_IRUGO, show_psu_led, NULL, 1); static SENSOR_DEVICE_ATTR(port_1_data_a0, S_IRUGO, show_port_data_a0, NULL, 0); static SENSOR_DEVICE_ATTR(port_2_data_a0, S_IRUGO, show_port_data_a0, NULL, 1); @@ -4127,6 +5668,71 @@ static SENSOR_DEVICE_ATTR(port_62_data_a2, S_IRUGO, show_port_data_a2, NULL, 61) static SENSOR_DEVICE_ATTR(port_63_data_a2, S_IRUGO, show_port_data_a2, NULL, 62); static SENSOR_DEVICE_ATTR(port_64_data_a2, S_IRUGO, show_port_data_a2, NULL, 63); +static SENSOR_DEVICE_ATTR(port_1_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 0); +static SENSOR_DEVICE_ATTR(port_2_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 1); +static SENSOR_DEVICE_ATTR(port_3_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 2); +static SENSOR_DEVICE_ATTR(port_4_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 3); +static SENSOR_DEVICE_ATTR(port_5_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 4); +static SENSOR_DEVICE_ATTR(port_6_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 5); +static SENSOR_DEVICE_ATTR(port_7_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 6); +static SENSOR_DEVICE_ATTR(port_8_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 7); +static SENSOR_DEVICE_ATTR(port_9_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 8); +static SENSOR_DEVICE_ATTR(port_10_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 9); +static SENSOR_DEVICE_ATTR(port_11_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 10); +static SENSOR_DEVICE_ATTR(port_12_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 11); +static SENSOR_DEVICE_ATTR(port_13_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 12); +static SENSOR_DEVICE_ATTR(port_14_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 13); +static SENSOR_DEVICE_ATTR(port_15_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 14); +static SENSOR_DEVICE_ATTR(port_16_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 15); +static SENSOR_DEVICE_ATTR(port_17_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 16); +static SENSOR_DEVICE_ATTR(port_18_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 17); +static SENSOR_DEVICE_ATTR(port_19_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 18); +static SENSOR_DEVICE_ATTR(port_20_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 19); +static SENSOR_DEVICE_ATTR(port_21_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 20); +static SENSOR_DEVICE_ATTR(port_22_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 21); +static SENSOR_DEVICE_ATTR(port_23_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 22); +static SENSOR_DEVICE_ATTR(port_24_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 23); +static SENSOR_DEVICE_ATTR(port_25_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 24); +static SENSOR_DEVICE_ATTR(port_26_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 25); +static SENSOR_DEVICE_ATTR(port_27_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 26); +static SENSOR_DEVICE_ATTR(port_28_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 27); +static SENSOR_DEVICE_ATTR(port_29_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 28); +static SENSOR_DEVICE_ATTR(port_30_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 29); +static SENSOR_DEVICE_ATTR(port_31_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 30); +static SENSOR_DEVICE_ATTR(port_32_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 31); +static SENSOR_DEVICE_ATTR(port_33_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 32); +static SENSOR_DEVICE_ATTR(port_34_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 33); +static SENSOR_DEVICE_ATTR(port_35_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 34); +static SENSOR_DEVICE_ATTR(port_36_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 35); +static SENSOR_DEVICE_ATTR(port_37_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 36); +static SENSOR_DEVICE_ATTR(port_38_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 37); +static SENSOR_DEVICE_ATTR(port_39_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 38); +static SENSOR_DEVICE_ATTR(port_40_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 39); +static SENSOR_DEVICE_ATTR(port_41_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 40); +static SENSOR_DEVICE_ATTR(port_42_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 41); +static SENSOR_DEVICE_ATTR(port_43_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 42); +static SENSOR_DEVICE_ATTR(port_44_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 43); +static SENSOR_DEVICE_ATTR(port_45_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 44); +static SENSOR_DEVICE_ATTR(port_46_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 45); +static SENSOR_DEVICE_ATTR(port_47_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 46); +static SENSOR_DEVICE_ATTR(port_48_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 47); +static SENSOR_DEVICE_ATTR(port_49_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 48); +static SENSOR_DEVICE_ATTR(port_50_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 49); +static SENSOR_DEVICE_ATTR(port_51_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 50); +static SENSOR_DEVICE_ATTR(port_52_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 51); +static SENSOR_DEVICE_ATTR(port_53_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 52); +static SENSOR_DEVICE_ATTR(port_54_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 53); +static SENSOR_DEVICE_ATTR(port_55_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 54); +static SENSOR_DEVICE_ATTR(port_56_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 55); +static SENSOR_DEVICE_ATTR(port_57_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 56); +static SENSOR_DEVICE_ATTR(port_58_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 57); +static SENSOR_DEVICE_ATTR(port_59_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 58); +static SENSOR_DEVICE_ATTR(port_60_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 59); +static SENSOR_DEVICE_ATTR(port_61_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 60); +static SENSOR_DEVICE_ATTR(port_62_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 61); +static SENSOR_DEVICE_ATTR(port_63_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 62); +static SENSOR_DEVICE_ATTR(port_64_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 63); + static SENSOR_DEVICE_ATTR(port_1_abs, S_IRUGO, show_port_abs, NULL, 0); static SENSOR_DEVICE_ATTR(port_2_abs, S_IRUGO, show_port_abs, NULL, 1); static SENSOR_DEVICE_ATTR(port_3_abs, S_IRUGO, show_port_abs, NULL, 2); @@ -4372,9 +5978,30 @@ static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu_pin, NULL, 1); static DEVICE_ATTR(psu_power_off, S_IWUSR, NULL, set_psu_power_off); +/* lm-sensors compatible feature/subfeature names */ +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_psu_vout, NULL, 100); +static SENSOR_DEVICE_ATTR(curr12_input, S_IRUGO, show_psu_iout, NULL, 100); +static SENSOR_DEVICE_ATTR(power11_input, S_IRUGO, show_psu_pin, NULL, 100); +static SENSOR_DEVICE_ATTR(power12_input, S_IRUGO, show_psu_pout, NULL, 100); +static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_psu_temp_1, NULL, 100); +static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_psu_temp_2, NULL, 100); +static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_psu_fan_speed, NULL, 100); + +static SENSOR_DEVICE_ATTR(in22_input, S_IRUGO, show_psu_vout, NULL, 101); +static SENSOR_DEVICE_ATTR(curr22_input, S_IRUGO, show_psu_iout, NULL, 101); +static SENSOR_DEVICE_ATTR(power21_input, S_IRUGO, show_psu_pin, NULL, 101); +static SENSOR_DEVICE_ATTR(power22_input, S_IRUGO, show_psu_pout, NULL, 101); +static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO, show_psu_temp_1, NULL, 101); +static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO, show_psu_temp_2, NULL, 101); +static SENSOR_DEVICE_ATTR(fan21_input, S_IRUGO, show_psu_fan_speed, NULL, 101); + + static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4442,6 +6069,39 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { &sensor_dev_attr_port_31_data_a2.dev_attr.attr, &sensor_dev_attr_port_32_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -4506,12 +6166,32 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { &dev_attr_psu_power_off.attr, + /* lm-sensors */ + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_curr12_input.dev_attr.attr, + &sensor_dev_attr_power11_input.dev_attr.attr, + &sensor_dev_attr_power12_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + &sensor_dev_attr_power21_input.dev_attr.attr, + &sensor_dev_attr_power22_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_fan21_input.dev_attr.attr, + NULL }; static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4623,6 +6303,61 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { &sensor_dev_attr_port_53_data_a2.dev_attr.attr, &sensor_dev_attr_port_54_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -4856,12 +6591,32 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { &dev_attr_psu_power_off.attr, + /* lm-sensors */ + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_curr12_input.dev_attr.attr, + &sensor_dev_attr_power11_input.dev_attr.attr, + &sensor_dev_attr_power12_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + &sensor_dev_attr_power21_input.dev_attr.attr, + &sensor_dev_attr_power22_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_fan21_input.dev_attr.attr, + NULL }; static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4973,6 +6728,61 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { &sensor_dev_attr_port_53_data_a2.dev_attr.attr, &sensor_dev_attr_port_54_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -5157,12 +6967,32 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { &dev_attr_psu_power_off.attr, + /* lm-sensors */ + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_curr12_input.dev_attr.attr, + &sensor_dev_attr_power11_input.dev_attr.attr, + &sensor_dev_attr_power12_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + &sensor_dev_attr_power21_input.dev_attr.attr, + &sensor_dev_attr_power22_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_fan21_input.dev_attr.attr, + NULL }; static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -5294,6 +7124,71 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_port_63_data_a2.dev_attr.attr, &sensor_dev_attr_port_64_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_55_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_56_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_57_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_58_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_59_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_60_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_61_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_62_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_63_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_64_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -5524,30 +7419,432 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_psu1_vout.dev_attr.attr, &sensor_dev_attr_psu1_iout.dev_attr.attr, &sensor_dev_attr_psu1_temp_1.dev_attr.attr, - &sensor_dev_attr_psu1_temp_2.dev_attr.attr, &sensor_dev_attr_psu1_fan_speed.dev_attr.attr, &sensor_dev_attr_psu1_pout.dev_attr.attr, - &sensor_dev_attr_psu1_pin.dev_attr.attr, &sensor_dev_attr_psu2_vout.dev_attr.attr, &sensor_dev_attr_psu2_iout.dev_attr.attr, &sensor_dev_attr_psu2_temp_1.dev_attr.attr, - &sensor_dev_attr_psu2_temp_2.dev_attr.attr, &sensor_dev_attr_psu2_fan_speed.dev_attr.attr, &sensor_dev_attr_psu2_pout.dev_attr.attr, - &sensor_dev_attr_psu2_pin.dev_attr.attr, &dev_attr_psu_power_off.attr, + /* lm-sensors */ + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_curr12_input.dev_attr.attr, + &sensor_dev_attr_power11_input.dev_attr.attr, + &sensor_dev_attr_power12_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + &sensor_dev_attr_power21_input.dev_attr.attr, + &sensor_dev_attr_power22_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_fan21_input.dev_attr.attr, + NULL }; +static int is_port_present(struct i2c_bus1_hardware_monitor_data *data, int port) +{ + int rc = 0; + + switch(platformModelId) + { + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + rc = ((SFPPortAbsStatus[port] == 1) && (SFPPortDataValid[port] == 1)); + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortAbsAst = 0, index = 0, bit = 0; + unsigned char sfpPortDataValidAst = 0; + + if (port < 48) + { + index = (port / 2); + bit = ((port & 0x01) ? 5 : 1); + qsfpPortAbsAst = data->sfpPortAbsRxLosStatus[index]; + sfpPortDataValidAst = data->sfpPortDataValidAst[port]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, bit) ? 0 : 1) && (sfpPortDataValidAst)); + } + else + { + index = (port % 48); + qsfpPortAbsAst = data->qsfpPortAbsStatusAst[index]; + sfpPortDataValidAst = data->sfpPortDataValidAst[port]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, 1) ? 0 : 1) && (sfpPortDataValidAst)); + } + } + break; + + default: + { + unsigned short qsfpPortAbs = 0, index = 0, bit = 0; + unsigned short qsfpPortDataValid = 0; + + index = (port / 16); + bit = (port % 16); + qsfpPortAbs = data->qsfpPortAbsStatus[index]; + qsfpPortDataValid = data->qsfpPortDataValid[index]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbs, bit) ? 0 : 1) && (PCA9553_TEST_BIT(qsfpPortDataValid, bit))); + } + break; + } + + return rc; +} + +static ssize_t get_qsfp_port_tx_rx_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); + unsigned char qsfpPortData[QSFP_DATA_SIZE]; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = (client->addr - 1); + int val = 0; + + memset(qsfpPortData, 0, QSFP_DATA_SIZE); + + mutex_lock(&data->lock); + if (is_port_present(data, index) == 1) + memcpy(qsfpPortData, &(data->qsfpPortDataA0[index][0]), QSFP_DATA_SIZE); + else + { + qsfpPortData[SFF8436_RX_LOS_ADDR] = qsfpPortData[SFF8436_TX_FAULT_ADDR] = 0xF; + qsfpPortData[SFF8436_TX_DISABLE_ADDR] = data->qsfpPortTxDisableData[index]; + } + mutex_unlock(&data->lock); + + switch (attr->index) + { + case RX_LOS: + val = (qsfpPortData[SFF8436_RX_LOS_ADDR] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = (qsfpPortData[SFF8436_RX_LOS_ADDR] & BIT_INDEX(attr->index - RX_LOS1)); + break; + + case TX_DISABLE: + val = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & 0xF); + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + + case TX_FAULT: + val = (qsfpPortData[SFF8436_TX_FAULT_ADDR] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = (qsfpPortData[SFF8436_TX_FAULT_ADDR] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + + default: + break; + } + return sprintf(buf, "%d\n", ((val) ? 1 : 0)); +} + +static ssize_t get_port_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int status = LAST_ATTRIBUTE; + ssize_t count = 0; + + mutex_lock(&portStatusLock); + + status = attr->index; + + /* common status */ + switch (status) + { + case PRESENT: + attr->index = (client->addr - 1); + count = show_port_abs(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case EEPROM_A0_PAGE: + attr->index = (client->addr - 1); + count = show_port_data_a0(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case EEPROM_A2_PAGE: + attr->index = (client->addr - 1); + count = show_port_data_a2(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case SFP_COPPER: + attr->index = (client->addr - 1); + count = show_port_sfp_copper(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + default: + break; + } + + /* status for QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + count = get_qsfp_port_tx_rx_status(dev, devattr, buf); + mutex_unlock(&portStatusLock); + return count; + } + + /* status for SFP+ ports */ + attr->index = (client->addr - 1); + switch (status) + { + case RX_LOS: + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + count = show_port_rxlos(dev, devattr, buf); + break; + + case TX_DISABLE: + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + count = show_port_tx_disable(dev, devattr, buf); + break; + + case TX_FAULT: + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + count = show_port_tx_fault(dev, devattr, buf); + break; + + default: + count = sprintf(buf, "0\n"); + break; + } + attr->index = status; + mutex_unlock(&portStatusLock); + return count; +} + +static ssize_t set_qsfp_port_tx_status(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); + unsigned char qsfpPortData[QSFP_DATA_SIZE]; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = (client->addr - 1); + long disable; + + if (kstrtol(buf, 10, &disable)) + return -EINVAL; + disable = clamp_val(disable, 0, 1); + + memset(qsfpPortData, 0, QSFP_DATA_SIZE); + + mutex_lock(&data->lock); + memcpy(qsfpPortData, &(data->qsfpPortDataA0[index][0]), QSFP_DATA_SIZE); + switch (attr->index) + { + case TX_DISABLE: + if (disable == 1) + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] |0xF); + else + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & 0xF0); + data->qsfpPortTxDisableDataUpdate[index] = 1; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + if (disable == 1) + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] | (1 << (attr->index - TX_DISABLE1))); + else + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & ~(1 << (attr->index - TX_DISABLE1))); + data->qsfpPortTxDisableDataUpdate[index] = 1; + break; + + default: + break; + } + mutex_unlock(&data->lock); + return count; +} + +static ssize_t set_port_tx_status(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int status = LAST_ATTRIBUTE; + + mutex_lock(&portStatusLock); + + /* status for QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + set_qsfp_port_tx_status(dev, devattr, buf, count); + mutex_unlock(&portStatusLock); + return count; + } + + /* status for SFP+ ports */ + status = attr->index; + attr->index = (client->addr - 1); + switch (status) + { + case TX_DISABLE: + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + set_port_tx_disable(dev, devattr, buf, count); + break; + + default: + break; + } + attr->index = status; + mutex_unlock(&portStatusLock); + return count; +} + +static ssize_t set_port_sfp_copper(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + + /* QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + return count; + } + /* SFP+ ports */ + else + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&SfpCopperData_client); + int index = (client->addr - 1); + long value; + + if ((platformModelId != NCIIX_WITH_BMC) && (platformModelId != NCIIX_WITHOUT_BMC)) + return count; + + if (kstrtol(buf, 10, &value)) + return -EINVAL; + + mutex_lock(&data->lock); + if (SFPPortAbsStatus[index]) /*present*/ + { + i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, sfpPortData_78F[index].portMaskBitForPCA9548_1); + i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, sfpPortData_78F[index].portMaskBitForPCA9548_2TO5); + i2c_device_word_write(&SfpCopperData_client, + (unsigned char)((value >> 16) & 0xff), + (unsigned short)(value & 0xffff)); + i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, 0x00); + i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, 0x00); + } + mutex_unlock(&data->lock); + } + + return count; +} + +static SENSOR_DEVICE_ATTR(abs, S_IRUGO, get_port_status, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(rxlos, S_IRUGO, get_port_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(rxlos1, S_IRUGO, get_port_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(rxlos2, S_IRUGO, get_port_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(rxlos3, S_IRUGO, get_port_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(rxlos4, S_IRUGO, get_port_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(tx_disable, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE); +static SENSOR_DEVICE_ATTR(tx_disable1, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(tx_disable2, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(tx_disable3, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(tx_disable4, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(tx_fault, S_IRUGO, get_port_status, NULL, TX_FAULT); +static SENSOR_DEVICE_ATTR(tx_fault1, S_IRUGO, get_port_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(tx_fault2, S_IRUGO, get_port_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(tx_fault3, S_IRUGO, get_port_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(tx_fault4, S_IRUGO, get_port_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(data_a0, S_IRUGO, get_port_status, NULL, EEPROM_A0_PAGE); +static SENSOR_DEVICE_ATTR(data_a2, S_IRUGO, get_port_status, NULL, EEPROM_A2_PAGE); +static SENSOR_DEVICE_ATTR(sfp_copper, S_IWUSR | S_IRUGO, get_port_status, set_port_sfp_copper, SFP_COPPER); + +static struct attribute *sfp_attributes[] = { + &sensor_dev_attr_abs.dev_attr.attr, + &sensor_dev_attr_rxlos.dev_attr.attr, + &sensor_dev_attr_rxlos1.dev_attr.attr, + &sensor_dev_attr_rxlos2.dev_attr.attr, + &sensor_dev_attr_rxlos3.dev_attr.attr, + &sensor_dev_attr_rxlos4.dev_attr.attr, + &sensor_dev_attr_tx_disable.dev_attr.attr, + &sensor_dev_attr_tx_disable1.dev_attr.attr, + &sensor_dev_attr_tx_disable2.dev_attr.attr, + &sensor_dev_attr_tx_disable3.dev_attr.attr, + &sensor_dev_attr_tx_disable4.dev_attr.attr, + &sensor_dev_attr_tx_fault.dev_attr.attr, + &sensor_dev_attr_tx_fault1.dev_attr.attr, + &sensor_dev_attr_tx_fault2.dev_attr.attr, + &sensor_dev_attr_tx_fault3.dev_attr.attr, + &sensor_dev_attr_tx_fault4.dev_attr.attr, + &sensor_dev_attr_data_a0.dev_attr.attr, + &sensor_dev_attr_data_a2.dev_attr.attr, + &sensor_dev_attr_sfp_copper.dev_attr.attr, + NULL +}; + +static const struct attribute_group sfp_group = { + .attrs = sfp_attributes, +}; + +static struct i2c_client *sfpPortDeviceCreate(struct i2c_adapter *adap, int port, const char *sfpType) +{ + struct i2c_client *client = NULL; + int status; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!client) + return NULL; + + client->adapter = adap; + client->addr = (port + 1); + sprintf(client->name, "%s_%03d", sfpType, (port + 1)); + client->dev.parent = &client->adapter->dev; + dev_set_name(&client->dev, "port_%03d", (port + 1)); + status = device_register(&client->dev); + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_group); + return client; +} + static void i2c_bus0_devices_client_address_init(struct i2c_client *client) { int index; - pca9535pwr_client = *client; - pca9535pwr_client.addr = 0x27; + pca9535pwr_client_bus0 = *client; + pca9535pwr_client_bus0.addr = 0x27; cpld_client = *client; cpld_client.addr = 0x33; @@ -5635,7 +7932,7 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien /* Get device id */ data->dviceId= i2c_smbus_read_byte_data(client, W83795ADG_REG_DEVICE_ID); - /* set FANCTL8 ¡V FANCTL1 output mode control to PWM output duty cycle mode. */ + /* set FANCTL8 - FANCTL1 output mode control to PWM output duty cycle mode. */ i2c_smbus_write_byte_data(client, W83795ADG_REG_FOMC, 0x00); i2c_smbus_write_byte_data(client, W83795ADG_REG_F1OV, 0xff); i2c_smbus_write_byte_data(client, W83795ADG_REG_F2OV, 0xff); @@ -5644,6 +7941,10 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien i2c_smbus_write_byte_data(client, W83795ADG_REG_BANK, 0x00); /* Enable TR1~TR4 thermistor temperature monitoring */ i2c_smbus_write_byte_data(client, W83795ADG_REG_TEMP_CTRL2, 0xff); + + /* set FANCTL2 to enable FANIN9 and FANIN10 monitoring */ + i2c_smbus_write_byte_data(client, W83795ADG_REG_FANIN_CTRL2, 0x03); + /* Enable monitoring operations */ configByte |= 0x01; i2c_smbus_write_byte_data(client, W83795ADG_REG_CONFIG, configByte); @@ -5732,10 +8033,10 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien default: /* set default value for IO expander #0 */ - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); /* set input-1/output-0 mode for IO expander #0 */ - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xff7f); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xff7f); break; } @@ -5754,27 +8055,47 @@ static void i2c_bus1_devices_client_address_init(struct i2c_client *client) for (index=0; index<6; index++) { - pca9535pwr_client_bus1[index] = *client; - pca9535pwr_client_bus1[index].addr = (0x20+index); + pca9535pwr_client[index] = *client; + pca9535pwr_client[index].addr = (0x20+index); } + cpld_client_bus1 = *client; + cpld_client_bus1.addr = 0x33; + qsfpDataA0_client = *client; qsfpDataA0_client.addr = 0x50; qsfpDataA2_client = *client; qsfpDataA2_client.addr = 0x51; - eeprom_client = *client; - eeprom_client.addr = 0x54; + SfpCopperData_client = *client; + SfpCopperData_client.addr = 0x56; - eeprom_client_2 = *client; - eeprom_client_2.addr = 0x56; + switch(platformModelId) + { + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + eeprom_client = *client; + eeprom_client.addr = 0x56; - psu_eeprom_client = *client; - psu_eeprom_client.addr = 0x50; + psu_eeprom_client = *client; + psu_eeprom_client.addr = 0x51; - psu_mcu_client = *client; - psu_mcu_client.addr = 0x58; + psu_mcu_client = *client; + psu_mcu_client.addr = 0x59; + break; + + default: + eeprom_client = *client; + eeprom_client.addr = 0x54; + + psu_eeprom_client = *client; + psu_eeprom_client.addr = 0x50; + + psu_mcu_client = *client; + psu_mcu_client.addr = 0x58; + break; + } } static void i2c_bus1_io_expander_default_set(struct i2c_client *client) @@ -5793,8 +8114,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 4 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548 channel 5 on I2C-bus1 */ @@ -5804,27 +8125,27 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-2 on channel 5 */ for (i=0; i<2; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } /* RST#(Module Reset) = 1 */ /* set input-1/output-0 mode for IO expander #3-4 on channel 5 */ for (i=2; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } /* MODSEL# (Module Select) = 0 */ /* set input-1/output-0 mode for IO expander #5-6 on channel 5 */ for (i=4; i<6; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } if (isBMCSupport == 0) @@ -5833,30 +8154,30 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) i2c_smbus_write_byte(client, (1<frontLedStatus); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } } @@ -5875,8 +8196,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 0 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 1 on I2C-bus1 - RXLOS */ @@ -5884,8 +8205,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-3 on channel 1 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 2 on I2C-bus1 - TXFAULT */ @@ -5893,8 +8214,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-3 on channel 2 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 3 on I2C-bus1 - TX_RS = 1, LPMODE = 0, MODSEL = 0 */ @@ -5902,22 +8223,22 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 3 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); /* Turn on PCA9548#1 channel 4 on I2C-bus1 - RX _RS = 1 */ i2c_smbus_write_byte(&(pca9548_client[1]), (1<frontLedStatus); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); /* Turn off PCA9548#0 all channels on I2C-bus1 */ i2c_smbus_write_byte(client, 0x00); } @@ -5979,17 +8300,17 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #20-23 on channel 0 : SFP+ 40-47 : TXEN = 0, RX_RS = 0, TX_RS = 0 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xf1c7); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xf1c7); } /* Turn on PCA9548#1 channel 1 on I2C-bus1 */ i2c_smbus_write_byte(client, (1<frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + + /* Turn on PCA9548#0 channel 5 on I2C-bus1 */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH05)); + /* PSU Status */ + /* set input-1/output-0 mode for IO expander #1 on channel 5 */ + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); +/* If the PSU_PWROFF pin of IO expander is output mode, the power cycling of CPLD cannot work.*/ +#if 0 + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffbb); +#else + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); +#endif + + /* Turn off PCA9548#0 all channels on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x00); break; default: @@ -6213,6 +8570,69 @@ static int w83795adg_hardware_monitor_probe(struct i2c_client *client, } else { + struct i2c_adapter *adap = to_i2c_adapter(&client->dev); + int port; + + for (port = 0; port < QSFP_COUNT; port++) + data->qsfpPortTxDisableDataUpdate[port] = 1; + mutex_init(&portStatusLock); + switch (platformModelId) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + /* QSFP ports */ + for (port = 0; port < 32; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + /* SFP+ ports */ + for (port = 0; port < 48; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "sfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + /* QSFP ports */ + for (port = 48; port < 54; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + /* SFP+ ports */ + for (port = 0; port < 48; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "sfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + /* QSFP ports */ + for (port = 48; port < 64; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + default: + break; + } + init_completion(&data->auto_update_stop); data->auto_update = kthread_run(i2c_bus1_hardware_monitor_update_thread, client, dev_name(data->hwmon_dev)); if (IS_ERR(data->auto_update)) { @@ -6249,16 +8669,35 @@ static int w83795adg_hardware_monitor_remove(struct i2c_client *client) i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_LED_0x44, 0x00); #endif + mutex_destroy(&client->dev.mutex); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); + mutex_destroy(&data->lock); } else if(client->adapter->nr == 0x1) { + int port; + struct i2c_client *c; struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); kthread_stop(data->auto_update); wait_for_completion(&data->auto_update_stop); + for (port = 0; port < QSFP_COUNT; port ++) + { + c = data->sfpPortClient[port]; + if (c) + { + sysfs_remove_group(&c->dev.kobj, &sfp_group); + mutex_destroy(&c->dev.mutex); + device_del(&c->dev); + kfree(c); + } + } + mutex_destroy(&portStatusLock); + + mutex_destroy(&client->dev.mutex); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); + mutex_destroy(&data->lock); } return 0; } @@ -6284,8 +8723,22 @@ static void w83795adg_hardware_monitor_shutdown(struct i2c_client *client) i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_LED_0x44, 0x00); #endif /* reset MAC */ - i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6e); - i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6f); + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x3e); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x3f); + /* reset CPLD 2, 3 and 4 */ + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x35, 0xfd); /* assert RST_CPLD2_3_4 */ + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x35, 0xff); + break; + + default: + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6e); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6f); + break; + } hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore new file mode 100755 index 00000000..ec93c180 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore @@ -0,0 +1,2 @@ +*x86*64*netberg*aurora*420*rangeley*.mk +onlpdump.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml new file mode 100755 index 00000000..b3df78e4 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=amd64 VENDOR=netberg BASENAME=x86-64-netberg-aurora-420-rangeley diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml new file mode 100755 index 00000000..85e495fc --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-netberg-aurora-420-rangeley ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile new file mode 100755 index 00000000..b7174f7d --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-netberg-aurora-420-rangeley +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_netberg_aurora_420_rangeley onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-netberg-aurora-420-rangeley.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..b88bedd8 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_netberg_aurora_420_rangeley onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore new file mode 100644 index 00000000..c81d16be --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore @@ -0,0 +1 @@ +*.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module new file mode 100755 index 00000000..d3df16ce --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module @@ -0,0 +1 @@ +name: x86_64_netberg_aurora_420_rangeley diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile new file mode 100755 index 00000000..e0be8a99 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_netberg_aurora_420_rangeley +AUTOMODULE := x86_64_netberg_aurora_420_rangeley +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml new file mode 100644 index 00000000..c9e72b4f --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml @@ -0,0 +1,119 @@ +############################################################################### +# +# x86_64_netberg_aurora_420_rangeley Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD: + doc: "RPM Threshold at which the fan is considered to have failed." + default: 3000 + +definitions: + cdefs: + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_netberg_aurora_420_rangeley_config + + enum: &enums + + fan_id: + members: + - FAN1 : 1 + - FAN2 : 2 + - FAN3 : 3 + - FAN4 : 4 + - FAN5 : 5 + - FAN6 : 6 + - FAN7 : 7 + - FAN8 : 8 + - FAN9 : 9 + - FAN10 : 10 + + fan_oid: + members: + - FAN1 : ONLP_FAN_ID_CREATE(1) + - FAN2 : ONLP_FAN_ID_CREATE(2) + - FAN3 : ONLP_FAN_ID_CREATE(3) + - FAN4 : ONLP_FAN_ID_CREATE(4) + - FAN5 : ONLP_FAN_ID_CREATE(5) + - FAN6 : ONLP_FAN_ID_CREATE(6) + - FAN7 : ONLP_FAN_ID_CREATE(7) + - FAN8 : ONLP_FAN_ID_CREATE(8) + - FAN9 : ONLP_FAN_ID_CREATE(9) + - FAN10 : ONLP_FAN_ID_CREATE(10) + + psu_id: + members: + - PSU1 : 1 + - PSU2 : 2 + + psu_oid: + members: + - PSU1 : ONLP_PSU_ID_CREATE(1) + - PSU2 : ONLP_PSU_ID_CREATE(2) + + thermal_id: + members: + - THERMAL1 : 1 + - THERMAL2 : 2 + - THERMAL3 : 3 + - THERMAL4 : 4 + - THERMAL5 : 5 + - THERMAL6 : 6 + - THERMAL7 : 7 + + thermal_oid: + members: + - THERMAL1 : ONLP_THERMAL_ID_CREATE(1) + - THERMAL2 : ONLP_THERMAL_ID_CREATE(2) + - THERMAL3 : ONLP_THERMAL_ID_CREATE(3) + - THERMAL4 : ONLP_THERMAL_ID_CREATE(4) + - THERMAL5 : ONLP_THERMAL_ID_CREATE(5) + - THERMAL6 : ONLP_THERMAL_ID_CREATE(6) + - THERMAL7 : ONLP_THERMAL_ID_CREATE(7) + + led_id: + members: + - STAT : 1 + - FAN : 2 + - PSU1 : 3 + - PSU2 : 4 + + led_oid: + members: + - STAT : ONLP_LED_ID_CREATE(1) + - FAN : ONLP_LED_ID_CREATE(2) + - PSU1 : ONLP_LED_ID_CREATE(3) + - PSU2 : ONLP_LED_ID_CREATE(4) + + portingmacro: + X86_64_NETBERG_AURORA_420_RANGELEY: + macros: + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x new file mode 100755 index 00000000..7be4645d --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h new file mode 100755 index 00000000..6a506e23 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_netberg_aurora_420_rangeley Configuration Header + * + * @addtogroup x86_64_netberg_aurora_420_rangeley-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + * + * RPM Threshold at which the fan is considered to have failed. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD 3000 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_netberg_aurora_420_rangeley_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_netberg_aurora_420_rangeley_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_netberg_aurora_420_rangeley_config_settings table. */ +extern x86_64_netberg_aurora_420_rangeley_config_settings_t x86_64_netberg_aurora_420_rangeley_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_netberg_aurora_420_rangeley_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_netberg_aurora_420_rangeley_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_netberg_aurora_420_rangeley_porting.h" + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h new file mode 100755 index 00000000..d37fea93 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_netberg_aurora_420_rangeley Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ + +/** + * @defgroup x86_64_netberg_aurora_420_rangeley x86_64_netberg_aurora_420_rangeley - x86_64_netberg_aurora_420_rangeley Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_netberg_aurora_420_rangeley-x86_64_netberg_aurora_420_rangeley Public Interface + * @defgroup x86_64_netberg_aurora_420_rangeley-config Compile Time Configuration + * @defgroup x86_64_netberg_aurora_420_rangeley-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h new file mode 100755 index 00000000..79f2983a --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_netberg_aurora_420_rangeley Porting Macros. + * + * @addtogroup x86_64_netberg_aurora_420_rangeley-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ + + +/* */ +#if X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET GLOBAL_MEMSET + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET memset + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY GLOBAL_MEMCPY + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY memcpy + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY GLOBAL_STRNCPY + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY strncpy + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF vsnprintf + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF snprintf + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN GLOBAL_STRLEN + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN strlen + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk new file mode 100644 index 00000000..dea3e533 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_netberg_aurora_420_rangeley_INCLUDES := -I $(THIS_DIR)inc +x86_64_netberg_aurora_420_rangeley_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_netberg_aurora_420_rangeley_DEPENDMODULE_ENTRIES := init:x86_64_netberg_aurora_420_rangeley ucli:x86_64_netberg_aurora_420_rangeley + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile new file mode 100755 index 00000000..ef9d70ed --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_netberg_aurora_420_rangeley_ucli.c + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c new file mode 100755 index 00000000..4cc75804 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c @@ -0,0 +1,234 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#include + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +sys_fan_info_get__(onlp_fan_info_t* info, int id) +{ + int value = 0; + int rv; + + rv = onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/fan%d_abs", ((id/2)+1)); + if (rv != ONLP_STATUS_OK) + return rv; + + if (value == 0) + { + info->status = ONLP_FAN_STATUS_FAILED; + } + else + { + info->status = ONLP_FAN_STATUS_PRESENT; + + rv = onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/fan%d_dir", ((id/2)+1)); + if (rv != ONLP_STATUS_OK) + return rv; + + if (value == 1) + { + info->status |= ONLP_FAN_STATUS_B2F; + info->caps |= ONLP_FAN_CAPS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_F2B; + info->caps |= ONLP_FAN_CAPS_F2B; + } + + rv = onlp_file_read_int(&(info->rpm), SYS_HWMON1_PREFIX "/fan%d_rpm", (id+1)); + if (rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if (rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~1; + return 0; + } + + if (info->rpm <= X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD) + info->status |= ONLP_FAN_STATUS_FAILED; + + + rv = onlp_file_read_int(&(info->percentage), SYS_HWMON1_PREFIX "/fan%d_duty", (id+1)); + if (rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if (rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~1; + return 0; + } + } + return 0; +} + +static int +psu_fan_info_get__(onlp_fan_info_t* info, int id) +{ + return onlp_file_read_int(&(info->rpm), SYS_HWMON2_PREFIX "/psu%d_fan_speed", id); +} + +/* Onboard Fans */ +static onlp_fan_info_t fans__[] = { + { }, /* Not used */ + { { FAN_OID_FAN1, "Fan1_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN2, "Fan1_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN3, "Fan2_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN4, "Fan2_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN5, "Fan3_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN6, "Fan3_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN7, "Fan4_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN8, "Fan4_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN9, "PSU-1 Fan", 0 }, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN10, "PSU-2 Fan", 0 }, ONLP_FAN_STATUS_PRESENT }, +}; + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int fid; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_fan_info_t)); + fid = ONLP_OID_ID_GET(id); + *info = fans__[fid]; + + info->caps |= ONLP_FAN_CAPS_GET_RPM; + + switch(fid) + { + case FAN_ID_FAN1: + case FAN_ID_FAN2: + case FAN_ID_FAN3: + case FAN_ID_FAN4: + case FAN_ID_FAN5: + case FAN_ID_FAN6: + case FAN_ID_FAN7: + case FAN_ID_FAN8: + return sys_fan_info_get__(info, (fid - 1)); + break; + + case FAN_ID_FAN9: + case FAN_ID_FAN10: + return psu_fan_info_get__(info, (fid - FAN_ID_FAN9 + 1)); + break; + + default: + return ONLP_STATUS_E_INVALID; + break; + } + + return ONLP_STATUS_E_INVALID; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c new file mode 100755 index 00000000..2b482315 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c @@ -0,0 +1,221 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum led_light_mode { /*must be the same with the definition @ kernel driver */ + LED_MODE_OFF = 0, + LED_MODE_AMBER, + LED_MODE_GREEN, +}; + +int led_light_map_mode[][2] = +{ + {LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { LED_OID_LED1, "Chassis LED 1 (STAT LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED2, "Chassis LED 2 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED3, "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED4, "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, +}; + +static int conver_led_light_mode_to_driver(int led_ligth_mode) +{ + int i, nsize = sizeof(led_light_map_mode)/sizeof(led_light_map_mode[0]); + for(i=0; i + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static onlp_psu_info_t psus__[] = { + { }, /* Not used */ + { + { + PSU_OID_PSU1, + "PSU-1", + 0, + { + FAN_OID_FAN9, + }, + } + }, + { + { + PSU_OID_PSU2, + "PSU-2", + 0, + { + FAN_OID_FAN10, + }, + } + }, +}; + +/* + * This function will be called prior to any other onlp_psui functions. + */ +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int rv; + int pid; + uint8_t data[256]; + int value = -1; + int len; + double dvalue; + int i; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + pid = ONLP_OID_ID_GET(id); + *info = psus__[pid]; + + rv = onlp_file_read_int(&value, SYS_HWMON1_PREFIX "/psu%d_abs", pid); + if (rv != ONLP_STATUS_OK) + return rv; + if (value == 0) + { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ONLP_STATUS_OK; + } + + /* PSU is present. */ + info->status = ONLP_PSU_STATUS_PRESENT; + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_eeprom", pid); + if (rv == ONLP_STATUS_OK) + { + i = 11; + + /* Manufacturer Name */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Name */ + len = (data[i]&0x0f); + i++; + memcpy(info->model, (char *) &(data[i]), len); + i += len; + + /* Product part,model number */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Version */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Serial Number */ + len = (data[i]&0x0f); + i++; + memcpy(info->serial, (char *) &(data[i]), len); + } + else + { + strcpy(info->model, "Missing"); + strcpy(info->serial, "Missing"); + } + + info->caps |= ONLP_PSU_CAPS_AC; + +#if 0 + /* PSU is powered. */ + rv = onlp_file_read_int(&value, SYS_HWMON1_PREFIX "/psu%d_pg", pid); + if (rv != ONLP_STATUS_OK) + return rv; + if (value == 0) + { + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } +#endif + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_iout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_IOUT; + info->miout = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_vout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_VOUT; + info->mvout = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_pin", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_PIN; + info->mpin = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_pout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_POUT; + info->mpout = (int)(dvalue * 1000); + } + } + + return ONLP_STATUS_OK; +} + +/* + * This is an optional generic ioctl() interface. + * Its purpose is to allow future expansion and + * custom functionality that is not otherwise exposed + * in the standard interface. + * + * The semantics of this function are platform specific. + * This function is completely optional. + */ +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c new file mode 100755 index 00000000..5aaf3760 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c @@ -0,0 +1,451 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * SFPI Interface for the Aurora 420 Platform + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#include +#include + +/* Model ID Definition */ +typedef enum +{ + HURACAN_WITH_BMC = 0x0, + HURACAN_WITHOUT_BMC, + CABRERAIII_WITH_BMC, + CABRERAIII_WITHOUT_BMC, + SESTO_WITH_BMC, + SESTO_WITHOUT_BMC, + NCIIX_WITH_BMC, + NCIIX_WITHOUT_BMC, + ASTERION_WITH_BMC, + ASTERION_WITHOUT_BMC, + HURACAN_A_WITH_BMC, + HURACAN_A_WITHOUT_BMC, + + MODEL_ID_LAST +} modelId_t; + +static int +onlp_board_model_id_get(void) +{ + static int board_model_id = MODEL_ID_LAST; + + if (board_model_id == MODEL_ID_LAST) + { + if (onlp_file_read_int(&board_model_id, SYS_HWMON1_PREFIX "/board_model_id") != ONLP_STATUS_OK) + return 0; + } + + return board_model_id; +} + +/* + * This function will be called prior to all other onlp_sfpi_* functions. + */ +int +onlp_sfpi_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * This function should populate the give bitmap with + * all valid, SFP-capable port numbers. + * + * Only port numbers in this bitmap will be queried by the the + * ONLP framework. + * + * No SFPI functions will be called with ports that are + * not in this bitmap. You can ignore all error checking + * on the incoming ports defined in this interface. + */ +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + int total_port = 0; + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + total_port = 32; + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + total_port = 54; + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + total_port = 64; + break; + + default: + break; + } + + AIM_BITMAP_CLR_ALL(bmap); + for(p = 0; p < total_port; p++) + AIM_BITMAP_SET(bmap, p); + + return ONLP_STATUS_OK; +} + +/* + * This function should return whether an SFP is inserted on the given + * port. + * + * Returns 1 if the SFP is present. + * Returns 0 if the SFP is not present. + * Returns ONLP_E_* if there was an error determining the status. + */ +int +onlp_sfpi_is_present(int port) +{ + int value = 0; + + onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/port_%d_abs", (port+1)); + return value; +} + +int +onlp_sfpi_port_map(int port, int* rport) +{ + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + /* odd <=> even */ + if (port & 0x1) + *rport = (port - 1); + else + *rport = (port + 1); + break; + + default: + *rport = port; break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + int total_port = 0; + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + total_port = 32; + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + total_port = 54; + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + total_port = 64; + break; + + default: + break; + } + + AIM_BITMAP_CLR_ALL(bmap); + for(p = 0; p < total_port; p++) + AIM_BITMAP_SET(bmap, p); + + return ONLP_STATUS_OK; +} + +/* + * This function reads the SFPs idrom and returns in + * in the data buffer provided. + */ +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + int rv = ONLP_STATUS_OK; + char fname[128]; + + memset(data, 0, 256); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_data_a0", (port+1)); + rv = onlplib_sfp_eeprom_read_file(fname, data); + if (rv != ONLP_STATUS_OK) + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + + return rv; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + int rv = ONLP_STATUS_OK; + char fname[128]; + + memset(data, 0, 256); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_data_a2", (port+1)); + rv = onlplib_sfp_eeprom_read_file(fname, data); + if (rv != ONLP_STATUS_OK) + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + + return rv; +} + +/* + * Manually enable or disable the given SFP. + * + */ +int +onlp_sfpi_enable_set(int port, int enable) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Returns whether the SFP is currently enabled or disabled. + */ +int +onlp_sfpi_enable_get(int port, int* enable) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * If the platform requires any setup or equalizer modifications + * based on the actual SFP that was inserted then that custom + * setup should be performed here. + * + * After a new SFP is detected by the ONLP framework this + * function will be called to perform the (optional) setup. + */ +int +onlp_sfpi_post_insert(int port, sff_info_t* sff_info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Return the current status of the SFP. + * See onlp_sfp_status_t; + */ +int +onlp_sfpi_status_get(int port, uint32_t* status) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* supported) +{ + if (supported == NULL) + return ONLP_STATUS_E_PARAM; + + *supported = 0; + switch (control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + case ONLP_SFP_CONTROL_RX_LOS: + case ONLP_SFP_CONTROL_TX_FAULT: + { + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + *supported = 1; + break; + + default: + break; + } + } + break; + + default: + break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv = ONLP_STATUS_OK; + int supported = 0; + + if ((onlp_sfpi_control_supported(port, control, &supported) == ONLP_STATUS_OK) && (supported == 0)) + return ONLP_STATUS_E_UNSUPPORTED; + + switch (control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + rv = onlp_file_write_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_disable", (port+1)); + break; + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv = ONLP_STATUS_OK; + int supported = 0; + + if (value == NULL) + return ONLP_STATUS_E_PARAM; + + if ((onlp_sfpi_control_supported(port, control, &supported) == ONLP_STATUS_OK) && (supported == 0)) + return ONLP_STATUS_E_UNSUPPORTED; + + *value = 0; + switch (control) + { + case ONLP_SFP_CONTROL_RX_LOS: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_rxlos", (port+1)); + break; + + case ONLP_SFP_CONTROL_TX_DISABLE: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_disable", (port+1)); + break; + + case ONLP_SFP_CONTROL_TX_FAULT: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_fault", (port+1)); + break; + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int value = 0; + char fname[128]; + char data[512]; + + memset(data, 0, 512); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_sfp_copper", (port+1)); + + int fd = open(fname, O_RDONLY); + if (fd < 0) { + AIM_LOG_INFO("Unable to read devaddr(0xAC) from port(%d)\r\n", port); + return value; + } + + int nrd = read(fd, data, 512); + close(fd); + + if (nrd != 512) { + AIM_LOG_INTERNAL("Failed to read EEPROM file '%s'", fname); + return value; + } + + value = (((data[addr*2 + 1] & 0xff) << 8) | (data[addr*2] & 0xff)) & 0xffff; + + return value; +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int rv = ONLP_STATUS_OK; + int data = 0; + + data = ((addr << 16) | (value & 0xffff)) & 0x00ffffff; + rv = onlp_file_write_int(data, SYS_HWMON2_PREFIX "/port_%d_sfp_copper", (port+1)); + + return rv; +} + +/* + * This is a generic ioctl interface. + */ +int +onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * De-initialize the SFPI subsystem. + */ +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c new file mode 100755 index 00000000..7e044c3b --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c @@ -0,0 +1,98 @@ +/************************************************************ + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +/* + * This is the first function called by the ONLP framework. + * + * It should return the name of your platform driver. + * + * If the name of your platform driver is the same as the + * current platform then this driver will be used. + * + * If the name of the driver is different from the current + * platform, or the driver is capable of supporting multiple + * platform variants, see onlp_sysi_platform_set() below. + */ +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-netberg-aurora-420-rangeley-r0"; +} + +/* + * This is the first function the ONLP framework will call + * after it has validated the the platform is supported using the mechanisms + * described above. + * + * If this function does not return ONL_STATUS_OK + * then platform initialization is aborted. + */ +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_onie_info_get(onlp_onie_info_t* onie) +{ + int rv; + uint8_t data[256]; + int len; + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/eeprom"); + if (rv == ONLP_STATUS_OK) + { + rv = onlp_onie_decode(onie, (uint8_t*)data, sizeof(data)); + if(rv >= 0) + { + onie->platform_name = aim_strdup("x86-64-netberg-aurora-420-rangeley-r0"); + } + } + return rv; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + int i; + int n_thermal=7, n_fan=10, n_led=4; + + /* 2 PSUs */ + *e++ = ONLP_PSU_ID_CREATE(1); + *e++ = ONLP_PSU_ID_CREATE(2); + + /* LEDs Item */ + for (i=1; i<=n_led; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* THERMALs Item */ + for (i=1; i<=n_thermal; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* Fans Item */ + for (i=1; i<=n_fan; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c new file mode 100755 index 00000000..e3241013 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c @@ -0,0 +1,173 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html + * + * 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +sys_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + + if (id == THERMAL_ID_THERMAL3) + { + rv = onlp_file_read_int(&info->mcelsius, SYS_HWMON1_PREFIX "/mac_temp"); + info->mcelsius *= 1000; + } + else + { + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON1_PREFIX "/remote_temp%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + } + + if(rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if(rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~(ONLP_THERMAL_STATUS_PRESENT); + return ONLP_STATUS_OK; + } + + return ONLP_STATUS_OK; +} + +static int +psu1_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON2_PREFIX "/psu1_temp_%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + return rv; +} + +static int +psu2_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON2_PREFIX "/psu2_temp_%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + return rv; +} + +static onlp_thermal_info_t temps__[] = +{ + { }, /* Not used */ + { { THERMAL_OID_THERMAL1, "Chassis Thermal 1 (Front of MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL2, "Chassis Thermal 2 (Rear of MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL3, "Chassis Thermal 3 (MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + + { { THERMAL_OID_THERMAL4, "PSU-1 Thermal 1", PSU_OID_PSU1 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL5, "PSU-1 Thermal 2", PSU_OID_PSU1 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + + { { THERMAL_OID_THERMAL6, "PSU-2 Thermal 1", PSU_OID_PSU2 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL7, "PSU-2 Thermal 2", PSU_OID_PSU2 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, +}; + + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_thermal_info_t)); + tid = ONLP_OID_ID_GET(id); + *info = temps__[tid]; + + switch(tid) + { + case THERMAL_ID_THERMAL1: + case THERMAL_ID_THERMAL2: + case THERMAL_ID_THERMAL3: + return sys_thermal_info_get__(info, tid); + + case THERMAL_ID_THERMAL4: + case THERMAL_ID_THERMAL5: + return psu1_thermal_info_get__(info, (tid - THERMAL_ID_THERMAL4 + 1)); + + case THERMAL_ID_THERMAL6: + case THERMAL_ID_THERMAL7: + return psu2_thermal_info_get__(info, (tid - THERMAL_ID_THERMAL6 + 1)); + } + + return ONLP_STATUS_E_INVALID; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c new file mode 100755 index 00000000..94ef2e10 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(_x) __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(_x) +x86_64_netberg_aurora_420_rangeley_config_settings_t x86_64_netberg_aurora_420_rangeley_config_settings[] = +{ +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE +#undef __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME + +const char* +x86_64_netberg_aurora_420_rangeley_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_netberg_aurora_420_rangeley_config_settings[i].name; i++) { + if(!strcmp(x86_64_netberg_aurora_420_rangeley_config_settings[i].name, setting)) { + return x86_64_netberg_aurora_420_rangeley_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_netberg_aurora_420_rangeley_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_netberg_aurora_420_rangeley_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_netberg_aurora_420_rangeley_config_settings[i].name, x86_64_netberg_aurora_420_rangeley_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c new file mode 100755 index 00000000..1df7f4cd --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h new file mode 100755 index 00000000..3067638c --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h @@ -0,0 +1,271 @@ +/**************************************************************************//** + * + * x86_64_netberg_aurora_420_rangeley Internal Header + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ + +#include +#include + +/* */ +/** fan_id */ +typedef enum fan_id_e { + FAN_ID_FAN1 = 1, + FAN_ID_FAN2 = 2, + FAN_ID_FAN3 = 3, + FAN_ID_FAN4 = 4, + FAN_ID_FAN5 = 5, + FAN_ID_FAN6 = 6, + FAN_ID_FAN7 = 7, + FAN_ID_FAN8 = 8, + FAN_ID_FAN9 = 9, + FAN_ID_FAN10 = 10, +} fan_id_t; + +/** Enum names. */ +const char* fan_id_name(fan_id_t e); + +/** Enum values. */ +int fan_id_value(const char* str, fan_id_t* e, int substr); + +/** Enum descriptions. */ +const char* fan_id_desc(fan_id_t e); + +/** Enum validator. */ +int fan_id_valid(fan_id_t e); + +/** validator */ +#define FAN_ID_VALID(_e) \ + (fan_id_valid((_e))) + +/** fan_id_map table. */ +extern aim_map_si_t fan_id_map[]; +/** fan_id_desc_map table. */ +extern aim_map_si_t fan_id_desc_map[]; + +/** fan_oid */ +typedef enum fan_oid_e { + FAN_OID_FAN1 = ONLP_FAN_ID_CREATE(1), + FAN_OID_FAN2 = ONLP_FAN_ID_CREATE(2), + FAN_OID_FAN3 = ONLP_FAN_ID_CREATE(3), + FAN_OID_FAN4 = ONLP_FAN_ID_CREATE(4), + FAN_OID_FAN5 = ONLP_FAN_ID_CREATE(5), + FAN_OID_FAN6 = ONLP_FAN_ID_CREATE(6), + FAN_OID_FAN7 = ONLP_FAN_ID_CREATE(7), + FAN_OID_FAN8 = ONLP_FAN_ID_CREATE(8), + FAN_OID_FAN9 = ONLP_FAN_ID_CREATE(9), + FAN_OID_FAN10 = ONLP_FAN_ID_CREATE(10), +} fan_oid_t; + +/** Enum names. */ +const char* fan_oid_name(fan_oid_t e); + +/** Enum values. */ +int fan_oid_value(const char* str, fan_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* fan_oid_desc(fan_oid_t e); + +/** Enum validator. */ +int fan_oid_valid(fan_oid_t e); + +/** validator */ +#define FAN_OID_VALID(_e) \ + (fan_oid_valid((_e))) + +/** fan_oid_map table. */ +extern aim_map_si_t fan_oid_map[]; +/** fan_oid_desc_map table. */ +extern aim_map_si_t fan_oid_desc_map[]; + +/** led_id */ +typedef enum led_id_e { + LED_ID_LED1 = 1, + LED_ID_LED2 = 2, + LED_ID_LED3 = 3, + LED_ID_LED4 = 4, +} led_id_t; + +/** Enum names. */ +const char* led_id_name(led_id_t e); + +/** Enum values. */ +int led_id_value(const char* str, led_id_t* e, int substr); + +/** Enum descriptions. */ +const char* led_id_desc(led_id_t e); + +/** Enum validator. */ +int led_id_valid(led_id_t e); + +/** validator */ +#define LED_ID_VALID(_e) \ + (led_id_valid((_e))) + +/** led_id_map table. */ +extern aim_map_si_t led_id_map[]; +/** led_id_desc_map table. */ +extern aim_map_si_t led_id_desc_map[]; + +/** led_oid */ +typedef enum led_oid_e { + LED_OID_LED1 = ONLP_LED_ID_CREATE(1), + LED_OID_LED2 = ONLP_LED_ID_CREATE(2), + LED_OID_LED3 = ONLP_LED_ID_CREATE(3), + LED_OID_LED4 = ONLP_LED_ID_CREATE(4), +} led_oid_t; + +/** Enum names. */ +const char* led_oid_name(led_oid_t e); + +/** Enum values. */ +int led_oid_value(const char* str, led_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* led_oid_desc(led_oid_t e); + +/** Enum validator. */ +int led_oid_valid(led_oid_t e); + +/** validator */ +#define LED_OID_VALID(_e) \ + (led_oid_valid((_e))) + +/** led_oid_map table. */ +extern aim_map_si_t led_oid_map[]; +/** led_oid_desc_map table. */ +extern aim_map_si_t led_oid_desc_map[]; + +/** psu_id */ +typedef enum psu_id_e { + PSU_ID_PSU1 = 1, + PSU_ID_PSU2 = 2, +} psu_id_t; + +/** Enum names. */ +const char* psu_id_name(psu_id_t e); + +/** Enum values. */ +int psu_id_value(const char* str, psu_id_t* e, int substr); + +/** Enum descriptions. */ +const char* psu_id_desc(psu_id_t e); + +/** Enum validator. */ +int psu_id_valid(psu_id_t e); + +/** validator */ +#define PSU_ID_VALID(_e) \ + (psu_id_valid((_e))) + +/** psu_id_map table. */ +extern aim_map_si_t psu_id_map[]; +/** psu_id_desc_map table. */ +extern aim_map_si_t psu_id_desc_map[]; + +/** psu_oid */ +typedef enum psu_oid_e { + PSU_OID_PSU1 = ONLP_PSU_ID_CREATE(1), + PSU_OID_PSU2 = ONLP_PSU_ID_CREATE(2), +} psu_oid_t; + +/** Enum names. */ +const char* psu_oid_name(psu_oid_t e); + +/** Enum values. */ +int psu_oid_value(const char* str, psu_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* psu_oid_desc(psu_oid_t e); + +/** Enum validator. */ +int psu_oid_valid(psu_oid_t e); + +/** validator */ +#define PSU_OID_VALID(_e) \ + (psu_oid_valid((_e))) + +/** psu_oid_map table. */ +extern aim_map_si_t psu_oid_map[]; +/** psu_oid_desc_map table. */ +extern aim_map_si_t psu_oid_desc_map[]; + +/** thermal_id */ +typedef enum thermal_id_e { + THERMAL_ID_THERMAL1 = 1, + THERMAL_ID_THERMAL2 = 2, + THERMAL_ID_THERMAL3 = 3, + THERMAL_ID_THERMAL4 = 4, + THERMAL_ID_THERMAL5 = 5, + THERMAL_ID_THERMAL6 = 6, + THERMAL_ID_THERMAL7 = 7, +} thermal_id_t; + +/** Enum names. */ +const char* thermal_id_name(thermal_id_t e); + +/** Enum values. */ +int thermal_id_value(const char* str, thermal_id_t* e, int substr); + +/** Enum descriptions. */ +const char* thermal_id_desc(thermal_id_t e); + +/** Enum validator. */ +int thermal_id_valid(thermal_id_t e); + +/** validator */ +#define THERMAL_ID_VALID(_e) \ + (thermal_id_valid((_e))) + +/** thermal_id_map table. */ +extern aim_map_si_t thermal_id_map[]; +/** thermal_id_desc_map table. */ +extern aim_map_si_t thermal_id_desc_map[]; + +/** thermal_oid */ +typedef enum thermal_oid_e { + THERMAL_OID_THERMAL1 = ONLP_THERMAL_ID_CREATE(1), + THERMAL_OID_THERMAL2 = ONLP_THERMAL_ID_CREATE(2), + THERMAL_OID_THERMAL3 = ONLP_THERMAL_ID_CREATE(3), + THERMAL_OID_THERMAL4 = ONLP_THERMAL_ID_CREATE(4), + THERMAL_OID_THERMAL5 = ONLP_THERMAL_ID_CREATE(5), + THERMAL_OID_THERMAL6 = ONLP_THERMAL_ID_CREATE(6), + THERMAL_OID_THERMAL7 = ONLP_THERMAL_ID_CREATE(7), +} thermal_oid_t; + +/** Enum names. */ +const char* thermal_oid_name(thermal_oid_t e); + +/** Enum values. */ +int thermal_oid_value(const char* str, thermal_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* thermal_oid_desc(thermal_oid_t e); + +/** Enum validator. */ +int thermal_oid_valid(thermal_oid_t e); + +/** validator */ +#define THERMAL_OID_VALID(_e) \ + (thermal_oid_valid((_e))) + +/** thermal_oid_map table. */ +extern aim_map_si_t thermal_oid_map[]; +/** thermal_oid_desc_map table. */ +extern aim_map_si_t thermal_oid_desc_map[]; +/* */ + +/* psu info table */ +struct psu_info_s { + char path[PATH_MAX]; + int present; + int busno; + int addr; +}; + +#define SYS_HWMON1_PREFIX "/sys/class/hwmon/hwmon1/device" +#define SYS_HWMON2_PREFIX "/sys/class/hwmon/hwmon2/device" + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c new file mode 100755 index 00000000..c465bdec --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_netberg_aurora_420_rangeley_log.h" +/* + * x86_64_netberg_aurora_420_rangeley log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h new file mode 100755 index 00000000..e3724e3f --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_netberg_aurora_420_rangeley +#include + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c new file mode 100755 index 00000000..1924d1a6 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +static int +datatypes_init__(void) +{ +#define X86_64_NETBERG_AURORA_420_RANGELEY_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_netberg_aurora_420_rangeley_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c new file mode 100755 index 00000000..5bfdc4cd --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_netberg_aurora_420_rangeley_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_netberg_aurora_420_rangeley) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_netberg_aurora_420_rangeley_ucli_module__ = + { + "x86_64_netberg_aurora_420_rangeley_ucli", + NULL, + x86_64_netberg_aurora_420_rangeley_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_netberg_aurora_420_rangeley_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_netberg_aurora_420_rangeley_ucli_module__); + n = ucli_node_create("x86_64_netberg_aurora_420_rangeley", NULL, &x86_64_netberg_aurora_420_rangeley_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_netberg_aurora_420_rangeley")); + return n; +} + +#else +void* +x86_64_netberg_aurora_420_rangeley_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml new file mode 100755 index 00000000..ad4b02d5 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=netberg BASENAME=x86-64-netberg-aurora-420-rangeley REVISION=r0 diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml new file mode 100755 index 00000000..ad855b37 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AURORA 420 +# +###################################################################### + +x86-64-netberg-aurora-420-rangeley-r0: + + grub: + + serial: >- + --port=0x2f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + console=ttyS1,115200n8 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py new file mode 100644 index 00000000..94949cd7 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py @@ -0,0 +1,12 @@ +from onl.platform.base import * +from onl.platform.netberg import * + +class OnlPlatform_x86_64_netberg_aurora_420_rangeley_r0(OnlPlatformNetberg, + OnlPlatformPortConfig_48x10_6x40): + PLATFORM='x86-64-netberg-aurora-420-rangeley-r0' + MODEL="AURORA420" + SYS_OBJECT_ID=".420.1" + + def baseconfig(self): + self.insmod("hardware_monitor") + return True diff --git a/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/PKG.yml b/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/PKG.yml index d6ef2795..66afda3b 100644 --- a/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/PKG.yml +++ b/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=qemu BASENAME=arm-qemu-armv7a REVISION=r0 +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=qemu BASENAME=arm-qemu-armv7a REVISION=r0 DISTS=jessie diff --git a/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/src/lib/arm-qemu-armv7a-r0.yml b/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/src/lib/arm-qemu-armv7a-r0.yml index 0620cb71..debda83c 100644 --- a/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/src/lib/arm-qemu-armv7a-r0.yml +++ b/packages/platforms/qemu/arm/arm-qemu-armv7a/platform-config/r0/src/lib/arm-qemu-armv7a-r0.yml @@ -15,7 +15,7 @@ arm-qemu-armv7a-r0: =: accton_as4610_54.dtb <<: *arm-iproc-kernel-package itb: - <<: *arm-itb + <<: *armel-itb loader: diff --git a/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol b/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol index e38e15ee..bc8dff27 100644 --- a/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol +++ b/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol @@ -5,12 +5,12 @@ ############################################################ INTERVAL=10 -DEVPATH=hwmon0=devices/soc.0/ffe03000.i2c/i2c-0/i2c-4/4-002e -DEVNAME=hwmon0=quanta_ly_hwmon -FCTEMPS=hwmon0/device/pwm1=hwmon0/device/temp1_input hwmon0/device/pwm2=hwmon0/device/temp1_input hwmon0/device/pwm3=hwmon0/device/temp1_input hwmon0/device/pwm4=hwmon0/device/temp1_input -FCFANS=hwmon0/device/pwm1=hwmon0/device/fan1_input hwmon0/device/pwm2=hwmon0/device/fan2_input hwmon0/device/pwm3=hwmon0/device/fan3_input hwmon0/device/pwm4=hwmon0/device/fan4_input -MINTEMP=hwmon0/device/pwm1=20 hwmon0/device/pwm2=20 hwmon0/device/pwm3=20 hwmon0/device/pwm4=20 -MAXTEMP=hwmon0/device/pwm1=60 hwmon0/device/pwm2=60 hwmon0/device/pwm3=60 hwmon0/device/pwm4=60 -MINSTART=hwmon0/device/pwm1=150 hwmon0/device/pwm2=150 hwmon0/device/pwm3=150 hwmon0/device/pwm4=150 -MINSTOP=hwmon0/device/pwm1=0 hwmon0/device/pwm2=0 hwmon0/device/pwm3=0 hwmon0/device/pwm4=0 -MAXPWM=hwmon0/device/pwm1=254 hwmon0/device/pwm2=254 hwmon0/device/pwm3=254 hwmon0/device/pwm4=254 +DEVPATH=hwmon2=devices/soc@ffe00000/ffe03000.i2c/i2c-0/i2c-4/4-002e +DEVNAME=hwmon2=quanta_ly_hwmon +FCTEMPS=hwmon2/device/pwm1=hwmon2/device/temp1_input hwmon2/device/pwm2=hwmon2/device/temp1_input hwmon2/device/pwm3=hwmon2/device/temp1_input hwmon2/device/pwm4=hwmon2/device/temp1_input +FCFANS=hwmon2/device/pwm1=hwmon2/device/fan1_input hwmon2/device/pwm2=hwmon2/device/fan2_input hwmon2/device/pwm3=hwmon2/device/fan3_input hwmon2/device/pwm4=hwmon2/device/fan4_input +MINTEMP=hwmon2/device/pwm1=20 hwmon2/device/pwm2=20 hwmon2/device/pwm3=20 hwmon2/device/pwm4=20 +MAXTEMP=hwmon2/device/pwm1=60 hwmon2/device/pwm2=60 hwmon2/device/pwm3=60 hwmon2/device/pwm4=60 +MINSTART=hwmon2/device/pwm1=150 hwmon2/device/pwm2=150 hwmon2/device/pwm3=150 hwmon2/device/pwm4=150 +MINSTOP=hwmon2/device/pwm1=0 hwmon2/device/pwm2=0 hwmon2/device/pwm3=0 hwmon2/device/pwm4=0 +MAXPWM=hwmon2/device/pwm1=254 hwmon2/device/pwm2=254 hwmon2/device/pwm3=254 hwmon2/device/pwm4=254 diff --git a/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol.b2f b/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol.b2f index c3a6a067..6b4befac 100644 --- a/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol.b2f +++ b/packages/platforms/quanta/powerpc/powerpc-quanta-ly2/platform-config/r0/src/lib/etc/fancontrol.b2f @@ -5,12 +5,12 @@ ############################################################ INTERVAL=10 -DEVPATH=hwmon0=devices/soc.0/ffe03000.i2c/i2c-0/i2c-4/4-002e -DEVNAME=hwmon0=quanta_ly_hwmon -FCTEMPS=hwmon0/device/pwm5=hwmon0/device/temp1_input hwmon0/device/pwm6=hwmon0/device/temp1_input hwmon0/device/pwm7=hwmon0/device/temp1_input hwmon0/device/pwm8=hwmon0/device/temp1_input -FCFANS=hwmon0/device/pwm5=hwmon0/device/fan5_input hwmon0/device/pwm6=hwmon0/device/fan6_input hwmon0/device/pwm7=hwmon0/device/fan7_input hwmon0/device/pwm8=hwmon0/device/fan8_input -MINTEMP=hwmon0/device/pwm5=20 hwmon0/device/pwm6=20 hwmon0/device/pwm7=20 hwmon0/device/pwm8=20 -MAXTEMP=hwmon0/device/pwm5=60 hwmon0/device/pwm6=60 hwmon0/device/pwm7=60 hwmon0/device/pwm8=60 -MINSTART=hwmon0/device/pwm5=150 hwmon0/device/pwm6=150 hwmon0/device/pwm7=150 hwmon0/device/pwm8=150 -MINSTOP=hwmon0/device/pwm5=0 hwmon0/device/pwm6=0 hwmon0/device/pwm7=0 hwmon0/device/pwm8=0 -MAXPWM=hwmon0/device/pwm5=254 hwmon0/device/pwm6=254 hwmon0/device/pwm7=254 hwmon0/device/pwm8=254 +DEVPATH=hwmon2=devices/soc@ffe00000/ffe03000.i2c/i2c-0/i2c-4/4-002e +DEVNAME=hwmon2=quanta_ly_hwmon +FCTEMPS=hwmon2/device/pwm5=hwmon2/device/temp1_input hwmon2/device/pwm6=hwmon2/device/temp1_input hwmon2/device/pwm7=hwmon2/device/temp1_input hwmon2/device/pwm8=hwmon2/device/temp1_input +FCFANS=hwmon2/device/pwm5=hwmon2/device/fan5_input hwmon2/device/pwm6=hwmon2/device/fan6_input hwmon2/device/pwm7=hwmon2/device/fan7_input hwmon2/device/pwm8=hwmon2/device/fan8_input +MINTEMP=hwmon2/device/pwm5=20 hwmon2/device/pwm6=20 hwmon2/device/pwm7=20 hwmon2/device/pwm8=20 +MAXTEMP=hwmon2/device/pwm5=60 hwmon2/device/pwm6=60 hwmon2/device/pwm7=60 hwmon2/device/pwm8=60 +MINSTART=hwmon2/device/pwm5=150 hwmon2/device/pwm6=150 hwmon2/device/pwm7=150 hwmon2/device/pwm8=150 +MINSTOP=hwmon2/device/pwm5=0 hwmon2/device/pwm6=0 hwmon2/device/pwm7=0 hwmon2/device/pwm8=0 +MAXPWM=hwmon2/device/pwm5=254 hwmon2/device/pwm6=254 hwmon2/device/pwm7=254 hwmon2/device/pwm8=254 diff --git a/packages/platforms/quanta/x86-64/modules/builds/optoe.c b/packages/platforms/quanta/x86-64/modules/builds/optoe.c deleted file mode 100644 index 27d7ffbd..00000000 --- a/packages/platforms/quanta/x86-64/modules/builds/optoe.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * optoe.c - A driver to read and write the EEPROM on optical transceivers - * (SFP, QSFP and similar I2C based devices) - * - * Copyright (C) 2014 Cumulus networks Inc. - * Copyright (C) 2017 Finisar Corp. - * Copyright (C) 2017 Quanta - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Freeoftware Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/* - * Description: - * a) Optical transceiver EEPROM read/write transactions are just like - * the at24 eeproms managed by the at24.c i2c driver - * b) The register/memory layout is up to 256 128 byte pages defined by - * a "pages valid" register and switched via a "page select" - * register as explained in below diagram. - * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 - * bytes of address space, and always references the same - * location, independent of the page select register. - * All mapped pages are mapped into the upper 128 bytes - * (offset 128-255) of the i2c address. - * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 - * (A0h in the spec), and map all pages in the upper 128 bytes - * of that address. - * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data - * at I2C address 0x50, and 256 bytes of data at I2C address - * 0x51 (A2h in the spec). Page selection and paged access - * only apply to this second I2C address (0x51). - * e) The address space is presented, by the driver, as a linear - * address space. For devices with one I2C client at address - * 0x50 (eg QSFP), offset 0-127 are in the lower - * half of address 50/A0h/client[0]. Offset 128-255 are in - * page 0, 256-383 are page 1, etc. More generally, offset - * 'n' resides in page (n/128)-1. ('page -1' is the lower - * half, offset 0-127). - * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), - * the address space places offset 0-127 in the lower - * half of 50/A0/client[0], offset 128-255 in the upper - * half. Offset 256-383 is in the lower half of 51/A2/client[1]. - * Offset 384-511 is in page 0, in the upper half of 51/A2/... - * Offset 512-639 is in page 1, in the upper half of 51/A2/... - * Offset 'n' is in page (n/128)-3 (for n > 383) - * - * One I2c addressed (eg QSFP) Memory Map - * - * 2-Wire Serial Address: 1010000x - * - * Lower Page 00h (128 bytes) - * ===================== - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * |Page Select Byte(127)| - * ===================== - * | - * | - * | - * | - * V - * ------------------------------------------------------------ - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * V V V V - * ------------ -------------- --------------- -------------- - * | | | | | | | | - * | Upper | | Upper | | Upper | | Upper | - * | Page 00h | | Page 01h | | Page 02h | | Page 03h | - * | | | (Optional) | | (Optional) | | (Optional | - * | | | | | | | for Cable | - * | | | | | | | Assemblies) | - * | ID | | AST | | User | | | - * | Fields | | Table | | EEPROM Data | | | - * | | | | | | | | - * | | | | | | | | - * | | | | | | | | - * ------------ -------------- --------------- -------------- - * - * The SFF 8436 (QSFP) spec only defines the 4 pages described above. - * In anticipation of future applications and devices, this driver - * supports access to the full architected range, 256 pages. - * - **/ - -/* #define DEBUG 1 */ - -#undef EEPROM_CLASS -#ifdef CONFIG_EEPROM_CLASS -#define EEPROM_CLASS -#endif -#ifdef CONFIG_EEPROM_CLASS_MODULE -#define EEPROM_CLASS -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef EEPROM_CLASS -#include -#endif - -#include - -/* - * The optoe driver is for read/write access to the EEPROM on standard - * I2C based optical transceivers (SFP, QSFP, etc) - * - * While based on the at24 driver, it eliminates code that supports other - * types of I2C EEPROMs, and adds support for pages accessed through the - * page-select register at offset 127. - */ - -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - - void (*setup)(struct memory_accessor *, void *context); - void *context; -#ifdef EEPROM_CLASS - struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ -#endif - int oom_port_name; -}; - -/* fundamental unit of addressing for EEPROM */ -#define OPTOE_PAGE_SIZE 128 -/* - * Single address devices (eg QSFP) have 256 pages, plus the unpaged - * low 128 bytes. If the device does not support paging, it is - * only 2 'pages' long. - */ -#define OPTOE_ARCH_PAGES 256 -#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) -/* - * Dual address devices (eg SFP) have 256 pages, plus the unpaged - * low 128 bytes, plus 256 bytes at 0x50. If the device does not - * support paging, it is 4 'pages' long. - */ -#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define OPTOE_PAGE_SELECT_REG 0x7F -#define ONE_ADDR_PAGEABLE_REG 0x02 -#define ONE_ADDR_NOT_PAGEABLE (1<<2) -#define TWO_ADDR_PAGEABLE_REG 0x40 -#define TWO_ADDR_PAGEABLE (1<<4) -#define OPTOE_ID_REG 0 - -/* The maximum length of a port name */ -#define MAX_PORT_NAME_LEN 20 -struct optoe_data { - struct optoe_platform_data chip; - struct memory_accessor macc; - int use_smbus; - char port_name[MAX_PORT_NAME_LEN]; - - /* - * Lock protects against activities from other Linux tasks, - * but not from changes by other I2C masters. - */ - struct mutex lock; - struct bin_attribute bin; - struct attribute_group attr_group; - - u8 *writebuf; - unsigned write_max; - - unsigned num_addresses; - -#ifdef EEPROM_CLASS - struct eeprom_device *eeprom_dev; -#endif - - /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ - int dev_class; - - struct i2c_client *client[]; -}; - -typedef enum optoe_opcode { - OPTOE_READ_OP = 0, - OPTOE_WRITE_OP = 1 -} optoe_opcode_e; - -/* - * 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 = OPTOE_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; - -/* - * flags to distinguish one-address (QSFP family) from two-address (SFP family) - * If the family is not known, figure it out when the device is accessed - */ -#define ONE_ADDR 1 -#define TWO_ADDR 2 - -static const struct i2c_device_id optoe_ids[] = { - { "optoe1", ONE_ADDR }, - { "optoe2", TWO_ADDR }, - { "sff8436", ONE_ADDR }, - { "24c04", TWO_ADDR }, - { /* END OF LIST */ } -}; -MODULE_DEVICE_TABLE(i2c, optoe_ids); - -/*-------------------------------------------------------------------------*/ -/* - * 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 single address (eg QSFP) and two address (eg SFP). - * 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 optoe_translate_offset(struct optoe_data *optoe, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = optoe->client[0]; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (optoe->dev_class == TWO_ADDR) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = optoe->client[1]; - *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 < OPTOE_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 = OPTOE_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t optoe_eeprom_read(struct optoe_data *optoe, - 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 (optoe->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 (optoe->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 optoe_eeprom_write(struct optoe_data *optoe, - 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 > optoe->write_max) - count = optoe->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (optoe->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 = optoe->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 (optoe->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 optoe_eeprom_update_client(struct optoe_data *optoe, - char *buf, loff_t off, - size_t count, optoe_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - uint8_t page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = optoe_translate_offset(optoe, &phy_offset, &client); - dev_dbg(&client->dev, - "optoe_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 = optoe_eeprom_write(optoe, client, &page, - OPTOE_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 == OPTOE_READ_OP) { - status = optoe_eeprom_read(optoe, client, - buf, phy_offset, count); - } else { - status = optoe_eeprom_write(optoe, 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 = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to 0 failed:%d!\n", ret); - /* error only if nothing has been transferred */ - if (retval == 0) retval = 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 optoe_page_legal(struct optoe_data *optoe, - loff_t off, size_t len) -{ - struct i2c_client *client = optoe->client[0]; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (optoe->dev_class == TWO_ADDR) { - /* SFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= TWO_ADDR_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= TWO_ADDR_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & TWO_ADDR_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = TWO_ADDR_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = TWO_ADDR_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 { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= ONE_ADDR_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - ONE_ADDR_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & ONE_ADDR_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = ONE_ADDR_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - return len; -} - -static ssize_t optoe_read_write(struct optoe_data *optoe, - char *buf, loff_t off, size_t len, optoe_opcode_e opcode) -{ - struct i2c_client *client = optoe->client[0]; - 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; - - dev_dbg(&client->dev, - "optoe_read_write: off %lld len:%ld, opcode:%s\n", - off, (long int) len, (opcode == OPTOE_READ_OP) ? "r": "w"); - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&optoe->lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - status = optoe_page_legal(optoe, off, len); - if (status < 0) { - goto err; - } - len = status; - - /* - * 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 * OPTOE_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = OPTOE_PAGE_SIZE - off; - } else { - chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_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 = optoe_eeprom_update_client(optoe, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "optoe_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(&optoe->lock); - - return retval; - -err: - mutex_unlock(&optoe->lock); - - return status; -} - -static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); -} - - -static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); -} -/*-------------------------------------------------------------------------*/ - -/* - * This lets other kernel code access the eeprom data. For example, it - * might hold a board's Ethernet address, or board-specific calibration - * data generated on the manufacturing floor. - */ - -static ssize_t optoe_macc_read(struct memory_accessor *macc, - char *buf, off_t offset, size_t count) -{ - struct optoe_data *optoe = container_of(macc, - struct optoe_data, macc); - - return optoe_read_write(optoe, buf, offset, count, OPTOE_READ_OP); -} - -static ssize_t optoe_macc_write(struct memory_accessor *macc, - const char *buf, off_t offset, size_t count) -{ - struct optoe_data *optoe = container_of(macc, - struct optoe_data, macc); - - return optoe_read_write(optoe, (char *) buf, offset, - count, OPTOE_WRITE_OP); -} - -/*-------------------------------------------------------------------------*/ - -static int optoe_remove(struct i2c_client *client) -{ - struct optoe_data *optoe; - int i; - - optoe = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); - - for (i = 1; i < optoe->num_addresses; i++) - i2c_unregister_device(optoe->client[i]); - -#ifdef EEPROM_CLASS - eeprom_device_unregister(optoe->eeprom_dev); -#endif - - kfree(optoe->writebuf); - kfree(optoe); - return 0; -} - -static ssize_t show_port_name(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%s\n", optoe->port_name); - mutex_unlock(&optoe->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 optoe_data *optoe = 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(&optoe->lock); - strcpy(optoe->port_name, port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(port_name, S_IRUGO | S_IWUSR, - show_port_name, set_port_name); - -static ssize_t show_dev_class(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%d\n", optoe->dev_class); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_dev_class(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - int dev_class; - - /* - * dev_class is actually the number of sfp ports used, thus - * legal values are "1" (QSFP class) and "2" (SFP class) - */ - if (sscanf(buf, "%d", &dev_class) != 1 || - dev_class < 1 || dev_class > 2) - return -EINVAL; - - mutex_lock(&optoe->lock); - optoe->dev_class = dev_class; - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(dev_class, S_IRUGO | S_IWUSR, - show_dev_class, set_dev_class); - -static struct attribute *optoe_attrs[] = { - &dev_attr_port_name.attr, - &dev_attr_dev_class.attr, - NULL, -}; - -static struct attribute_group optoe_attr_group = { - .attrs = optoe_attrs, -}; - -static int optoe_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - int use_smbus = 0; - struct optoe_platform_data chip; - struct optoe_data *optoe; - int num_addresses = 0; - int i = 0; - - if (client->addr != 0x50) { - dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", - client->addr); - err = -EINVAL; - goto exit; - } - - if (client->dev.platform_data) { - chip = *(struct optoe_platform_data *)client->dev.platform_data; - dev_dbg(&client->dev, "probe, chip provided, flags:0x%x; name: %s\n", chip.flags, client->name); - } else { - if (!id->driver_data) { - err = -ENODEV; - goto exit; - } - dev_dbg(&client->dev, "probe, building chip\n"); - chip.flags = 0; - chip.setup = NULL; - chip.context = NULL; -#ifdef EEPROM_CLASS - chip.eeprom_data = NULL; -#endif - } - - /* 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 { - err = -EPFNOSUPPORT; - goto exit; - } - } - - - /* - * Make room for two i2c clients - */ - num_addresses = 2; - - optoe = kzalloc(sizeof(struct optoe_data) + - num_addresses * sizeof(struct i2c_client *), - GFP_KERNEL); - if (!optoe) { - err = -ENOMEM; - goto exit; - } - - mutex_init(&optoe->lock); - - /* determine whether this is a one-address or two-address module */ - if ((strcmp(client->name, "optoe1") == 0) || - (strcmp(client->name, "sff8436") == 0)) { - /* one-address (eg QSFP) family */ - optoe->dev_class = ONE_ADDR; - chip.byte_len = ONE_ADDR_EEPROM_SIZE; - num_addresses = 1; - } else if ((strcmp(client->name, "optoe2") == 0) || - (strcmp(client->name, "24c04") == 0)) { - /* SFP family */ - optoe->dev_class = TWO_ADDR; - chip.byte_len = TWO_ADDR_EEPROM_SIZE; - } else { /* those were the only two choices */ - err = -EINVAL; - goto exit; - } - - dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); - optoe->use_smbus = use_smbus; - optoe->chip = chip; - optoe->num_addresses = num_addresses; - - /* - * Use platform data to initial port name. - * Original port name is unitialized: strcpy(optoe->port_name, "unitialized"); - */ - sprintf(optoe->port_name, "%d", chip.oom_port_name); - - /* - * 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(&optoe->bin); - optoe->bin.attr.name = "eeprom"; - optoe->bin.attr.mode = S_IRUGO; - optoe->bin.read = optoe_bin_read; - optoe->bin.size = chip.byte_len; - - optoe->macc.read = optoe_macc_read; - - if (!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; - - optoe->macc.write = optoe_macc_write; - - optoe->bin.write = optoe_bin_write; - optoe->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; - optoe->write_max = write_max; - - /* buffer (data + address at the beginning) */ - optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!optoe->writebuf) { - err = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - optoe->client[0] = client; - - /* use a dummy I2C device for two-address chips */ - for (i = 1; i < num_addresses; i++) { - optoe->client[i] = i2c_new_dummy(client->adapter, - client->addr + i); - if (!optoe->client[i]) { - dev_err(&client->dev, "address 0x%02x unavailable\n", - client->addr + i); - err = -EADDRINUSE; - goto err_struct; - } - } - - /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); - if (err) - goto err_struct; - - optoe->attr_group = optoe_attr_group; - - err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); - if (err) { - dev_err(&client->dev, "failed to create sysfs attribute group.\n"); - goto err_struct; - } -#ifdef EEPROM_CLASS - optoe->eeprom_dev = eeprom_device_register(&client->dev, - chip.eeprom_data); - if (IS_ERR(optoe->eeprom_dev)) { - dev_err(&client->dev, "error registering eeprom device.\n"); - err = PTR_ERR(optoe->eeprom_dev); - goto err_sysfs_cleanup; - } -#endif - - i2c_set_clientdata(client, optoe); - - dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", - optoe->bin.size, client->name, - optoe->bin.write ? "read/write" : "read-only"); - - if (use_smbus == I2C_SMBUS_WORD_DATA || - use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } - - if (chip.setup) - chip.setup(&optoe->macc, chip.context); - - return 0; - -#ifdef EEPROM_CLASS -err_sysfs_cleanup: - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); -#endif - -err_struct: - for (i = 1; i < num_addresses; i++) { - if (optoe->client[i]) - i2c_unregister_device(optoe->client[i]); - } - - kfree(optoe->writebuf); -exit_kfree: - kfree(optoe); -exit: - dev_dbg(&client->dev, "probe error %d\n", err); - - return err; -} - -/*-------------------------------------------------------------------------*/ - -static struct i2c_driver optoe_driver = { - .driver = { - .name = "optoe", - .owner = THIS_MODULE, - }, - .probe = optoe_probe, - .remove = optoe_remove, - .id_table = optoe_ids, -}; - -static int __init optoe_init(void) -{ - - if (!io_limit) { - pr_err("optoe: io_limit must not be 0!\n"); - return -EINVAL; - } - - io_limit = rounddown_pow_of_two(io_limit); - return i2c_add_driver(&optoe_driver); -} -module_init(optoe_init); - -static void __exit optoe_exit(void) -{ - i2c_del_driver(&optoe_driver); -} -module_exit(optoe_exit); - -MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); -MODULE_AUTHOR("Jonathan Tsai "); -MODULE_LICENSE("GPL"); diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c old mode 100644 new mode 100755 index d7e12b68..66018dde --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c @@ -78,7 +78,6 @@ struct i2c_init_data { int busno; int gpio_base; char name[I2C_NAME_SIZE]; - int oom_port_name; }; static struct i2c_init_data quanta_ly8_i2c_init_data[] = { @@ -99,54 +98,54 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { { .parent_bus = (0x10 + 0), .type = i2c_type_pca9554, .addr = 0x25, .name = "PCA9554(PCA9698INT)\0" }, { .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_3(FAN)\0" }, { .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_4(QSFP_EN)\0" }, - { .parent_bus = (0x20 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_1_EEPROM\0", .oom_port_name = 1 }, - { .parent_bus = (0x20 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_2_EEPROM\0", .oom_port_name = 2 }, - { .parent_bus = (0x20 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_3_EEPROM\0", .oom_port_name = 3 }, - { .parent_bus = (0x20 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_4_EEPROM\0", .oom_port_name = 4 }, - { .parent_bus = (0x20 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_5_EEPROM\0", .oom_port_name = 5 }, - { .parent_bus = (0x20 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_6_EEPROM\0", .oom_port_name = 6 }, - { .parent_bus = (0x20 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_7_EEPROM\0", .oom_port_name = 7 }, - { .parent_bus = (0x20 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_8_EEPROM\0", .oom_port_name = 8 }, - { .parent_bus = (0x28 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_9_EEPROM\0", .oom_port_name = 9 }, - { .parent_bus = (0x28 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_10_EEPROM\0", .oom_port_name = 10 }, - { .parent_bus = (0x28 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_11_EEPROM\0", .oom_port_name = 11 }, - { .parent_bus = (0x28 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_12_EEPROM\0", .oom_port_name = 12 }, - { .parent_bus = (0x28 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_13_EEPROM\0", .oom_port_name = 13 }, - { .parent_bus = (0x28 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_14_EEPROM\0", .oom_port_name = 14 }, - { .parent_bus = (0x28 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_15_EEPROM\0", .oom_port_name = 15 }, - { .parent_bus = (0x28 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_16_EEPROM\0", .oom_port_name = 16 }, - { .parent_bus = (0x30 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_17_EEPROM\0", .oom_port_name = 17 }, - { .parent_bus = (0x30 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_18_EEPROM\0", .oom_port_name = 18 }, - { .parent_bus = (0x30 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_19_EEPROM\0", .oom_port_name = 19 }, - { .parent_bus = (0x30 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_20_EEPROM\0", .oom_port_name = 20 }, - { .parent_bus = (0x30 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_21_EEPROM\0", .oom_port_name = 21 }, - { .parent_bus = (0x30 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_22_EEPROM\0", .oom_port_name = 22 }, - { .parent_bus = (0x30 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_23_EEPROM\0", .oom_port_name = 23 }, - { .parent_bus = (0x30 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_24_EEPROM\0", .oom_port_name = 24 }, - { .parent_bus = (0x38 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_25_EEPROM\0", .oom_port_name = 25 }, - { .parent_bus = (0x38 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_26_EEPROM\0", .oom_port_name = 26 }, - { .parent_bus = (0x38 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_27_EEPROM\0", .oom_port_name = 27 }, - { .parent_bus = (0x38 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_28_EEPROM\0", .oom_port_name = 28 }, - { .parent_bus = (0x38 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_29_EEPROM\0", .oom_port_name = 29 }, - { .parent_bus = (0x38 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_30_EEPROM\0", .oom_port_name = 30 }, - { .parent_bus = (0x38 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_31_EEPROM\0", .oom_port_name = 31 }, - { .parent_bus = (0x38 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_32_EEPROM\0", .oom_port_name = 32 }, - { .parent_bus = (0x40 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_33_EEPROM\0", .oom_port_name = 33 }, - { .parent_bus = (0x40 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_34_EEPROM\0", .oom_port_name = 34 }, - { .parent_bus = (0x40 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_35_EEPROM\0", .oom_port_name = 35 }, - { .parent_bus = (0x40 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_36_EEPROM\0", .oom_port_name = 36 }, - { .parent_bus = (0x40 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_37_EEPROM\0", .oom_port_name = 37 }, - { .parent_bus = (0x40 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_38_EEPROM\0", .oom_port_name = 38 }, - { .parent_bus = (0x40 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_39_EEPROM\0", .oom_port_name = 39 }, - { .parent_bus = (0x40 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_40_EEPROM\0", .oom_port_name = 40 }, - { .parent_bus = (0x48 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_41_EEPROM\0", .oom_port_name = 41 }, - { .parent_bus = (0x48 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_42_EEPROM\0", .oom_port_name = 42 }, - { .parent_bus = (0x48 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_43_EEPROM\0", .oom_port_name = 43 }, - { .parent_bus = (0x48 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_44_EEPROM\0", .oom_port_name = 44 }, - { .parent_bus = (0x48 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_45_EEPROM\0", .oom_port_name = 45 }, - { .parent_bus = (0x48 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_46_EEPROM\0", .oom_port_name = 46 }, - { .parent_bus = (0x48 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_47_EEPROM\0", .oom_port_name = 47 }, - { .parent_bus = (0x48 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_48_EEPROM\0", .oom_port_name = 48 }, + { .parent_bus = (0x20 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_1_EEPROM\0" }, + { .parent_bus = (0x20 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_2_EEPROM\0" }, + { .parent_bus = (0x20 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_3_EEPROM\0" }, + { .parent_bus = (0x20 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_4_EEPROM\0" }, + { .parent_bus = (0x20 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_5_EEPROM\0" }, + { .parent_bus = (0x20 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_6_EEPROM\0" }, + { .parent_bus = (0x20 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_7_EEPROM\0" }, + { .parent_bus = (0x20 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_8_EEPROM\0" }, + { .parent_bus = (0x28 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_9_EEPROM\0" }, + { .parent_bus = (0x28 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_10_EEPROM\0" }, + { .parent_bus = (0x28 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_11_EEPROM\0" }, + { .parent_bus = (0x28 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_12_EEPROM\0" }, + { .parent_bus = (0x28 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_13_EEPROM\0" }, + { .parent_bus = (0x28 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_14_EEPROM\0" }, + { .parent_bus = (0x28 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_15_EEPROM\0" }, + { .parent_bus = (0x28 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_16_EEPROM\0" }, + { .parent_bus = (0x30 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_17_EEPROM\0" }, + { .parent_bus = (0x30 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_18_EEPROM\0" }, + { .parent_bus = (0x30 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_19_EEPROM\0" }, + { .parent_bus = (0x30 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_20_EEPROM\0" }, + { .parent_bus = (0x30 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_21_EEPROM\0" }, + { .parent_bus = (0x30 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_22_EEPROM\0" }, + { .parent_bus = (0x30 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_23_EEPROM\0" }, + { .parent_bus = (0x30 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_24_EEPROM\0" }, + { .parent_bus = (0x38 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_25_EEPROM\0" }, + { .parent_bus = (0x38 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_26_EEPROM\0" }, + { .parent_bus = (0x38 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_27_EEPROM\0" }, + { .parent_bus = (0x38 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_28_EEPROM\0" }, + { .parent_bus = (0x38 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_29_EEPROM\0" }, + { .parent_bus = (0x38 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_30_EEPROM\0" }, + { .parent_bus = (0x38 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_31_EEPROM\0" }, + { .parent_bus = (0x38 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_32_EEPROM\0" }, + { .parent_bus = (0x40 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_33_EEPROM\0" }, + { .parent_bus = (0x40 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_34_EEPROM\0" }, + { .parent_bus = (0x40 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_35_EEPROM\0" }, + { .parent_bus = (0x40 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_36_EEPROM\0" }, + { .parent_bus = (0x40 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_37_EEPROM\0" }, + { .parent_bus = (0x40 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_38_EEPROM\0" }, + { .parent_bus = (0x40 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_39_EEPROM\0" }, + { .parent_bus = (0x40 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_40_EEPROM\0" }, + { .parent_bus = (0x48 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_41_EEPROM\0" }, + { .parent_bus = (0x48 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_42_EEPROM\0" }, + { .parent_bus = (0x48 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_43_EEPROM\0" }, + { .parent_bus = (0x48 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_44_EEPROM\0" }, + { .parent_bus = (0x48 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_45_EEPROM\0" }, + { .parent_bus = (0x48 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_46_EEPROM\0" }, + { .parent_bus = (0x48 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_47_EEPROM\0" }, + { .parent_bus = (0x48 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_48_EEPROM\0" }, { .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x23, .name = "PCA9698(SFP_1-8)\0" }, { .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x21, .name = "PCA9698(SFP_9-16)\0" }, @@ -156,10 +155,10 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { { .parent_bus = (0x10 + 4), .type = i2c_type_pca9698, .addr = 0x25, .name = "PCA9698(SFP_41-48)\0" }, { .parent_bus = (0x10 + 5), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x50, .name = "PCA9548_8\0" }, - { .parent_bus = (0x50 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_1_EEPROM\0", .oom_port_name = 49 }, - { .parent_bus = (0x50 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_2_EEPROM\0", .oom_port_name = 50 }, - { .parent_bus = (0x50 + 2), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_3_EEPROM\0", .oom_port_name = 51 }, - { .parent_bus = (0x50 + 3), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_4_EEPROM\0", .oom_port_name = 52 }, + { .parent_bus = (0x50 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_1_EEPROM\0" }, + { .parent_bus = (0x50 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_2_EEPROM\0" }, + { .parent_bus = (0x50 + 2), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_3_EEPROM\0" }, + { .parent_bus = (0x50 + 3), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_4_EEPROM\0" }, { .parent_bus = (0x10 + 5), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_1(LED)\0" }, { .parent_bus = (0x10 + 6), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_2(QSFP)\0" }, @@ -167,8 +166,8 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { /* QSFP+ DB */ { .parent_bus = (0x10 + 7), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555(QDB)\0" }, { .parent_bus = (0x10 + 7), .type = i2c_type_pca9546, .addr = 0x76, .busno = 0x58, .name = "PCA9546(QDB)\0" }, - { .parent_bus = (0x58 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_1_EEPROM\0", .oom_port_name = 53 }, - { .parent_bus = (0x58 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_2_EEPROM\0", .oom_port_name = 54 }, + { .parent_bus = (0x58 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_1_EEPROM\0" }, + { .parent_bus = (0x58 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_2_EEPROM\0" }, { .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x72, .busno = 0x18, .name = "PCA9546\0" }, { .parent_bus = (0x18 + 0), .type = i2c_type_emerson700, .addr = 0x6f, .name = "PSU_1\0" }, /* RPSU 1 */ @@ -249,31 +248,9 @@ static inline struct pca953x_platform_data *pca953x_platform_data_get(int type, return &platform_data; } -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - - void (*setup)(struct memory_accessor *, void *context); - void *context; - - int oom_port_name; -}; - -static inline struct optoe_platform_data *optoe_platform_data_get(int port_name) { - static struct optoe_platform_data platform_data; - - platform_data = (struct optoe_platform_data) { - .oom_port_name = port_name, - }; - - return &platform_data; -} - static inline struct i2c_board_info *i2c_board_info_get(struct i2c_init_data data) { struct pca954x_platform_data *mux_platform_data; struct pca953x_platform_data *gpio_platform_data; - struct optoe_platform_data *oom_platform_data; static struct i2c_board_info board_info; switch(data.type) { @@ -303,16 +280,6 @@ static inline struct i2c_board_info *i2c_board_info_get(struct i2c_init_data dat break; case i2c_type_optoe1_QSFP: case i2c_type_optoe2_SFP: - oom_platform_data = optoe_platform_data_get(data.oom_port_name); - if(oom_platform_data == NULL) { - return (struct i2c_board_info *) NULL; - } - - board_info = (struct i2c_board_info) { - .platform_data = oom_platform_data, - }; - break; - case i2c_type_rtc: case i2c_type_spd: case i2c_type_24c02: diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py old mode 100644 new mode 100755 index 268c0d5f..ef3c38e2 --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py @@ -25,4 +25,14 @@ class OnlPlatform_x86_64_quanta_ly8_rangeley_r0(OnlPlatformQuanta, os.system("ln -snf /dev/rtc1 /dev/rtc") os.system("hwclock --hctosys") + #SFP for 1~48 port + #QSFP for 49~52 port + for port_number in range(1,53): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + #QDB QSFP 53~54port + os.system("echo 53 >/sys/bus/i2c/devices/88-0050/port_name") + os.system("echo 54 >/sys/bus/i2c/devices/89-0050/port_name") + return True diff --git a/sm/bigcode b/sm/bigcode index 3a0ca236..d9655572 160000 --- a/sm/bigcode +++ b/sm/bigcode @@ -1 +1 @@ -Subproject commit 3a0ca236ecba75278dffa31c7c4c91a9be2285f4 +Subproject commit d965557236c81cc2f047d94ac79eab39da16524b diff --git a/sm/build-artifacts b/sm/build-artifacts index 48603f21..aa92be2f 160000 --- a/sm/build-artifacts +++ b/sm/build-artifacts @@ -1 +1 @@ -Subproject commit 48603f21bc4e764317ae890444229c76ef2d1f8f +Subproject commit aa92be2faa3a4b3822bedeecd6d756e7755ed8ed diff --git a/sm/infra b/sm/infra index f78cc911..168b695e 160000 --- a/sm/infra +++ b/sm/infra @@ -1 +1 @@ -Subproject commit f78cc91121bf520b48b4888f08e055ed92b9fbf2 +Subproject commit 168b695e51241be2823111f105b129236a1d79f8 diff --git a/tools/flat-image-tree.py b/tools/flat-image-tree.py index 19ad7f9c..c4290daf 100755 --- a/tools/flat-image-tree.py +++ b/tools/flat-image-tree.py @@ -66,7 +66,7 @@ class Image(object): self.wl(""" description = "%s";""" % self.description) self.wl(""" type = "%s";""" % self.type) self.wl(""" data = /incbin/("%s");""" % self.data) - self.wl(""" arch = "%s";""" % ("arm" if ops.arch == 'armel' else ops.arch)) + self.wl(""" arch = "%s";""" % ("arm" if ops.arch in [ 'armel', 'armhf' ] else ops.arch)) self.wl(""" compression = "%s";""" % self.compression) if self.os: self.wl(""" os = %s;""" % self.os) @@ -95,7 +95,7 @@ class KernelImage(Image): if arch == 'powerpc': self.load = "<0x0>" self.entry = "<0x0>" - elif arch == 'armel': + elif arch in [ 'armel', 'armhf' ]: self.load = "<0x61008000>" self.entry = "<0x61008000>" elif arch == 'arm64': @@ -117,7 +117,7 @@ class InitrdImage(Image): if arch == 'powerpc': self.load = "<0x1000000>" self.entry ="<0x1000000>" - elif arch == 'armel': + elif arch in [ 'armel', 'armhf' ]: self.load = "<0x0000000>" self.entry ="<0x0000000>" elif arch == 'arm64': @@ -306,7 +306,7 @@ if __name__ == '__main__': ap.add_argument("--desc", nargs=1, help="Flat Image Tree description", default="ONL Flat Image Tree.") ap.add_argument("--itb", metavar='itb-file', help="Compile result to an image tree blob file.") ap.add_argument("--its", metavar='its-file', help="Write result to an image tree source file.") - ap.add_argument("--arch", choices=['powerpc', 'armel', 'arm64'], required=True) + ap.add_argument("--arch", choices=['powerpc', 'armel', 'armhf', 'arm64'], required=True) ops=ap.parse_args() fit = FlatImageTree(ops.desc) diff --git a/tools/mkinstaller.py b/tools/mkinstaller.py index 9ca57909..d54c805f 100755 --- a/tools/mkinstaller.py +++ b/tools/mkinstaller.py @@ -23,7 +23,7 @@ if ONL is None: sys.exit(1) class InstallerShar(object): - def __init__(self, arch, template=None, work_dir=None): + def __init__(self, onl_version, arch, template=None, work_dir=None): self.ONL = ONL if template is None: @@ -60,6 +60,8 @@ class InstallerShar(object): else: self.setvar("ARCH", self.arch) + self.setvar("ONLVERSION", onl_version) + def abort(self, msg): logger.error(msg) sys.exit(1) @@ -174,8 +176,9 @@ class InstallerShar(object): if __name__ == '__main__': ap = argparse.ArgumentParser(NAME) + ap.add_argument("--onl-version", help="Installer ONL Version.", required=True) ap.add_argument("--arch", help="Installer Architecture.", required=True, - choices = ['amd64', 'powerpc', 'armel', 'arm64']) + choices = ['amd64', 'powerpc', 'armel', 'armhf', 'arm64']) ap.add_argument("--initrd", nargs=2, help="The system initrd.") ap.add_argument("--fit", nargs=2, help="The system FIT image.") ap.add_argument("--boot-config", help="The boot-config source.") @@ -195,7 +198,7 @@ if __name__ == '__main__': help="Specify a Python plugin (runs from within the installer chroot)") ops = ap.parse_args() - installer = InstallerShar(ops.arch, ops.work_dir) + installer = InstallerShar(ops.onl_version, ops.arch, ops.work_dir) if ops.arch == 'amd64': if ops.initrd is None: diff --git a/tools/onl-nos-create.py b/tools/onl-nos-create.py index 2cbdf596..19327c37 100755 --- a/tools/onl-nos-create.py +++ b/tools/onl-nos-create.py @@ -920,6 +920,7 @@ include %(MTOP)s/make/versions/version-%(prefix)s.mk INSTALLER_NAME=$(FNAME_PRODUCT_VERSION)_ONL-OS_$(FNAME_BUILD_ID)_$(UARCH)_$(BOOTMODE)_INSTALLER MKINSTALLER_OPTS := \ + --onl-version "$(VERSION_STRING)" \ --arch $(ARCH) \ --boot-config boot-config \ --swi %(prefix)s-swi:$(ARCH) diff --git a/tools/onlpm.py b/tools/onlpm.py index 4701daed..3b1cf745 100755 --- a/tools/onlpm.py +++ b/tools/onlpm.py @@ -136,8 +136,10 @@ class OnlPackage(object): 'BUILD_DIR' : 'BUILD/%s' % g_dist_codename, # Default Templates Location - 'ONL_TEMPLATES' : "%s/packages/base/any/templates" % os.getenv("ONL") + 'ONL_TEMPLATES' : "%s/packages/base/any/templates" % os.getenv("ONL"), + # Default Distribution + 'DISTS' : g_dist_codename, } ############################################################ @@ -503,6 +505,13 @@ class OnlPackageGroup(object): return False return True + def distcheck(self): + for p in self.packages: + if p.pkg.get("dists", None): + if g_dist_codename not in p.pkg['dists'].split(','): + return False + return True + def prerequisite_packages(self): rv = [] for e in list(onlu.sflatten(self._pkgs.get('prerequisites', {}).get('packages', []))): @@ -863,7 +872,8 @@ class OnlPackageManager(object): pg.filtered = True if not pg.archcheck(arches): pg.filtered = True - + if not pg.distcheck(): + pg.filtered = True def load(self, basedir, usecache=True, rebuildcache=False): pkgspec = [ 'PKG.yml', 'pkg.yml' ] @@ -1089,6 +1099,8 @@ class OnlPackageManager(object): def list_platforms(self, arch): platforms = [] for pg in self.package_groups: + if not pg.distcheck(): + continue for p in pg.packages: (name, pkgArch) = OnlPackage.idparse(p.id()) m = re.match(r'onl-platform-config-(?P.*)', name) @@ -1103,7 +1115,7 @@ def defaultPm(): packagedirs = os.environ['ONLPM_OPTION_PACKAGEDIRS'].split(':') repoPackageDir = os.environ.get('ONLPM_OPTION_REPO_PACKAGE_DIR', 'packages') subdir = os.getcwd() - arches = ['amd64', 'powerpc', 'armel', 'arm64', 'all',] + arches = ['amd64', 'powerpc', 'armel', 'armhf', 'arm64', 'all',] if envJson: for j in envJson.split(':'): @@ -1139,7 +1151,7 @@ if __name__ == '__main__': ap.add_argument("--csv", action='store_true') ap.add_argument("--show-group", action='store_true') ap.add_argument("--arch") - ap.add_argument("--arches", nargs='+', default=['amd64', 'powerpc', 'armel', 'arm64', 'all']), + ap.add_argument("--arches", nargs='+', default=['amd64', 'powerpc', 'armel', 'armhf', 'arm64', 'all']), ap.add_argument("--pmake", action='store_true') ap.add_argument("--prereq-packages", action='store_true') ap.add_argument("--lookup", metavar='PACKAGE') diff --git a/tools/onlrfs.py b/tools/onlrfs.py index 46749d3b..85c51b28 100755 --- a/tools/onlrfs.py +++ b/tools/onlrfs.py @@ -334,7 +334,7 @@ class OnlRfsBuilder(object): if not os.path.exists(self.QEMU_PPC): raise OnlRfsError("%s is missing." % self.QEMU_PPC) - if self.arch == 'armel': + if self.arch in [ 'armel', 'armhf' ]: if not os.path.exists(self.QEMU_ARM): raise OnlRfsError("%s is missing." % self.QEMU_ARM) @@ -378,7 +378,7 @@ class OnlRfsBuilder(object): def dpkg_configure(self, dir_): if self.arch == 'powerpc': onlu.execute('sudo cp %s %s' % (self.QEMU_PPC, os.path.join(dir_, 'usr/bin'))) - if self.arch == 'armel': + if self.arch in [ 'armel', 'armhf' ]: onlu.execute('sudo cp %s %s' % (self.QEMU_ARM, os.path.join(dir_, 'usr/bin'))) if self.arch == 'arm64': onlu.execute('sudo cp %s %s' % (self.QEMU_ARM64, os.path.join(dir_, 'usr/bin'))) diff --git a/tools/scripts/kmodbuild.sh b/tools/scripts/kmodbuild.sh index 94f258d8..d5586b70 100755 --- a/tools/scripts/kmodbuild.sh +++ b/tools/scripts/kmodbuild.sh @@ -38,6 +38,9 @@ function build_source { BUILD_DIR=`mktemp -d` cp $2 $BUILD_DIR + if [ -n "$4" ]; then + cp $4 $BUILD_DIR + fi src=$(basename $2) obj=${src%.c}.o echo "obj-m := $obj" >> $BUILD_DIR/Kbuild @@ -49,7 +52,7 @@ for kernel in $1; do if [ -d $module ]; then build_directory $kernel $module $3 else - build_source $kernel $module $3 + build_source $kernel $module $3 $4 fi done done